From: Kichan Kwon Date: Thu, 18 Jun 2020 06:47:20 +0000 (+0900) Subject: Integrate files into N files to reduce total file size X-Git-Tag: submit/tizen_3.0/20200702.060303~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a7567d74e90d69832f1c6147e3d7ea7e9d157a69;p=platform%2Fcore%2Fapi%2Fsystem-info.git Integrate files into N files to reduce total file size - Although the size of value is small, each key file takes a file block - Block size is 4kB - 270 model-config keys takes 1.5MB - To reduce file size, store many keys into the same file - To find file name, use hash function - In current, store 10 files Change-Id: I7140e732d7dde1e6c6ad65b28f5f7a064502d9f5 Signed-off-by: Kichan Kwon --- diff --git a/include/system_info_private.h b/include/system_info_private.h index 05cef6a..9ece2a0 100644 --- a/include/system_info_private.h +++ b/include/system_info_private.h @@ -45,6 +45,18 @@ extern "C" #define DBL_TYPE "double" #define STR_TYPE "string" +#define NUM_HASH_FILE 10 +static inline unsigned long simple_hash(char *str) +{ + unsigned long ret = 0; + int c; + + while ((c = *str++) != 0) + ret += c; + + return ret % NUM_HASH_FILE; +} + int system_info_get_file(const char *key, char *value, size_t len); int system_info_get_type_file(const char *key, system_info_type_e *type); diff --git a/src/init_db/system_info_db_init.c b/src/init_db/system_info_db_init.c index 2bcb7a2..623c2dd 100644 --- a/src/init_db/system_info_db_init.c +++ b/src/init_db/system_info_db_init.c @@ -54,48 +54,120 @@ static int db_set_value(const char *db_path, char *tag, char *name, char *type, char *value, int val_len) { int ret; + char key_internal[KEY_MAX]; + size_t key_internal_len; char file_path[PATH_MAX]; + char file_path_new[PATH_MAX * 2]; + char buf[PATH_MAX]; char *ptr; FILE *fp = NULL; + FILE *fp_new = NULL; + int key_idx; + int i; if (!db_path || !tag || !name || !type || !value) return -EINVAL; if (name == strstr(name, KEY_PREFIX)) - snprintf(file_path, sizeof(file_path), "%s/%s/%s:%s", db_path, tag, name + strlen(KEY_PREFIX), type); + snprintf(key_internal, sizeof(key_internal), "%s:%s:%s", tag, name + strlen(KEY_PREFIX), type); else - snprintf(file_path, sizeof(file_path), "%s/%s/%s:%s", db_path, tag, name, type); - - // Make directory recursively - for (ptr = file_path + 1; *ptr != '\0'; ptr++) { - if (*ptr == '/') { - *ptr = '\0'; - ret = mkdir(file_path, 0555); - if (ret != 0 && errno != EEXIST) { - _E("mkdir for %s failed (%d)", file_path, errno); - return -errno; - } - *ptr = '/'; - } - } + snprintf(key_internal, sizeof(key_internal), "%s:%s:%s", tag, name, type); + snprintf(file_path, sizeof(file_path), "%s/%lu", db_path, simple_hash(key_internal)); - fp = fopen(file_path, "w"); + fp = fopen(file_path, "r+"); if (!fp) { _E("fopen for %s failed (%d)", file_path, errno); return -errno; } - ret = fwrite(value, val_len, 1, fp); - fclose(fp); + key_internal_len = strlen(key_internal); + key_idx = 0; + while ((ptr = fgets(buf, sizeof(buf), fp))) { + if (!strncmp(buf, key_internal, key_internal_len) && buf[key_internal_len] == ' ') + break; + key_idx++; + } - if (ret < 1) { - _E("fwrite for %s failed", file_path); - return -errno; + // 1. Insert new value + if (!ptr) { + ret = fprintf(fp, "%s %s\n", key_internal, value); + fclose(fp); + + if (ret < 2) { + _E("fprintf for %s failed (%d)", file_path, errno); + return -errno; + } + + _I("DB: value (key:%s,value:%s) is stored", name, value); + return 0; } - _I("DB: value (key:%s,value:%s) is stored", name, value); + // 2. Make new file to update value + snprintf(file_path_new, sizeof(file_path_new), "%s_tmp", file_path); + fp_new = fopen(file_path_new, "w"); + if (!fp_new) { + _E("fopen for %s failed (%d)", file_path_new, errno); + ret = -errno; + goto clean; + } - return 0; + // 2-1. Copy prefix + rewind(fp); + for (i = 0; i < key_idx; i++) { + if (!fgets(buf, sizeof(buf), fp)) { + _E("fgets for %s failed", file_path); + ret = -EIO; + goto clean; + } + if (fputs(buf, fp_new) == EOF) { + _E("fputs for %s failed", file_path_new); + ret = -EIO; + goto clean; + } + } + + // 2-2. Insert new value + ret = fprintf(fp_new, "%s %s\n", key_internal, value); + if (ret < 2) { + _E("fprintf for %s failed (%d)", file_path_new, errno); + ret = -errno; + goto clean; + } + + // To move position indicator + if (!fgets(buf, sizeof(buf), fp)) { + _E("fgets for %s failed", file_path); + ret = -EIO; + goto clean; + } + + // 2-3. Copy suffix + while (fgets(buf, sizeof(buf), fp)) { + if (fputs(buf, fp_new) == EOF) { + _E("fputs for %s failed", file_path_new); + ret = -EIO; + goto clean; + } + } + + // 2-4. Overwrite file + ret = rename(file_path_new, file_path); + if (ret != 0) { + _E("rename for %s failed (%d)", file_path_new, errno); + ret = -errno; + goto clean; + } + + _I("DB: value (key:%s,value:%s) is updated", name, value); + ret = 0; + +clean: + if (fp_new) + fclose(fp_new); + if (fp) + fclose(fp); + + return ret; } static int system_info_get_values_config_xml(const char *db_path) @@ -230,6 +302,25 @@ static int system_info_get_values_ini(const char *db_path) static int system_info_create_db(void) { int ret; + char file_path[PATH_MAX]; + FILE *fp = NULL; + int i; + + ret = mkdir(SYSTEM_INFO_DB_PATH, 0555); + if (ret != 0 && errno != EEXIST) { + _E("mkdir for %s failed (%d)", SYSTEM_INFO_DB_PATH, errno); + return -errno; + } + + for (i = 0; i < NUM_HASH_FILE; i++) { + snprintf(file_path, sizeof(file_path), SYSTEM_INFO_DB_PATH"/%d", i); + fp = fopen(file_path, "w"); + if (!fp) { + _E("fopen for %s failed (%d)", file_path, errno); + return -errno; + } + fclose(fp); + } ret = system_info_get_values_config_xml(SYSTEM_INFO_DB_PATH); if (ret < 0) diff --git a/src/system_info.c b/src/system_info.c index f7b9801..821fe93 100644 --- a/src/system_info.c +++ b/src/system_info.c @@ -72,7 +72,8 @@ static int db_get_value(enum tag_type tag, const char *key, const char *type, char *value, size_t len) { char key_internal[KEY_MAX]; - char file_path[PATH_MAX]; + size_t key_internal_len; + char buf[PATH_MAX]; // buffer size should be larger than KEY_MAX FILE *fp = NULL; int ret; char *tag_s; @@ -93,9 +94,9 @@ static int db_get_value(enum tag_type tag, const char *key, } if (strstr(key, KEY_PREFIX) == key) - snprintf(key_internal, sizeof(key_internal), "%s/%s:%s", tag_s, key + strlen(KEY_PREFIX), type); + snprintf(key_internal, sizeof(key_internal), "%s:%s:%s", tag_s, key + strlen(KEY_PREFIX), type); else - snprintf(key_internal, sizeof(key_internal), "%s/%s:%s", tag_s, key, type); + snprintf(key_internal, sizeof(key_internal), "%s:%s:%s", tag_s, key, type); pthread_mutex_lock(&fmutex); if (!hashtable) { @@ -109,20 +110,27 @@ static int db_get_value(enum tag_type tag, const char *key, } } - snprintf(file_path, sizeof(file_path), "%s/%s", SYSTEM_INFO_DB_PATH, key_internal); - fp = fopen(file_path, "r"); + snprintf(buf, sizeof(buf), SYSTEM_INFO_DB_PATH"/%lu", simple_hash(key_internal)); + fp = fopen(buf, "r"); if (!fp) { if (errno == ENOENT) _D("Failed to find key in DB (%s, %s)", key, type); else - _E("fopen for %s failed (%d)", file_path, errno); //LCOV_EXCL_LINE + _E("fopen for %s failed (%d)", buf, errno); //LCOV_EXCL_LINE ret = SYSTEM_INFO_ERROR_IO_ERROR; //LCOV_EXCL_LINE goto out; } - temp = fgets(value, len, fp); + key_internal_len = strlen(key_internal); + while ((temp = fgets(buf, sizeof(buf), fp))) { + if (!strncmp(buf, key_internal, key_internal_len) && buf[key_internal_len] == ' ') { + sscanf(buf, "%*s %[^\n]s", value); + break; + } + } + if (!temp) { - _E("fgets for %s failed", file_path); + _D("Failed to find key in DB (%s)", key_internal); ret = SYSTEM_INFO_ERROR_IO_ERROR; goto out; }