db.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. // $Id: db.c,v 1.2 2004/09/23 14:43:06 MouseJstr Exp $
  2. // #define MALLOC_DBN
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "db.h"
  7. #include "mmo.h"
  8. #include "utils.h"
  9. #include "malloc.h"
  10. #ifdef MEMWATCH
  11. #include "memwatch.h"
  12. #endif
  13. #define ROOT_SIZE 4096
  14. #ifdef MALLOC_DBN
  15. static struct dbn *dbn_root[512], *dbn_free;
  16. static int dbn_root_rest=0,dbn_root_num=0;
  17. static void * malloc_dbn(void)
  18. {
  19. struct dbn* ret;
  20. if(dbn_free==NULL){
  21. if(dbn_root_rest<=0){
  22. CREATE(dbn_root[dbn_root_num], struct dbn, ROOT_SIZE);
  23. dbn_root_rest=ROOT_SIZE;
  24. dbn_root_num++;
  25. }
  26. return &(dbn_root[dbn_root_num-1][--dbn_root_rest]);
  27. }
  28. ret=dbn_free;
  29. dbn_free = dbn_free->parent;
  30. return ret;
  31. }
  32. static void free_dbn(struct dbn* add_dbn)
  33. {
  34. add_dbn->parent = dbn_free;
  35. dbn_free = add_dbn;
  36. }
  37. #endif
  38. // maybe change the void* to const char* ???
  39. static int strdb_cmp(struct dbt* table,void* a,void* b)
  40. {
  41. if(table->maxlen)
  42. return strncmp((const char*)a,(const char*)b,table->maxlen);
  43. return strcmp((const char*)a,(const char*)b);
  44. }
  45. // maybe change the void* to unsigned char* ???
  46. static unsigned int strdb_hash(struct dbt* table,void* a)
  47. {
  48. int i;
  49. unsigned int h;
  50. unsigned char *p = (unsigned char*)a;
  51. i=table->maxlen;
  52. if(i==0) i=0x7fffffff;
  53. for(h=0;*p && --i>=0;){
  54. h=(h*33 + *p++) ^ (h>>24);
  55. }
  56. return h;
  57. }
  58. struct dbt* strdb_init_(int maxlen,const char *file,int line)
  59. {
  60. int i;
  61. struct dbt* table;
  62. CREATE(table, struct dbt, 1);
  63. table->cmp=strdb_cmp;
  64. table->hash=strdb_hash;
  65. table->maxlen=maxlen;
  66. for(i=0;i<HASH_SIZE;i++)
  67. table->ht[i]=NULL;
  68. table->alloc_file = file;
  69. table->alloc_line = line;
  70. table->item_count = 0;
  71. return table;
  72. }
  73. static int numdb_cmp(struct dbt* table,void* a,void* b)
  74. {
  75. int ia,ib;
  76. ia=(int)a;
  77. ib=(int)b;
  78. if((ia^ib) & 0x80000000)
  79. return ia<0 ? -1 : 1;
  80. return ia-ib;
  81. }
  82. static unsigned int numdb_hash(struct dbt* table,void* a)
  83. {
  84. return (unsigned int)a;
  85. }
  86. struct dbt* numdb_init_(const char *file,int line)
  87. {
  88. int i;
  89. struct dbt* table;
  90. CREATE(table, struct dbt, 1);
  91. table->cmp=numdb_cmp;
  92. table->hash=numdb_hash;
  93. table->maxlen=sizeof(int);
  94. for(i=0;i<HASH_SIZE;i++)
  95. table->ht[i]=NULL;
  96. table->alloc_file = file;
  97. table->alloc_line = line;
  98. table->item_count = 0;
  99. return table;
  100. }
  101. void* db_search(struct dbt *table,void* key)
  102. {
  103. struct dbn *p;
  104. for(p=table->ht[table->hash(table,key) % HASH_SIZE];p;){
  105. int c=table->cmp(table,key,p->key);
  106. if(c==0)
  107. return p->data;
  108. if(c<0)
  109. p=p->left;
  110. else
  111. p=p->right;
  112. }
  113. return NULL;
  114. }
  115. void * db_search2(struct dbt *table, const char *key)
  116. {
  117. int i,sp;
  118. struct dbn *p,*pn,*stack[64];
  119. int slen = strlen(key);
  120. for(i=0;i<HASH_SIZE;i++){
  121. if((p=table->ht[i])==NULL)
  122. continue;
  123. sp=0;
  124. while(1){
  125. if (strnicmp(key, (const char*)p->key, slen) == 0)
  126. return p->data;
  127. if((pn=p->left)!=NULL){
  128. if(p->right){
  129. stack[sp++]=p->right;
  130. }
  131. p=pn;
  132. } else {
  133. if(p->right){
  134. p=p->right;
  135. } else {
  136. if(sp==0)
  137. break;
  138. p=stack[--sp];
  139. }
  140. }
  141. }
  142. }
  143. return 0;
  144. }
  145. static void db_rotate_left(struct dbn *p,struct dbn **root)
  146. {
  147. struct dbn * y = p->right;
  148. p->right = y->left;
  149. if (y->left !=0)
  150. y->left->parent = p;
  151. y->parent = p->parent;
  152. if (p == *root)
  153. *root = y;
  154. else if (p == p->parent->left)
  155. p->parent->left = y;
  156. else
  157. p->parent->right = y;
  158. y->left = p;
  159. p->parent = y;
  160. }
  161. static void db_rotate_right(struct dbn *p,struct dbn **root)
  162. {
  163. struct dbn * y = p->left;
  164. p->left = y->right;
  165. if (y->right != 0)
  166. y->right->parent = p;
  167. y->parent = p->parent;
  168. if (p == *root)
  169. *root = y;
  170. else if (p == p->parent->right)
  171. p->parent->right = y;
  172. else
  173. p->parent->left = y;
  174. y->right = p;
  175. p->parent = y;
  176. }
  177. static void db_rebalance(struct dbn *p,struct dbn **root)
  178. {
  179. p->color = RED;
  180. while(p!=*root && p->parent->color==RED){ // rootは必ず黒で親は赤いので親の親は必ず存在する
  181. if (p->parent == p->parent->parent->left) {
  182. struct dbn *y = p->parent->parent->right;
  183. if (y && y->color == RED) {
  184. p->parent->color = BLACK;
  185. y->color = BLACK;
  186. p->parent->parent->color = RED;
  187. p = p->parent->parent;
  188. } else {
  189. if (p == p->parent->right) {
  190. p = p->parent;
  191. db_rotate_left(p, root);
  192. }
  193. p->parent->color = BLACK;
  194. p->parent->parent->color = RED;
  195. db_rotate_right(p->parent->parent, root);
  196. }
  197. } else {
  198. struct dbn* y = p->parent->parent->left;
  199. if (y && y->color == RED) {
  200. p->parent->color = BLACK;
  201. y->color = BLACK;
  202. p->parent->parent->color = RED;
  203. p = p->parent->parent;
  204. } else {
  205. if (p == p->parent->left) {
  206. p = p->parent;
  207. db_rotate_right(p, root);
  208. }
  209. p->parent->color = BLACK;
  210. p->parent->parent->color = RED;
  211. db_rotate_left(p->parent->parent, root);
  212. }
  213. }
  214. }
  215. (*root)->color=BLACK;
  216. }
  217. static void db_rebalance_erase(struct dbn *z,struct dbn **root)
  218. {
  219. struct dbn *y = z, *x = NULL, *x_parent = NULL;
  220. if (y->left == NULL)
  221. x = y->right;
  222. else if (y->right == NULL)
  223. x = y->left;
  224. else {
  225. y = y->right;
  226. while (y->left != NULL)
  227. y = y->left;
  228. x = y->right;
  229. }
  230. if (y != z) { // 左右が両方埋まっていた時 yをzの位置に持ってきてzを浮かせる
  231. z->left->parent = y;
  232. y->left = z->left;
  233. if (y != z->right) {
  234. x_parent = y->parent;
  235. if (x) x->parent = y->parent;
  236. y->parent->left = x;
  237. y->right = z->right;
  238. z->right->parent = y;
  239. } else
  240. x_parent = y;
  241. if (*root == z)
  242. *root = y;
  243. else if (z->parent->left == z)
  244. z->parent->left = y;
  245. else
  246. z->parent->right = y;
  247. y->parent = z->parent;
  248. { int tmp=y->color; y->color=z->color; z->color=tmp; }
  249. y = z;
  250. } else { // どちらか空いていた場合 xをzの位置に持ってきてzを浮かせる
  251. x_parent = y->parent;
  252. if (x) x->parent = y->parent;
  253. if (*root == z)
  254. *root = x;
  255. else if (z->parent->left == z)
  256. z->parent->left = x;
  257. else
  258. z->parent->right = x;
  259. }
  260. // ここまで色の移動の除いて通常の2分木と同じ
  261. if (y->color != RED) { // 赤が消える分には影響無し
  262. while (x != *root && (x == NULL || x->color == BLACK))
  263. if (x == x_parent->left) {
  264. struct dbn* w = x_parent->right;
  265. if (w->color == RED) {
  266. w->color = BLACK;
  267. x_parent->color = RED;
  268. db_rotate_left(x_parent, root);
  269. w = x_parent->right;
  270. }
  271. if ((w->left == NULL ||
  272. w->left->color == BLACK) &&
  273. (w->right == NULL ||
  274. w->right->color == BLACK)) {
  275. w->color = RED;
  276. x = x_parent;
  277. x_parent = x_parent->parent;
  278. } else {
  279. if (w->right == NULL ||
  280. w->right->color == BLACK) {
  281. if (w->left) w->left->color = BLACK;
  282. w->color = RED;
  283. db_rotate_right(w, root);
  284. w = x_parent->right;
  285. }
  286. w->color = x_parent->color;
  287. x_parent->color = BLACK;
  288. if (w->right) w->right->color = BLACK;
  289. db_rotate_left(x_parent, root);
  290. break;
  291. }
  292. } else { // same as above, with right <-> left.
  293. struct dbn* w = x_parent->left;
  294. if (w->color == RED) {
  295. w->color = BLACK;
  296. x_parent->color = RED;
  297. db_rotate_right(x_parent, root);
  298. w = x_parent->left;
  299. }
  300. if ((w->right == NULL ||
  301. w->right->color == BLACK) &&
  302. (w->left == NULL ||
  303. w->left->color == BLACK)) {
  304. w->color = RED;
  305. x = x_parent;
  306. x_parent = x_parent->parent;
  307. } else {
  308. if (w->left == NULL ||
  309. w->left->color == BLACK) {
  310. if (w->right) w->right->color = BLACK;
  311. w->color = RED;
  312. db_rotate_left(w, root);
  313. w = x_parent->left;
  314. }
  315. w->color = x_parent->color;
  316. x_parent->color = BLACK;
  317. if (w->left) w->left->color = BLACK;
  318. db_rotate_right(x_parent, root);
  319. break;
  320. }
  321. }
  322. if (x) x->color = BLACK;
  323. }
  324. }
  325. void db_free_lock(struct dbt *table) {
  326. table->free_lock++;
  327. }
  328. void db_free_unlock(struct dbt *table) {
  329. if(--table->free_lock == 0) {
  330. int i;
  331. for(i = 0; i < table->free_count ; i++) {
  332. db_rebalance_erase(table->free_list[i].z,table->free_list[i].root);
  333. if(table->cmp == strdb_cmp) {
  334. free(table->free_list[i].z->key);
  335. }
  336. #ifdef MALLOC_DBN
  337. free_dbn(table->free_list[i].z);
  338. #else
  339. free(table->free_list[i].z);
  340. #endif
  341. table->item_count--;
  342. }
  343. table->free_count = 0;
  344. }
  345. }
  346. struct dbn* db_insert(struct dbt *table,void* key,void* data)
  347. {
  348. struct dbn *p,*priv;
  349. int c,hash;
  350. hash = table->hash(table,key) % HASH_SIZE;
  351. for(c=0,priv=NULL ,p = table->ht[hash];p;){
  352. c=table->cmp(table,key,p->key);
  353. if(c==0){ // replace
  354. if (table->release)
  355. table->release(p, 3);
  356. if(p->deleted) {
  357. // 削除されたデータなので、free_list 上の削除予定を消す
  358. int i;
  359. for(i = 0; i < table->free_count ; i++) {
  360. if(table->free_list[i].z == p) {
  361. memmove(
  362. &table->free_list[i],
  363. &table->free_list[i+1],
  364. sizeof(struct db_free)*(table->free_count - i - 1)
  365. );
  366. break;
  367. }
  368. }
  369. if(i == table->free_count || table->free_count <= 0) {
  370. printf("db_insert: cannnot find deleted db node.\n");
  371. } else {
  372. table->free_count--;
  373. if(table->cmp == strdb_cmp) {
  374. free(p->key);
  375. }
  376. }
  377. }
  378. p->data=data;
  379. p->key=key;
  380. p->deleted = 0;
  381. return p;
  382. }
  383. priv=p;
  384. if(c<0){
  385. p=p->left;
  386. } else {
  387. p=p->right;
  388. }
  389. }
  390. #ifdef MALLOC_DBN
  391. p=malloc_dbn();
  392. #else
  393. CREATE(p, struct dbn, 1);
  394. #endif
  395. if(p==NULL){
  396. printf("out of memory : db_insert\n");
  397. return NULL;
  398. }
  399. p->parent= NULL;
  400. p->left = NULL;
  401. p->right = NULL;
  402. p->key = key;
  403. p->data = data;
  404. p->color = RED;
  405. p->deleted = 0;
  406. if(c==0){ // hash entry is empty
  407. table->ht[hash] = p;
  408. p->color = BLACK;
  409. } else {
  410. if(c<0){ // left node
  411. priv->left = p;
  412. p->parent=priv;
  413. } else { // right node
  414. priv->right = p;
  415. p->parent=priv;
  416. }
  417. if(priv->color==RED){ // must rebalance
  418. db_rebalance(p,&table->ht[hash]);
  419. }
  420. }
  421. table->item_count++;
  422. return p;
  423. }
  424. void* db_erase(struct dbt *table,void* key)
  425. {
  426. void *data;
  427. struct dbn *p;
  428. int c,hash;
  429. hash = table->hash(table,key) % HASH_SIZE;
  430. for(c=0,p = table->ht[hash];p;){
  431. c=table->cmp(table,key,p->key);
  432. if(c==0)
  433. break;
  434. if(c<0)
  435. p=p->left;
  436. else
  437. p=p->right;
  438. }
  439. if(!p)
  440. return NULL;
  441. data=p->data;
  442. if(table->free_lock) {
  443. if(table->free_count == table->free_max) {
  444. table->free_max += 32;
  445. table->free_list = (struct db_free*)realloc(table->free_list,sizeof(struct db_free) * table->free_max);
  446. }
  447. table->free_list[table->free_count].z = p;
  448. table->free_list[table->free_count].root = &table->ht[hash];
  449. table->free_count++;
  450. p->deleted = 1;
  451. p->data = NULL;
  452. if(table->cmp == strdb_cmp) {
  453. if(table->maxlen) {
  454. char *key = (char*)malloc(table->maxlen);
  455. memcpy(key,p->key,table->maxlen);
  456. p->key = key;
  457. } else {
  458. p->key = strdup((const char*)p->key);
  459. }
  460. }
  461. } else {
  462. db_rebalance_erase(p,&table->ht[hash]);
  463. #ifdef MALLOC_DBN
  464. free_dbn(p);
  465. #else
  466. aFree(p);
  467. #endif
  468. table->item_count--;
  469. }
  470. return data;
  471. }
  472. void db_foreach(struct dbt *table,int (*func)(void*,void*,va_list),...)
  473. {
  474. int i,sp;
  475. int count = table->item_count;
  476. // red-black treeなので64個stackがあれば2^32個ノードまで大丈夫
  477. struct dbn *p,*pn,*stack[64];
  478. va_list ap;
  479. va_start(ap,func);
  480. db_free_lock(table);
  481. for(i=0;i<HASH_SIZE;i++){
  482. if((p=table->ht[i])==NULL)
  483. continue;
  484. sp=0;
  485. while(1){
  486. //reverted it back. sorry that brought thios bug from Freya [Lupus]
  487. //if (!p->data) {
  488. // printf("Warning: no data for key %d in db_foreach (db.c) !\n",(int)p->key);
  489. //} else {
  490. if(!p->deleted)
  491. func(p->key, p->data, ap);
  492. count--;
  493. //}
  494. if((pn=p->left)!=NULL){
  495. if(p->right){
  496. stack[sp++]=p->right;
  497. }
  498. p=pn;
  499. } else {
  500. if(p->right){
  501. p=p->right;
  502. } else {
  503. if(sp==0)
  504. break;
  505. p=stack[--sp];
  506. }
  507. }
  508. }
  509. }
  510. db_free_unlock(table);
  511. if(count) {
  512. printf(
  513. "db_foreach : data lost %d item(s) allocated from %s line %d\n",
  514. count,table->alloc_file,table->alloc_line
  515. );
  516. }
  517. va_end(ap);
  518. }
  519. void db_final(struct dbt *table,int (*func)(void*,void*,va_list),...)
  520. {
  521. int i,sp;
  522. struct dbn *p,*pn,*stack[64];
  523. va_list ap;
  524. va_start(ap,func);
  525. db_free_lock(table);
  526. for(i=0;i<HASH_SIZE;i++){
  527. if((p=table->ht[i])==NULL)
  528. continue;
  529. sp=0;
  530. while(1){
  531. if(func && !p->deleted)
  532. func(p->key,p->data,ap);
  533. if((pn=p->left)!=NULL){
  534. if(p->right){
  535. stack[sp++]=p->right;
  536. }
  537. } else {
  538. if(p->right){
  539. pn=p->right;
  540. } else {
  541. if(sp==0)
  542. break;
  543. pn=stack[--sp];
  544. }
  545. }
  546. #ifdef MALLOC_DBN
  547. free_dbn(p);
  548. #else
  549. aFree(p);
  550. #endif
  551. p=pn;
  552. }
  553. }
  554. db_free_unlock(table);
  555. free(table->free_list);
  556. aFree(table);
  557. va_end(ap);
  558. }