From 0ff39c7b7950b12457ee1310850b4f5c232550f1 Mon Sep 17 00:00:00 2001 From: nishi Date: Mon, 27 May 2024 03:42:24 +0000 Subject: [PATCH] check lock git-svn-id: file:///raid/svn-main/nishi-dataworks/trunk@123 d4a5a174-5a4a-5b4b-b672-37683c10d7d5 --- FORMATv1.md | 2 +- Library/database.c | 25 +++++++++++++------------ Library/database_record.c | 29 +++++++++++++++++++++++++---- Library/database_table.c | 28 ++++++++++++++-------------- Library/dw_database.h | 9 ++++++++- Library/dw_util.h | 5 +++-- Library/util.c | 38 +++++++++++++++++++++++--------------- 7 files changed, 87 insertions(+), 49 deletions(-) diff --git a/FORMATv1.md b/FORMATv1.md index 485b91a..f1f97dc 100644 --- a/FORMATv1.md +++ b/FORMATv1.md @@ -17,7 +17,7 @@ Database entry (`dbentry`) MUST be in this format: | Name | Size | Type | Info | | ---- | ---- | ---- | ---- | | flag | 1 byte | uint8\_t | | -| length | 8 bytes | uint64\_t | Size of the entry | +| length | 8 bytes | uint64\_t | Size of the actual data inside | | size | 8 bytes | uint64\_t | | | field\_index | 1 byte | uint8\_t | | | db\_index | 1 byte | uint8\_t | | diff --git a/Library/database.c b/Library/database.c index 31e3980..5f77c7e 100644 --- a/Library/database.c +++ b/Library/database.c @@ -93,38 +93,39 @@ struct dataworks_db* dataworks_database_open(const char* fname) { db->error = false; db->fp = NULL; db->name = NULL; - FILE* fp = fopen(fname, "rb+"); - if(fp == NULL) { + db->locked = false; + db->fp = fopen(fname, "rb+"); + if(db->fp == NULL) { db->error = true; db->errnum = DW_ERR_FAIL_FOPEN; return db; } - fseek(fp, 0, SEEK_SET); + fseek(db->fp, 0, SEEK_SET); char readsig[sizeof(sig)]; - fread(readsig, 1, sizeof(sig), fp); + fread(readsig, 1, sizeof(sig), db->fp); if(memcmp(readsig, sig, sizeof(sig)) != 0) { db->error = true; db->errnum = DW_ERR_INVALID_SIGNATURE; return db; } - __dw_lockfile(fp); + __dw_lockfile(db); char ptrver[8]; - fread(ptrver, 1, 2, fp); + fread(ptrver, 1, 2, db->fp); uint16_t be_ver = *(uint16_t*)(char*)ptrver; uint16_t ver; __dw_native_endian(be_ver, uint16_t, ver = __converted); - fread(ptrver, 1, 8, fp); + fread(ptrver, 1, 8, db->fp); uint64_t be_mtime = *(uint64_t*)(char*)ptrver; uint64_t mtime; __dw_native_endian(be_mtime, uint64_t, mtime = __converted); - __dw_unlockfile(fp); + __dw_unlockfile(db); if(ver == 1) { - db->fp = fp; db->version = ver; db->mtime = mtime; return db; } else { - fclose(fp); + fclose(db->fp); + db->fp = NULL; db->error = true; db->errnum = DW_ERR_INVALID_VERSION; return db; @@ -140,11 +141,11 @@ int dataworks_database_get_error_number(struct dataworks_db* db) { return db->er const char* dataworks_database_strerror(int n) { return dw_errors[n]; } void dataworks_database_update_mtime(struct dataworks_db* db) { - __dw_lockfile(db->fp); + __dw_lockfile(db); fseek(db->fp, 3 + 2, SEEK_SET); int64_t t = time(NULL); __dw_big_endian(t, int64_t, fwrite(__converted_ptr, 1, 8, db->fp)); - __dw_unlockfile(db->fp); + __dw_unlockfile(db); } void dataworks_database_free(struct dataworks_db* db) { diff --git a/Library/database_record.c b/Library/database_record.c index f6e70e1..8937a52 100644 --- a/Library/database_record.c +++ b/Library/database_record.c @@ -36,9 +36,10 @@ #include #include -void __dw_add_record(struct dataworks_db* db, uint64_t index, void* _data, uint64_t size, bool set) { +void __dw_add_record(struct dataworks_db* db, uint64_t dbindex, uint64_t index, void* _data, uint64_t size, bool set) { uint8_t* data = _data; - __dw_lockfile(db->fp); + int fragnum = 0; + __dw_lockfile(db); if(db->version == 1) { char* buf = malloc(1 + 8 + 8 + 1 + 1 + 8 + 8); fseek(db->fp, 3 + 2 + 8 + (1 + 8 + 1 + 256 + 4096) * 256, SEEK_SET); @@ -50,19 +51,39 @@ void __dw_add_record(struct dataworks_db* db, uint64_t index, void* _data, uint6 if(!(dbentry.flag & DATAWORKS_V1_DBENTRY_USED)) { fseek(db->fp, -(1 + 8 + 8 + 1 + 1 + 8 + 8), SEEK_CUR); buf[0] |= DATAWORKS_V1_DBENTRY_USED; + if(dbentry.size <= size) { + if(dbentry.size < size) buf[0] |= DATAWORKS_V1_DBENTRY_FRAGMENT; + __dw_big_endian(dbentry.size, uint64_t, memcpy(buf + 1, __converted_ptr, 8)); + buf[1 + 8 + 8] = index; + buf[1 + 8 + 8 + 1] = dbindex; + __dw_big_endian(fragnum, uint64_t, memcpy(buf + 1 + 8 + 8 + 1 + 1 + 8, __converted_ptr, 8)); + fragnum++; + size -= dbentry.size; + } fwrite(buf, 1, 1 + 8 + 8 + 1 + 1 + 8 + 8, db->fp); } fseek(db->fp, dbentry.size, SEEK_CUR); } free(buf); } - __dw_unlockfile(db->fp); + __dw_unlockfile(db); } struct dataworks_db_result* dataworks_database_insert_record(struct dataworks_db* db, void** fields, const char* prop) { struct dataworks_db_result* r = malloc(sizeof(*r)); r->error = false; int i; + char** dbi = dataworks_database_get_table_list(db); + uint64_t dbindex; + bool set = false; + for(i = 0; dbi[i] != NULL; i++) { + if(!set && strcmp(dbi[i], db->name) == 0) { + dbindex = i; + set = true; + } + free(dbi[i]); + } + free(dbi); char* types = dataworks_database_get_table_field_types(db, db->name); for(i = 0; prop[i] != 0; i++) ; @@ -84,7 +105,7 @@ struct dataworks_db_result* dataworks_database_insert_record(struct dataworks_db } else if(types[i] == DW_RECORD_HELP) { entsize = strlen(fields[i]); } - __dw_add_record(db, i, fields[i], entsize, prop[i] == 'S'); + __dw_add_record(db, dbindex, i, fields[i], entsize, prop[i] == 'S'); } return r; } diff --git a/Library/database_table.c b/Library/database_table.c index 40ea3a7..390deda 100644 --- a/Library/database_table.c +++ b/Library/database_table.c @@ -37,7 +37,7 @@ int dataworks_database_delete_table(struct dataworks_db* db, const char* name) { bool rm = false; if(db->version == 1) { - __dw_lockfile(db->fp); + __dw_lockfile(db); fseek(db->fp, 3 + 10, SEEK_SET); int i; struct dataworks_db_v1_indexentry index; @@ -59,7 +59,7 @@ int dataworks_database_delete_table(struct dataworks_db* db, const char* name) { } } free(buf); - __dw_unlockfile(db->fp); + __dw_unlockfile(db); } if(rm) return DW_ERR_SUCCESS; return DW_ERR_NOT_USED; @@ -67,7 +67,7 @@ int dataworks_database_delete_table(struct dataworks_db* db, const char* name) { int dataworks_database_create_table(struct dataworks_db* db, const char* name, char** fields, const char* fieldtypes) { if(db->version == 1) { - __dw_lockfile(db->fp); + __dw_lockfile(db); fseek(db->fp, 3 + 10, SEEK_SET); int i; struct dataworks_db_v1_indexentry index; @@ -83,7 +83,7 @@ int dataworks_database_create_table(struct dataworks_db* db, const char* name, c if(strcmp(name, dbname) == 0) { free(dbname); free(buf); - __dw_unlockfile(db->fp); + __dw_unlockfile(db); return DW_ERR_USED; } cnt++; @@ -91,7 +91,7 @@ int dataworks_database_create_table(struct dataworks_db* db, const char* name, c } if(cnt == 256) { free(buf); - __dw_unlockfile(db->fp); + __dw_unlockfile(db); return DW_ERR_TOO_MANY_TABLES; } fseek(db->fp, 3 + 10, SEEK_SET); @@ -115,7 +115,7 @@ int dataworks_database_create_table(struct dataworks_db* db, const char* name, c } } free(buf); - __dw_unlockfile(db->fp); + __dw_unlockfile(db); dataworks_database_update_mtime(db); } return DW_ERR_SUCCESS; @@ -123,7 +123,7 @@ int dataworks_database_create_table(struct dataworks_db* db, const char* name, c char** dataworks_database_get_table_list(struct dataworks_db* db) { if(db->version == 1) { - __dw_lockfile(db->fp); + __dw_lockfile(db); fseek(db->fp, 3 + 10, SEEK_SET); int i; struct dataworks_db_v1_indexentry index; @@ -151,14 +151,14 @@ char** dataworks_database_get_table_list(struct dataworks_db* db) { } list[c] = NULL; free(buf); - __dw_unlockfile(db->fp); + __dw_unlockfile(db); return list; } } char** dataworks_database_get_table_fields(struct dataworks_db* db, const char* table) { if(db->version == 1) { - __dw_lockfile(db->fp); + __dw_lockfile(db); fseek(db->fp, 3 + 10, SEEK_SET); int i; struct dataworks_db_v1_indexentry index; @@ -197,21 +197,21 @@ char** dataworks_database_get_table_fields(struct dataworks_db* db, const char* } free(dbname); free(buf); - __dw_unlockfile(db->fp); + __dw_unlockfile(db); return list; } free(dbname); } } free(buf); - __dw_unlockfile(db->fp); + __dw_unlockfile(db); } return NULL; } char* dataworks_database_get_table_field_types(struct dataworks_db* db, const char* table) { if(db->version == 1) { - __dw_lockfile(db->fp); + __dw_lockfile(db); fseek(db->fp, 3 + 10, SEEK_SET); int i; struct dataworks_db_v1_indexentry index; @@ -245,14 +245,14 @@ char* dataworks_database_get_table_field_types(struct dataworks_db* db, const ch list[count] = 0; free(dbname); free(buf); - __dw_unlockfile(db->fp); + __dw_unlockfile(db); return list; } free(dbname); } } free(buf); - __dw_unlockfile(db->fp); + __dw_unlockfile(db); } return NULL; } diff --git a/Library/dw_database.h b/Library/dw_database.h index 8deab74..ec265e5 100644 --- a/Library/dw_database.h +++ b/Library/dw_database.h @@ -258,10 +258,17 @@ struct dataworks_db { /** * @~english - * @brief Database being used. + * @brief Table which is being used. * */ char* name; + + /** + * @~english + * @brief Locked or not. + * + */ + bool locked; }; /** diff --git a/Library/dw_util.h b/Library/dw_util.h index b40b24c..dade3b6 100644 --- a/Library/dw_util.h +++ b/Library/dw_util.h @@ -44,12 +44,13 @@ extern "C" { #include #include "dataworks.h" +#include "dw_database.h" char* __dw_strdup(const char* a); char* __dw_strcat(const char* a, const char* b); bool __dw_strcaseequ(const char* a, const char* b); -bool __dw_lockfile(FILE* fp); -bool __dw_unlockfile(FILE* fp); +bool __dw_lockfile(struct dataworks_db* db); +bool __dw_unlockfile(struct dataworks_db* db); #define __dw_xstr(x) #x #define __dw_str(x) __dw_xstr(x) diff --git a/Library/util.c b/Library/util.c index b9c488e..288f221 100644 --- a/Library/util.c +++ b/Library/util.c @@ -62,33 +62,41 @@ bool __dw_strcaseequ(const char* a, const char* b) { return true; } -bool __dw_lockfile(FILE* fp) { - off_t off = ftell(fp); - fseek(fp, 0, SEEK_SET); +bool __dw_lockfile(struct dataworks_db* db) { + if(db->locked) { + return true; + } + off_t off = ftell(db->fp); + fseek(db->fp, 0, SEEK_SET); #if defined(DOS) #elif defined(__MINGW32__) OVERLAPPED overlap = {0}; - LockFileEx(fp, LOCKFILE_EXCLUSIVE_LOCK, 0, MAXDWORD, MAXDWORD, &overlap); + LockFileEx(db->fp, LOCKFILE_EXCLUSIVE_LOCK, 0, MAXDWORD, MAXDWORD, &overlap); #else - lockf(fileno(fp), F_LOCK, 0); + lockf(fileno(db->fp), F_LOCK, 0); #endif - fseek(fp, off, SEEK_SET); - return false; + fseek(db->fp, off, SEEK_SET); + db->locked = true; + return true; } -bool __dw_unlockfile(FILE* fp) { - off_t off = ftell(fp); - fseek(fp, 0, SEEK_SET); - fflush(fp); +bool __dw_unlockfile(struct dataworks_db* db) { + if(!db->locked) { + return true; + } + off_t off = ftell(db->fp); + fseek(db->fp, 0, SEEK_SET); + fflush(db->fp); #if defined(DOS) #elif defined(__MINGW32__) OVERLAPPED overlap = {0}; - UnlockFileEx(fp, 0, MAXDWORD, MAXDWORD, &overlap); + UnlockFileEx(db->fp, 0, MAXDWORD, MAXDWORD, &overlap); #else - lockf(fileno(fp), F_ULOCK, 0); + lockf(fileno(db->fp), F_ULOCK, 0); #endif - fseek(fp, off, SEEK_SET); - return false; + fseek(db->fp, off, SEEK_SET); + db->locked = false; + return true; } -- 2.43.0