Scripting: Add flushing/reloading

This commit is contained in:
Vicki Pfau 2023-02-05 21:01:11 -08:00
parent 91474e179c
commit 63d96ab712
3 changed files with 114 additions and 40 deletions

View File

@ -15,6 +15,7 @@ CXX_GUARD_START
struct VFile;
void mScriptContextAttachStorage(struct mScriptContext* context);
void mScriptStorageFlushAll(struct mScriptContext* context);
bool mScriptStorageSaveBucket(struct mScriptContext* context, const char* bucket);
bool mScriptStorageSaveBucketVF(struct mScriptContext* context, const char* bucket, struct VFile* vf);

View File

@ -24,15 +24,18 @@ struct mScriptStorageContext {
};
void mScriptStorageBucketDeinit(void*);
struct mScriptValue* mScriptStorageBucketGet(struct mScriptStorageBucket* adapter, const char* key);
static void mScriptStorageBucketSet(struct mScriptStorageBucket* adapter, const char* key, struct mScriptValue* value);
static void mScriptStorageBucketSetVoid(struct mScriptStorageBucket* adapter, const char* key, struct mScriptValue* value);
static void mScriptStorageBucketSetSInt(struct mScriptStorageBucket* adapter, const char* key, int64_t value);
static void mScriptStorageBucketSetUInt(struct mScriptStorageBucket* adapter, const char* key, uint64_t value);
static void mScriptStorageBucketSetFloat(struct mScriptStorageBucket* adapter, const char* key, double value);
static void mScriptStorageBucketSetBool(struct mScriptStorageBucket* adapter, const char* key, bool value);
struct mScriptValue* mScriptStorageBucketGet(struct mScriptStorageBucket* bucket, const char* key);
static void mScriptStorageBucketSet(struct mScriptStorageBucket* bucket, const char* key, struct mScriptValue* value);
static void mScriptStorageBucketSetVoid(struct mScriptStorageBucket* bucket, const char* key, struct mScriptValue* value);
static void mScriptStorageBucketSetSInt(struct mScriptStorageBucket* bucket, const char* key, int64_t value);
static void mScriptStorageBucketSetUInt(struct mScriptStorageBucket* bucket, const char* key, uint64_t value);
static void mScriptStorageBucketSetFloat(struct mScriptStorageBucket* bucket, const char* key, double value);
static void mScriptStorageBucketSetBool(struct mScriptStorageBucket* bucket, const char* key, bool value);
static bool mScriptStorageBucketReload(struct mScriptStorageBucket* bucket);
static bool mScriptStorageBucketFlush(struct mScriptStorageBucket* bucket);
void mScriptStorageContextDeinit(struct mScriptStorageContext*);
static void mScriptStorageContextDeinit(struct mScriptStorageContext*);
static void mScriptStorageContextFlushAll(struct mScriptStorageContext*);
struct mScriptStorageBucket* mScriptStorageGetBucket(struct mScriptStorageContext*, const char* name);
static bool mScriptStorageToJson(struct mScriptValue* value, struct json_object** out);
@ -48,6 +51,8 @@ mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptStorageBucket, setStr, mScriptStorageB
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptStorageBucket, setList, mScriptStorageBucketSet, 2, CHARP, key, WLIST, value);
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptStorageBucket, setTable, mScriptStorageBucketSet, 2, CHARP, key, WTABLE, value);
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptStorageBucket, setVoid, mScriptStorageBucketSetVoid, 2, CHARP, key, NUL, value);
mSCRIPT_DECLARE_STRUCT_METHOD(mScriptStorageBucket, BOOL, reload, mScriptStorageBucketReload, 0);
mSCRIPT_DECLARE_STRUCT_METHOD(mScriptStorageBucket, BOOL, flush, mScriptStorageBucketFlush, 0);
mSCRIPT_DEFINE_STRUCT(mScriptStorageBucket)
mSCRIPT_DEFINE_STRUCT_DEFAULT_SET(mScriptStorageBucket, setSInt)
@ -59,15 +64,19 @@ mSCRIPT_DEFINE_STRUCT(mScriptStorageBucket)
mSCRIPT_DEFINE_STRUCT_DEFAULT_SET(mScriptStorageBucket, setTable)
mSCRIPT_DEFINE_STRUCT_DEFAULT_SET(mScriptStorageBucket, setVoid)
mSCRIPT_DEFINE_STRUCT_DEFAULT_GET(mScriptStorageBucket)
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptStorageBucket, reload)
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptStorageBucket, flush)
mSCRIPT_DEFINE_END;
mSCRIPT_DECLARE_STRUCT(mScriptStorageContext);
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptStorageContext, _deinit, mScriptStorageContextDeinit, 0);
mSCRIPT_DECLARE_STRUCT_METHOD(mScriptStorageContext, S(mScriptStorageBucket), getBucket, mScriptStorageGetBucket, 1, CHARP, key);
mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptStorageContext, flushAll, mScriptStorageContextFlushAll, 0);
mSCRIPT_DEFINE_STRUCT(mScriptStorageContext)
mSCRIPT_DEFINE_STRUCT_DEINIT(mScriptStorageContext)
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptStorageContext, getBucket)
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptStorageContext, flushAll)
mSCRIPT_DEFINE_END;
struct mScriptValue* mScriptStorageBucketGet(struct mScriptStorageBucket* bucket, const char* key) {
@ -218,14 +227,7 @@ bool mScriptStorageToJson(struct mScriptValue* value, struct json_object** out)
return ok;
}
bool mScriptStorageSaveBucketVF(struct mScriptContext* context, const char* bucketName, struct VFile* vf) {
struct mScriptValue* value = mScriptContextGetGlobal(context, "storage");
if (!value) {
vf->close(vf);
return false;
}
struct mScriptStorageContext* storage = value->value.opaque;
struct mScriptStorageBucket* bucket = mScriptStorageGetBucket(storage, bucketName);
static bool _mScriptStorageBucketFlushVF(struct mScriptStorageBucket* bucket, struct VFile* vf) {
struct json_object* rootObj;
bool ok = mScriptStorageToJson(bucket->root, &rootObj);
if (!ok) {
@ -249,6 +251,24 @@ bool mScriptStorageSaveBucketVF(struct mScriptContext* context, const char* buck
return true;
}
bool mScriptStorageBucketFlush(struct mScriptStorageBucket* bucket) {
char path[PATH_MAX];
mScriptStorageGetBucketPath(bucket->name, path);
struct VFile* vf = VFileOpen(path, O_WRONLY | O_CREAT | O_TRUNC);
return _mScriptStorageBucketFlushVF(bucket, vf);
}
bool mScriptStorageSaveBucketVF(struct mScriptContext* context, const char* bucketName, struct VFile* vf) {
struct mScriptValue* value = mScriptContextGetGlobal(context, "storage");
if (!value) {
vf->close(vf);
return false;
}
struct mScriptStorageContext* storage = value->value.opaque;
struct mScriptStorageBucket* bucket = mScriptStorageGetBucket(storage, bucketName);
return _mScriptStorageBucketFlushVF(bucket, vf);
}
bool mScriptStorageSaveBucket(struct mScriptContext* context, const char* bucketName) {
char path[PATH_MAX];
mScriptStorageGetBucketPath(bucketName, path);
@ -314,6 +334,51 @@ struct mScriptValue* mScriptStorageFromJson(struct json_object* json) {
return value;
}
static struct mScriptValue* _mScriptStorageLoadJson(struct VFile* vf) {
ssize_t size = vf->size(vf);
if (size < 2) {
vf->close(vf);
return NULL;
}
char* json = calloc(1, size + 1);
if (vf->read(vf, json, size) != size) {
vf->close(vf);
return NULL;
}
vf->close(vf);
struct json_object* obj = json_tokener_parse(json);
free(json);
if (!obj) {
return NULL;
}
struct mScriptValue* root = mScriptStorageFromJson(obj);
json_object_put(obj);
return root;
}
bool mScriptStorageBucketReload(struct mScriptStorageBucket* bucket) {
char path[PATH_MAX];
mScriptStorageGetBucketPath(bucket->name, path);
struct VFile* vf = VFileOpen(path, O_RDONLY);
if (!vf) {
return false;
}
struct mScriptValue* root = _mScriptStorageLoadJson(vf);
if (!root) {
return false;
}
if (bucket->root) {
mScriptValueDeref(bucket->root);
}
bucket->root = root;
bucket->dirty = false;
return true;
}
bool mScriptStorageLoadBucketVF(struct mScriptContext* context, const char* bucketName, struct VFile* vf) {
struct mScriptValue* value = mScriptContextGetGlobal(context, "storage");
if (!value) {
@ -321,35 +386,16 @@ bool mScriptStorageLoadBucketVF(struct mScriptContext* context, const char* buck
return false;
}
struct mScriptStorageContext* storage = value->value.opaque;
ssize_t size = vf->size(vf);
if (size < 2) {
vf->close(vf);
return false;
}
char* json = calloc(1, size + 1);
if (vf->read(vf, json, size) != size) {
vf->close(vf);
return false;
}
vf->close(vf);
struct json_object* obj = json_tokener_parse(json);
free(json);
if (!obj) {
return false;
}
struct mScriptValue* root = mScriptStorageFromJson(obj);
json_object_put(obj);
struct mScriptValue* root = _mScriptStorageLoadJson(vf);
if (!root) {
return false;
}
struct mScriptStorageBucket* bucket = mScriptStorageGetBucket(storage, bucketName);
mScriptValueDeref(bucket->root);
bucket->root = root;
bucket->dirty = false;
return true;
}
@ -375,10 +421,29 @@ void mScriptContextAttachStorage(struct mScriptContext* context) {
mScriptContextSetDocstring(context, "storage", "Singleton instance of struct::mScriptStorageContext");
}
void mScriptStorageFlushAll(struct mScriptContext* context) {
struct mScriptValue* value = mScriptContextGetGlobal(context, "storage");
if (!value) {
return;
}
struct mScriptStorageContext* storage = value->value.opaque;
mScriptStorageContextFlushAll(storage);
}
void mScriptStorageContextDeinit(struct mScriptStorageContext* storage) {
HashTableDeinit(&storage->buckets);
}
void mScriptStorageContextFlushAll(struct mScriptStorageContext* storage) {
struct TableIterator iter;
if (HashTableIteratorStart(&storage->buckets, &iter)) {
do {
struct mScriptStorageBucket* bucket = HashTableIteratorGetValue(&storage->buckets, &iter);
mScriptStorageBucketFlush(bucket);
} while (HashTableIteratorNext(&storage->buckets, &iter));
}
}
struct mScriptStorageBucket* mScriptStorageGetBucket(struct mScriptStorageContext* storage, const char* name) {
if (!name) {
return NULL;
@ -401,14 +466,19 @@ struct mScriptStorageBucket* mScriptStorageGetBucket(struct mScriptStorageContex
}
bucket = calloc(1, sizeof(*bucket));
bucket->root = mScriptValueAlloc(mSCRIPT_TYPE_MS_TABLE);
bucket->name = strdup(name);
if (!mScriptStorageBucketReload(bucket)) {
bucket->root = mScriptValueAlloc(mSCRIPT_TYPE_MS_TABLE);
}
HashTableInsert(&storage->buckets, name, bucket);
return bucket;
}
void mScriptStorageBucketDeinit(void* data) {
struct mScriptStorageBucket* bucket = data;
if (bucket->dirty) {
mScriptStorageBucketFlush(bucket);
}
mScriptValueDeref(bucket->root);
free(bucket->name);
free(bucket);

View File

@ -16,7 +16,10 @@
mScriptContextInit(&context); \
struct mScriptEngineContext* lua = mScriptContextRegisterEngine(&context, mSCRIPT_ENGINE_LUA); \
mScriptContextAttachStdlib(&context); \
mScriptContextAttachStorage(&context)
mScriptContextAttachStorage(&context); \
char bucketPath[PATH_MAX]; \
mScriptStorageGetBucketPath("xtest", bucketPath); \
remove(bucketPath)
M_TEST_SUITE_SETUP(mScriptStorage) {
if (mSCRIPT_ENGINE_LUA->init) {