Update logic for OS filesystem timestamps for caching.

PiperOrigin-RevId: 616138153
Change-Id: I0ce966546bc4af04e57b983e27bbd75a94377237
This commit is contained in:
Kyle Bayes
2024-03-15 08:29:39 -07:00
committed by Copybara-Service
parent a23cb4d22c
commit c42868a91b
2 changed files with 47 additions and 17 deletions
+14 -17
View File
@@ -34,6 +34,7 @@
#include <mujoco/mjplugin.h>
#include "engine/engine_plugin.h"
#include "engine/engine_util_errmem.h"
#include "engine/engine_util_misc.h"
// internal helper for mju_fileToMemory (closes fp automatically)
static void* _fileToMemory(FILE* fp, const char* filename, size_t* filesize);
@@ -113,10 +114,8 @@ mjResource* mju_openResource(const char* name, char* error, size_t error_sz) {
memcpy(&spec->mtime, &file_stat.st_mtime, sizeof(time_t));
} else {
memset(&spec->mtime, 0, sizeof(time_t));
resource->timestamp[0] = '\0';
}
strftime(resource->timestamp, 512, "%Y-%m-%d-%H:%M:%S",
localtime(&(spec->mtime)));
mju_encodeBase64(resource->timestamp, (uint8_t*) &spec->mtime, sizeof(time_t));
return resource;
}
@@ -199,19 +198,6 @@ void mju_getResourceDir(mjResource* resource, const char** dir, int* ndir) {
// modified callback for OS filesystem
static int mju_isModifiedFile(const char* name, const file_spec* spec) {
if (spec != NULL) {
struct stat file_stat;
if (stat(name, &file_stat) == 0) {
return difftime(spec->mtime, file_stat.st_mtime) < 0;
}
}
return 1; // modified (default)
}
// return 0 if the resource's timestamp matches the provided timestamp
// return > 0 if the the resource is younger than the given timestamp
// return < 0 if the resource is older than the given timestamp
@@ -224,7 +210,18 @@ int mju_isModifiedResource(const mjResource* resource, const char* timestamp) {
return 1; // default (modified)
}
return mju_isModifiedFile(resource->name, (file_spec*) resource->data);
// fallback to OS filesystem
if (mju_isValidBase64(timestamp) != sizeof(time_t)) {
return 1; // error (assume modified)
}
time_t time1, time2;
mju_decodeBase64((uint8_t*) &time1, timestamp);
time2 = ((file_spec*) resource->data)->mtime;
double diff = difftime(time2, time1);
if (diff < 0) return -1;
if (diff > 0) return 1;
return 0;
}
+33
View File
@@ -15,7 +15,10 @@
// Tests for engine/engine_resource.c
#include <array>
#include <cstdint>
#include <cstring>
#include <ctime>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
@@ -24,6 +27,7 @@
#include <mujoco/mujoco.h>
#include "src/engine/engine_plugin.h"
#include "src/engine/engine_resource.h"
#include "src/engine/engine_util_misc.h"
#include "test/fixture.h"
namespace mujoco {
@@ -327,5 +331,34 @@ TEST_F(ResourceTest, NameWithInvalidPrefix) {
ASSERT_THAT(resource, IsNull());
}
TEST_F(ResourceTest, OSFilesystemTimestamps) {
time_t t;
// some random file
const char* const file = "engine/testdata/collision_box/boxbox_deep.xml";
const std::string xml_path = GetTestDataFilePath(file);
mjResource* resource = mju_openResource(xml_path.c_str(), nullptr, 0);
mju_decodeBase64((uint8_t*) &t, resource->timestamp);
// equal timestamps
EXPECT_EQ(mju_isModifiedResource(resource, resource->timestamp), 0);
std::array<char, 512> test_timestamp;
// older resource timestamp
t++;
mju_encodeBase64(test_timestamp.data(), (uint8_t*) &t, sizeof(time_t));
EXPECT_EQ(mju_isModifiedResource(resource, test_timestamp.data()), -1);
// newer resource timestamp
t -= 2;
mju_encodeBase64(test_timestamp.data(), (uint8_t*) &t, sizeof(time_t));
EXPECT_EQ(mju_isModifiedResource(resource, test_timestamp.data()), 1);
mju_closeResource(resource);
}
} // namespace
} // namespace mujoco