diff --git a/.gitignore b/.gitignore index 6567fad..3b96d13 100644 --- a/.gitignore +++ b/.gitignore @@ -50,6 +50,7 @@ src/tests/test_uniq_skiplist src/tests/test_server_id_func src/tests/test_pipe src/tests/test_atomic +src/tests/test_file_write_hole # other *.swp diff --git a/HISTORY b/HISTORY index b9e5e66..20ebb69 100644 --- a/HISTORY +++ b/HISTORY @@ -1,5 +1,5 @@ -Version 1.44 2020-05-06 +Version 1.44 2020-05-07 * add test file src/tests/test_pthread_lock.c * add uniq_skiplist.[hc] * add function split_string_ex @@ -28,6 +28,7 @@ Version 1.44 2020-05-06 * uniq_skiplist add function find_ge and support bidirection * connection_pool support validate connection on error * fast_task_queue.[hc]: free_queue support init_callback + * ini_file_reader.c: use mutex lock when access dynamic content array Version 1.43 2019-12-25 * replace function call system to getExecResult, diff --git a/src/ini_file_reader.c b/src/ini_file_reader.c index b5c614a..bdd6fd3 100644 --- a/src/ini_file_reader.c +++ b/src/ini_file_reader.c @@ -19,6 +19,7 @@ #include "logger.h" #include "http_func.h" #include "local_ip_func.h" +#include "pthread_func.h" #include "ini_file_reader.h" #define _LINE_BUFFER_SIZE 512 @@ -53,15 +54,15 @@ #define _PREPROCESS_TAG_STR_FOR_STEP "step" #define _PREPROCESS_TAG_LEN_FOR_STEP (sizeof(_PREPROCESS_TAG_STR_FOR_STEP) - 1) -#define _MAX_DYNAMIC_CONTENTS 8 -#define _BUILTIN_ANNOTATION_COUNT 3 +#define _INIT_DYNAMIC_CONTENTS 8 +#define _BUILTIN_ANNOTATION_COUNT 3 static AnnotationEntry *g_annotations = NULL; static int g_annotation_count = 0; typedef struct { int count; - int alloc_count; + int alloc; char **contents; } DynamicContents; @@ -72,7 +73,7 @@ typedef struct { typedef struct { int count; - int alloc_count; + int alloc; AnnotationEntry *annotations; } DynamicAnnotations; @@ -84,11 +85,17 @@ typedef struct { DynamicAnnotations dynamicAnnotations; } CDCPair; +typedef struct { + volatile int init_counter; + int alloc; + int count; + int index; + CDCPair *contents; + pthread_mutex_t lock; +} DynamicContentArray; + //dynamic alloced contents which will be freed when destroy -static int g_dynamic_content_count = 0; -static int g_dynamic_content_index = 0; -static CDCPair g_dynamic_contents[_MAX_DYNAMIC_CONTENTS] = {{false, NULL, - {0, 0, NULL}, {0, NULL}, {0, 0, NULL}}}; +static DynamicContentArray g_dynamic_content_array = {0, 0, 0, 0, NULL}; static int remallocSection(IniSection *pSection, IniItem **pItem); static int iniDoLoadFromFile(const char *szFilename, \ @@ -1194,7 +1201,7 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext) nValueLen = FAST_INI_ITEM_VALUE_LEN; } - if (pSection->count >= pSection->alloc_count) + if (pSection->count >= pSection->alloc) { result = remallocSection(pSection, &pItem); if (result != 0) @@ -1300,7 +1307,7 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext) pItem->value[nValueLen] = '\0'; pSection->count++; pItem++; - if (pSection->count >= pSection->alloc_count) + if (pSection->count >= pSection->alloc) { result = remallocSection(pSection, &pItem); if (result != 0) @@ -1331,27 +1338,96 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext) return result; } +static inline int checkInitDynamicContentArray() +{ + if (__sync_fetch_and_add(&g_dynamic_content_array.init_counter, 1) != 0) + { + return 0; + } + + logInfo("file: "__FILE__", line: %d, func: %s, " + "init_pthread_lock", __LINE__, __FUNCTION__); + return init_pthread_lock(&g_dynamic_content_array.lock); +} + +static int checkAllocDynamicContentArray() +{ + CDCPair *contents; + int alloc; + int bytes; + + if (g_dynamic_content_array.alloc > g_dynamic_content_array.count) + { + return 0; + } + + alloc = (g_dynamic_content_array.alloc == 0) ? _INIT_DYNAMIC_CONTENTS : + g_dynamic_content_array.alloc * 2; + bytes = sizeof(CDCPair) * alloc; + contents = (CDCPair *)malloc(bytes); + if (contents == NULL) + { + logError("file: "__FILE__", line: %d, " + "malloc %d bytes fail", __LINE__, bytes); + return ENOMEM; + } + memset(contents, 0, bytes); + + if (g_dynamic_content_array.alloc > 0) + { + memcpy(contents, g_dynamic_content_array.contents, + sizeof(CDCPair) * g_dynamic_content_array.alloc); + free(g_dynamic_content_array.contents); + } + + logInfo("file: "__FILE__", line: %d, func: %s, " + "alloc count: %d", __LINE__, __FUNCTION__, alloc); + + g_dynamic_content_array.contents = contents; + g_dynamic_content_array.alloc = alloc; + return 0; +} + static CDCPair *iniGetCDCPair(IniContext *pContext) { int i; - if (g_dynamic_contents[g_dynamic_content_index].context == pContext) + CDCPair *pair; + + if (checkInitDynamicContentArray() != 0) { - return g_dynamic_contents + g_dynamic_content_index; + return NULL; } - if (g_dynamic_content_count > 0) + pthread_mutex_lock(&g_dynamic_content_array.lock); + if (g_dynamic_content_array.contents == NULL) { - for (i=0; i<_MAX_DYNAMIC_CONTENTS; i++) + pair = NULL; + } + else if (g_dynamic_content_array.contents[g_dynamic_content_array.index]. + context == pContext) + { + pair = g_dynamic_content_array.contents + g_dynamic_content_array.index; + } + else + { + pair = NULL; + if (g_dynamic_content_array.count > 0) { - if (g_dynamic_contents[i].context == pContext) + for (i=0; idynamicContents; - if (pDynamicContents->contents != NULL) - { - for (i=0; icount; i++) + pDynamicContents = &pCDCPair->dynamicContents; + if (pDynamicContents->contents != NULL) { - if (pDynamicContents->contents[i] != NULL) + for (i=0; icount; i++) { - free(pDynamicContents->contents[i]); + if (pDynamicContents->contents[i] != NULL) + { + free(pDynamicContents->contents[i]); + } } + free(pDynamicContents->contents); + pDynamicContents->contents = NULL; + pDynamicContents->alloc = 0; + pDynamicContents->count = 0; } - free(pDynamicContents->contents); - pDynamicContents->contents = NULL; - pDynamicContents->alloc_count = 0; - pDynamicContents->count = 0; - } - pDynamicAnnotations = &pCDCPair->dynamicAnnotations; - if (pDynamicAnnotations->annotations != NULL) - { - free(pDynamicAnnotations->annotations); - pDynamicAnnotations->annotations = NULL; - pDynamicAnnotations->alloc_count = 0; - pDynamicAnnotations->count = 0; - } + pDynamicAnnotations = &pCDCPair->dynamicAnnotations; + if (pDynamicAnnotations->annotations != NULL) + { + free(pDynamicAnnotations->annotations); + pDynamicAnnotations->annotations = NULL; + pDynamicAnnotations->alloc = 0; + pDynamicAnnotations->count = 0; + } - pCDCPair->used = false; - pCDCPair->context = NULL; - g_dynamic_content_count--; + pCDCPair->used = false; + pCDCPair->context = NULL; + g_dynamic_content_array.count--; + } while (0); + + pthread_mutex_unlock(&g_dynamic_content_array.lock); } static char *iniAllocContent(IniContext *pContext, const int content_len) @@ -1542,20 +1637,20 @@ static char *iniAllocContent(IniContext *pContext, const int content_len) "malloc dynamic contents fail", __LINE__); return NULL; } - if (pDynamicContents->count >= pDynamicContents->alloc_count) + if (pDynamicContents->count >= pDynamicContents->alloc) { - int alloc_count; + int alloc; int bytes; char **contents; - if (pDynamicContents->alloc_count == 0) + if (pDynamicContents->alloc == 0) { - alloc_count = 8; + alloc = 8; } else { - alloc_count = pDynamicContents->alloc_count * 2; + alloc = pDynamicContents->alloc * 2; } - bytes = sizeof(char *) * alloc_count; + bytes = sizeof(char *) * alloc; contents = (char **)malloc(bytes); if (contents == NULL) { @@ -1571,7 +1666,7 @@ static char *iniAllocContent(IniContext *pContext, const int content_len) free(pDynamicContents->contents); } pDynamicContents->contents = contents; - pDynamicContents->alloc_count = alloc_count; + pDynamicContents->alloc = alloc; } buff = malloc(content_len); @@ -1588,29 +1683,29 @@ static char *iniAllocContent(IniContext *pContext, const int content_len) static int iniCheckAllocAnnotations(DynamicAnnotations *pDynamicAnnotations, const int annotation_count) { - int alloc_count; + int alloc; int bytes; AnnotationEntry *annotations; if (pDynamicAnnotations->count + annotation_count < - pDynamicAnnotations->alloc_count) + pDynamicAnnotations->alloc) { return 0; } - if (pDynamicAnnotations->alloc_count == 0) + if (pDynamicAnnotations->alloc == 0) { - alloc_count = 8; + alloc = 8; } else { - alloc_count = pDynamicAnnotations->alloc_count * 2; + alloc = pDynamicAnnotations->alloc * 2; } - while (alloc_count <= pDynamicAnnotations->count + annotation_count) + while (alloc <= pDynamicAnnotations->count + annotation_count) { - alloc_count *= 2; + alloc *= 2; } - bytes = sizeof(AnnotationEntry) * alloc_count; + bytes = sizeof(AnnotationEntry) * alloc; annotations = (AnnotationEntry *)malloc(bytes); if (annotations == NULL) { @@ -1626,7 +1721,7 @@ static int iniCheckAllocAnnotations(DynamicAnnotations *pDynamicAnnotations, free(pDynamicAnnotations->annotations); } pDynamicAnnotations->annotations = annotations; - pDynamicAnnotations->alloc_count = alloc_count; + pDynamicAnnotations->alloc = alloc; return 0; } @@ -2630,18 +2725,18 @@ static int remallocSection(IniSection *pSection, IniItem **pItem) { int bytes; int result; - int alloc_count; + int alloc; IniItem *pNew; - if (pSection->alloc_count == 0) + if (pSection->alloc == 0) { - alloc_count = _INIT_ALLOC_ITEM_COUNT; + alloc = _INIT_ALLOC_ITEM_COUNT; } else { - alloc_count = pSection->alloc_count * 2; + alloc = pSection->alloc * 2; } - bytes = sizeof(IniItem) * alloc_count; + bytes = sizeof(IniItem) * alloc; pNew = (IniItem *)malloc(bytes); if (pNew == NULL) { @@ -2658,11 +2753,11 @@ static int remallocSection(IniSection *pSection, IniItem **pItem) free(pSection->items); } - pSection->alloc_count = alloc_count; + pSection->alloc = alloc; pSection->items = pNew; *pItem = pSection->items + pSection->count; memset(*pItem, 0, sizeof(IniItem) * - (pSection->alloc_count - pSection->count)); + (pSection->alloc - pSection->count)); return 0; } diff --git a/src/ini_file_reader.h b/src/ini_file_reader.h index 14d9f81..9d161fb 100644 --- a/src/ini_file_reader.h +++ b/src/ini_file_reader.h @@ -43,7 +43,7 @@ typedef struct ini_section { IniItem *items; int count; //item count - int alloc_count; + int alloc; } IniSection; typedef struct ini_section_info