diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/core.c | 31 | ||||
-rw-r--r-- | src/common/db.c | 106 | ||||
-rw-r--r-- | src/common/db.h | 12 |
3 files changed, 132 insertions, 17 deletions
diff --git a/src/common/core.c b/src/common/core.c index 016ade08d..a30445650 100644 --- a/src/common/core.c +++ b/src/common/core.c @@ -76,6 +76,11 @@ sigfunc *compat_signal(int signo, sigfunc *func) static void sig_proc(int sn) { int i; + static int is_called = 0; + + if(is_called++) + return; + switch(sn){ case SIGINT: case SIGTERM: @@ -196,11 +201,37 @@ static void display_title(void) */ int runflag = 1; +char pid_file[256]; + +void pid_delete(void) { + unlink(pid_file); +} + +void pid_create(const char* file) { + FILE *fp; + int len = strlen(file); + strcpy(pid_file,file); + if(len > 4 && pid_file[len - 4] == '.') { + pid_file[len - 4] = 0; + } + strcat(pid_file,".pid"); + fp = fopen(pid_file,"w"); + if(fp) { +#ifdef _WIN32 + fprintf(fp,"%d",GetCurrentProcessId()); +#else + fprintf(fp,"%d",getpid()); +#endif + fclose(fp); + atexit(pid_delete); + } +} int main(int argc,char **argv) { int next; + pid_create(argv[0]); Net_Init(); do_socket(); diff --git a/src/common/db.c b/src/common/db.c index 9f2c75a68..5eb73c785 100644 --- a/src/common/db.c +++ b/src/common/db.c @@ -354,6 +354,29 @@ static void db_rebalance_erase(struct dbn *z,struct dbn **root) } } +void db_free_lock(struct dbt *table) { + table->free_lock++; +} + +void db_free_unlock(struct dbt *table) { + if(--table->free_lock == 0) { + int i; + for(i = 0; i < table->free_count ; i++) { + db_rebalance_erase(table->free_list[i].z,table->free_list[i].root); + if(table->cmp == strdb_cmp) { + free(table->free_list[i].z->key); + } +#ifdef MALLOC_DBN + free_dbn(table->free_list[i].z); +#else + free(table->free_list[i].z); +#endif + table->item_count--; + } + table->free_count = 0; + } +} + struct dbn* db_insert(struct dbt *table,void* key,void* data) { struct dbn *p,*priv; @@ -363,10 +386,33 @@ struct dbn* db_insert(struct dbt *table,void* key,void* data) for(c=0,priv=NULL ,p = table->ht[hash];p;){ c=table->cmp(table,key,p->key); if(c==0){ // replace - if (table->release) - table->release(p, 3); + if (table->release) + table->release(p, 3); + if(p->deleted) { + // 削除されたデータなので、free_list 上の削除予定を消す + int i; + for(i = 0; i < table->free_count ; i++) { + if(table->free_list[i].z == p) { + memmove( + &table->free_list[i], + &table->free_list[i+1], + sizeof(struct db_free)*(table->free_count - i - 1) + ); + break; + } + } + if(i == table->free_count || table->free_count <= 0) { + printf("db_insert: cannnot find deleted db node.\n"); + } else { + table->free_count--; + if(table->cmp == strdb_cmp) { + free(p->key); + } + } + } p->data=data; p->key=key; + p->deleted = 0; return p; } priv=p; @@ -391,6 +437,7 @@ struct dbn* db_insert(struct dbt *table,void* key,void* data) p->key = key; p->data = data; p->color = RED; + p->deleted = 0; if(c==0){ // hash entry is empty table->ht[hash] = p; p->color = BLACK; @@ -429,25 +476,47 @@ void* db_erase(struct dbt *table,void* key) if(!p) return NULL; data=p->data; - db_rebalance_erase(p,&table->ht[hash]); -#ifdef MALLOC_DBN - free_dbn(p); -#else - aFree(p); -#endif - table->item_count--; + if(table->free_lock) { + if(table->free_count == table->free_max) { + table->free_max += 32; + table->free_list = (struct db_free*)realloc(table->free_list,sizeof(struct db_free) * table->free_max); + } + table->free_list[table->free_count].z = p; + table->free_list[table->free_count].root = &table->ht[hash]; + table->free_count++; + p->deleted = 1; + p->data = NULL; + if(table->cmp == strdb_cmp) { + if(table->maxlen) { + char *key = (char*)malloc(table->maxlen); + memcpy(key,p->key,table->maxlen); + p->key = key; + } else { + p->key = strdup((const char*)p->key); + } + } + } else { + db_rebalance_erase(p,&table->ht[hash]); + #ifdef MALLOC_DBN + free_dbn(p); + #else + aFree(p); + #endif + table->item_count--; + } return data; } void db_foreach(struct dbt *table,int (*func)(void*,void*,va_list),...) { int i,sp; - int count = 0; + int count = table->item_count; // red-black treeなので64個stackがあれば2^32個ノードまで大丈夫 struct dbn *p,*pn,*stack[64]; va_list ap; va_start(ap,func); + db_free_lock(table); for(i=0;i<HASH_SIZE;i++){ if((p=table->ht[i])==NULL) continue; @@ -457,8 +526,9 @@ void db_foreach(struct dbt *table,int (*func)(void*,void*,va_list),...) //if (!p->data) { // printf("Warning: no data for key %d in db_foreach (db.c) !\n",(int)p->key); //} else { - func(p->key, p->data, ap); - count++; + if(!p->deleted) + func(p->key, p->data, ap); + count--; //} if((pn=p->left)!=NULL){ if(p->right){ @@ -476,10 +546,11 @@ void db_foreach(struct dbt *table,int (*func)(void*,void*,va_list),...) } } } - if(count != table->item_count) { + db_free_unlock(table); + if(count) { printf( - "db_foreach : data lost %d of %d item(s) allocated from %s line %d\n", - table->item_count - count,count,table->alloc_file,table->alloc_line + "db_foreach : data lost %d item(s) allocated from %s line %d\n", + count,table->alloc_file,table->alloc_line ); } va_end(ap); @@ -492,12 +563,13 @@ void db_final(struct dbt *table,int (*func)(void*,void*,va_list),...) va_list ap; va_start(ap,func); + db_free_lock(table); for(i=0;i<HASH_SIZE;i++){ if((p=table->ht[i])==NULL) continue; sp=0; while(1){ - if(func) + if(func && !p->deleted) func(p->key,p->data,ap); if((pn=p->left)!=NULL){ if(p->right){ @@ -520,6 +592,8 @@ void db_final(struct dbt *table,int (*func)(void*,void*,va_list),...) p=pn; } } + db_free_unlock(table); + free(table->free_list); aFree(table); va_end(ap); } diff --git a/src/common/db.h b/src/common/db.h index c31f5bfaa..11ed4f3e1 100644 --- a/src/common/db.h +++ b/src/common/db.h @@ -13,6 +13,7 @@ struct dbn { int color; void *key; void *data; + int deleted; // 削除済みフラグ(db_foreach) }; struct dbt { @@ -24,7 +25,16 @@ struct dbt { struct dbn *ht[HASH_SIZE]; int item_count; // vf? const char* alloc_file; // DB?t@C - int alloc_line; // DB?s + int alloc_line; // DB?s + // db_foreach 内部でdb_erase される対策として、 + // db_foreach が終わるまでロックすることにする + struct db_free { + struct dbn *z; + struct dbn **root; + } *free_list; + int free_count; + int free_max; + int free_lock; }; #define strdb_search(t,k) db_search((t),(void*)(k)) |