| 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 | |
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;
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) {
#include <stdlib.h>
#include <string.h>
-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);
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++)
;
} 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;
}
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;
}
}
free(buf);
- __dw_unlockfile(db->fp);
+ __dw_unlockfile(db);
}
if(rm) return DW_ERR_SUCCESS;
return DW_ERR_NOT_USED;
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;
if(strcmp(name, dbname) == 0) {
free(dbname);
free(buf);
- __dw_unlockfile(db->fp);
+ __dw_unlockfile(db);
return DW_ERR_USED;
}
cnt++;
}
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);
}
}
free(buf);
- __dw_unlockfile(db->fp);
+ __dw_unlockfile(db);
dataworks_database_update_mtime(db);
}
return DW_ERR_SUCCESS;
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;
}
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;
}
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;
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;
}
/**
* @~english
- * @brief Database being used.
+ * @brief Table which is being used.
*
*/
char* name;
+
+ /**
+ * @~english
+ * @brief Locked or not.
+ *
+ */
+ bool locked;
};
/**
#include <stdio.h>
#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)
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;
}