db.c
上传用户:qys8201
上传日期:2021-12-11
资源大小:978k
文件大小:40k
源码类别:

模拟服务器

开发平台:

C/C++

  1. /*
  2.   仿件平件弘窗  勾五犯□正矛□旦及  隶[
  3.   1999 Aug 14 Created by ringo
  4.   犯□正矛□旦反1  及伉件弁及溥匹忡绣今木月[
  5.   
  6.   
  7.  */
  8. #define _DB_C_
  9. #include "db.h"
  10. #include "main.h"
  11. #include "util.h"
  12. #include "version.h"
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <sys/types.h>
  16. #include <dirent.h>
  17. #include <errno.h>
  18. #include <string.h>
  19. #include <sys/stat.h>
  20. /*   侬  巨件玄伉及    length */
  21. //#define CHARVALUE_MAX 1024
  22. #define MAXTABLE 16
  23. // Spock 2000/10/12
  24. #define CHARVALUE_MAX 256 // DB 字串资料的buffer大小
  25. #define KEY_MAX 64 // DB Key字串的buffer大小
  26. #define HASH_SIZE 65536 // Hash table 一次增加的Entry数量
  27. #define HASH_PRIME 65521 // Hash function 使用的质数
  28. #define DBINIT_SIZE 16384 // DB 每次配置Entry的数量
  29. // Spock end
  30. /* 犯□正矛□旦及伉件弁及邰豳1蜊毛丐日歹允[ */
  31. struct dbentry
  32. {
  33.     int use;
  34. //    unsigned int keyhash;       /* 腹绸平□及甩永扑亘戊□玉 */
  35.     int ivalue;                  /* 旦戊失[玄永皿 NODE 反  -1 匹}
  36.                                  允屯化及旦戊失反 0 动晓匹卅中午中仃卅中*/
  37. //    int nextind;                /* -1 分匀凶日    毛啦  允月 */
  38.     // Spock 2000/10/12
  39.     int prev; // 前一个dbentry, -1表示此项为head
  40.     int next; // 下一个dbentry, -1表示此项为tail
  41.     char key[KEY_MAX];
  42.     char charvalue[CHARVALUE_MAX];
  43. //    char key[64];               /* 腹绸平□午卅月  侬   */
  44. //    int charvalue_index;        /*   侬  田永白央毛今允index */
  45.     // Spock end
  46. };
  47. // Spock 2000/10/12
  48. // Database hashtable
  49. struct hashentry
  50. {
  51.     char key[KEY_MAX]; // 索引key值
  52.     int use; // 是否已被使用
  53.     int dbind; // 指向 dbentry 的 index
  54.     int prev; // 同一key值的上一个 hashentry, -1为head
  55.     int next; // 同一key值的下一个 hashentry, -1为tail
  56. };
  57. // Spock end
  58. typedef enum
  59. {
  60.     DB_INT_SORTED,
  61.     DB_STRING,
  62. }DBTYPE;
  63. /* 1蜊及犯□正矛□旦毛丐日歹允 */
  64. struct table
  65. {
  66.     int use; // 0:未使用 1:已使用
  67.     DBTYPE type;                    /* DB及潘   */
  68.     char name[32];                  /* 犯□正矛□旦及  蟆 */
  69.     int num;                        /* 巨件玄伉及醒 */
  70.     int toplinkindex;
  71.     // Spock 2000/10/12
  72.     struct hashentry *hashtable;
  73.     int hashsize;
  74.     int updated; // 0:dbflush後未更新 1:已更新
  75.     int ent_finder; // 指向最後一次配置的 hashentry
  76.     // Spock end
  77. };
  78. struct dbentry *master_buf;     /* 巨件玄伉筏盛迕 */
  79. int dbsize = 0;                 /*   赓0匹}1,2,4,8,16...*/
  80. static int dbent_finder = 0;
  81. struct table dbt[MAXTABLE];
  82. static void dbShowAllTable(void);
  83. // Spock 2000/10/12
  84. int dbHash(char* s)
  85. {
  86.     char *p;
  87.     unsigned int h= 0 ,g;
  88.     for( p = s ; *p ; p ++ ){
  89.         h = ( h<< 4 ) + (*p);
  90.         if( (g = h & 0xf0000000) != 0){
  91.             h = h ^ (g>>24);
  92.             h = h ^ g;
  93.         }
  94.     }
  95.     return h % HASH_PRIME;
  96. }
  97. // Spock end
  98. /* Spock deleted 2000/10/12
  99. struct charvalue
  100. {
  101.     int use;
  102.     char buf[CHARVALUE_MAX];
  103. };
  104. struct charvalue *charvalue_buf;
  105. int charvaluesize=0;
  106. */
  107. /*
  108.     侬  田永白央□毛傀舰允月
  109.  */
  110. /* Spock deleted 2000/10/12
  111. int
  112. reallocCharValue(void)
  113. {
  114.     struct charvalue *previous = charvalue_buf;
  115.     struct charvalue *newbuf;
  116.     int new_charvaluesize;
  117.     if( charvaluesize == 0 ){
  118.         new_charvaluesize = 1;
  119.     } else {
  120.         new_charvaluesize = charvaluesize * 2;
  121.     }
  122.     newbuf = ( struct charvalue *) calloc( 1, new_charvaluesize *
  123.                                           sizeof( struct charvalue ));
  124.     if( newbuf == NULL ){
  125.         log( "reallocCharValue: memory shortage!! new_charvaluesize:%dn",
  126.              new_charvaluesize );
  127.         return -1;
  128.     }
  129.     memset( newbuf, 0 , new_charvaluesize * sizeof( struct charvalue ));
  130.     if( previous) memcpy( (char*)newbuf, (char*)previous,
  131.             charvaluesize * sizeof( struct charvalue ));
  132.     free( previous );
  133.     charvaluesize = new_charvaluesize;
  134.     charvalue_buf = newbuf;
  135.     log( "reallocCharValue: "
  136.          "new_charvaluesize:%d Old address:%x New address:%xn",
  137.          new_charvaluesize , (unsigned int )previous,
  138.          (unsigned int)newbuf );
  139.     return 0;
  140. }
  141. */
  142. /*
  143.     侬  田永白央□毛1蜊歹曰丐化月[
  144.   凶曰卅仁卅匀凶日realloc允月[
  145.   
  146. */
  147. /* Spock deleted 2000/10/12
  148. static int charvalue_finder=0;
  149. static int
  150. dbAllocCharValue( void )
  151. {
  152.     int i;
  153.     for(i=0;i<charvaluesize;i++){
  154.         charvalue_finder++;
  155.         if( charvalue_finder == charvaluesize ) charvalue_finder =0;
  156.         if( charvalue_buf[charvalue_finder].use == 0 ){
  157.             charvalue_buf[charvalue_finder].use =1;
  158.             charvalue_buf[charvalue_finder].buf[0] = 0;
  159.             return charvalue_finder;
  160.         }
  161.     }
  162.     log( "dbAllocCharValue: charvalue array full. reallocating....n" );
  163.     if( reallocCharValue() < 0 ){
  164.         log( "dbAllocCharValue: reallocation failn");
  165.     } else {
  166.         return dbAllocCharValue();
  167.     }
  168.     return -1;
  169. }
  170. */
  171. /*
  172.   charvalue 井日/卞袄毛必永玄/本永玄允月
  173.   int index : charvalue index
  174.   
  175.  */
  176. /* Spock deleted 2000/10/12
  177. static char *
  178. dbGetString( int index )
  179. {
  180.     return charvalue_buf[index].buf;
  181. }
  182. static int
  183. dbSetString( int index , char *data )
  184. {
  185.     int l = strlen(data);
  186.     if( l >= (sizeof( charvalue_buf[0].buf )-1)) return -1;
  187.     memcpy( charvalue_buf[index].buf , data, l+1 );
  188.     return 0;
  189. }
  190. */
  191. /*
  192.   DB及云云五今互凶日氏仁卅匀凶日歹曰丐化卅云允[中引及扔奶术及2  卞允月
  193.   0分匀凶日1卞允月
  194.  */
  195. static int
  196. reallocDB( void )
  197. {
  198.     struct dbentry *previous = master_buf;
  199.     struct dbentry *newbuf;
  200.     int new_dbsize;
  201. /* Spock deleted 2000/10/12    
  202.     if( dbsize == 0 ){
  203.         new_dbsize = 1;
  204.     } else {
  205.         new_dbsize = dbsize * 2;
  206.     }
  207. */
  208.     // Spock+1 2000/10/12
  209.     new_dbsize = dbsize + DBINIT_SIZE;
  210.     
  211.     newbuf = (struct dbentry* ) calloc( 1, new_dbsize *
  212.                                          sizeof( struct dbentry) );
  213.     /* 丢乒伉凶曰卅中   */
  214.     if( newbuf == NULL ){
  215.         log( "重新分配数据: 内存不足!!! 新数据大小: %dn", new_dbsize );
  216.         return -1;
  217.     }
  218.     /* 衙中幻丹井日蕙仄中  卞戊疋□仄化 */
  219.     memset( newbuf , 0 , new_dbsize * sizeof( struct dbentry ) );
  220.     /* Spock deleted 2000/10/19
  221.     if( previous )memcpy( (char*)newbuf, (char*)previous,
  222.             dbsize * sizeof( struct dbentry ));
  223.     // 衙中幻丹毛荸  仄
  224.     free( previous );
  225.     */
  226.     // Spock 2000/10/19
  227.     if ( dbsize > 0 )
  228.     {
  229.      memcpy( newbuf , previous , dbsize * sizeof(struct dbentry));
  230.      free( previous );
  231.     }
  232.     // Spock end
  233.     dbent_finder = dbsize; // 将 dbent_finder 指向未使用的 entry
  234.     dbsize = new_dbsize;
  235.     master_buf = newbuf;
  236.     
  237.     log( "重新分配数据: 新数据大小:%d 旧地址: %x 新地址:%xn",
  238.          new_dbsize , (unsigned int)previous, (unsigned int)newbuf );
  239.     return 0;
  240. }
  241. /*
  242.   allocate a node
  243.  */
  244. static int
  245. //dbAllocNode( DBTYPE type  )
  246. // Spock +1 2000/10/13
  247. dbAllocNode()
  248. {
  249.     int i;
  250.     for(i=0;i<dbsize;i++){
  251.         dbent_finder ++;
  252.         if( dbent_finder == dbsize ) {
  253.             dbent_finder = 0;
  254.         }
  255.         if( master_buf[dbent_finder].use == 0 ){
  256.             master_buf[dbent_finder].use = 1;
  257.             /* Spock deleted 2000/10/12
  258.             // int 匹手尥笛树  及啃卞stringbuffer毛  勾仪卞允月 kawata
  259.             if( type == DB_STRING || type == DB_INT_SORTED){
  260.                 if( ( master_buf[dbent_finder].charvalue_index =
  261.                       dbAllocCharValue() ) < 0 ){
  262.                     //   侬  田永白央□互凶曰卅中冗
  263.                     return -1;
  264.                 }
  265.             }
  266.             */
  267.             return dbent_finder;
  268.         }
  269.     }
  270.     log( "数据进入队列失败. 重新分配中....n" );
  271.     if( reallocDB() < 0 ){
  272.         log( "重新分配失败n" );
  273.     } else {
  274.         //return dbAllocNode( type );
  275.         // Spock 2000/10/13
  276.         master_buf[dbent_finder].use = 1;
  277.         log( "数据探测=%dn" , dbent_finder );
  278.         return dbent_finder;
  279.         // Spock end
  280.     }
  281.     return -1;
  282. }
  283. static void
  284. dbReleaseNode( int index )
  285. {
  286.     // Spock 2000/10/12
  287.     int prev = master_buf[index].prev;
  288.     int next = master_buf[index].next;
  289.     master_buf[index].use = 0;
  290.     if ( prev >= 0 ) master_buf[prev].next = next;
  291.     if ( next >= 0 ) master_buf[next].prev = prev;
  292.     // Spock end
  293.     /* Spock deleted 2000/10/12
  294. if( master_buf[index].charvalue_index >= 0 ) {
  295. charvalue_buf[ master_buf[index].charvalue_index].use = 0;
  296. }
  297.     */
  298. }
  299. void
  300. dbShowLink( int topind )
  301. {
  302.     int cur = topind;
  303.     log( "开始从 %d 链接数据n", cur );
  304.     
  305.     /* Spock deleted 2000/10/19
  306.     for(;;){
  307.         if( cur == -1 )break;
  308.     */
  309.     // Spock +1 2000/10/19
  310.     while ( cur >= 0 )
  311.     {
  312.         if( master_buf[cur].use == 0 ){
  313.             log( "dbShowLink: use is 0! key:%sn", master_buf[cur].key );
  314.             return;
  315.         }
  316.         // Spock +1  2000/10/12
  317.         log( "%s %in", master_buf[cur].key, master_buf[cur].ivalue );
  318.         /* Spock deleted 2000/10/12
  319.         log( "%s %u %in", master_buf[cur].key ,
  320.              master_buf[cur].keyhash, master_buf[cur].ivalue );
  321.         */
  322.         cur = master_buf[cur].next;
  323.     }
  324. }
  325. // Spock 2000/10/13
  326. static int
  327. reallocHash( int dbi )
  328. {
  329.     struct hashentry *previous = dbt[dbi].hashtable;
  330.     struct hashentry *newbuf;
  331.     int new_hashsize;
  332.  
  333.     new_hashsize = dbt[dbi].hashsize + HASH_SIZE;
  334.     newbuf = (struct hashentry* ) calloc( 1, new_hashsize *
  335.                                          sizeof( struct hashentry) );
  336.     if( newbuf == NULL ){
  337.         log( "重新分配无用信息: 内存不足!!! 新无用信息大小: %dn", new_hashsize );
  338.         return -1;
  339.     }
  340.     memset( newbuf , 0 , new_hashsize * sizeof( struct hashentry ) );
  341.     if( previous )
  342.     {
  343.      memcpy( newbuf, previous,
  344.             dbt[dbi].hashsize * sizeof( struct hashentry ));
  345.         free( previous );
  346.     }
  347.     if ( dbt[dbi].hashsize > HASH_PRIME )
  348.         dbt[dbi].ent_finder = dbt[dbi].hashsize;
  349.     else
  350.         dbt[dbi].ent_finder = HASH_PRIME;
  351.     dbt[dbi].hashsize = new_hashsize;
  352.     dbt[dbi].hashtable = newbuf;
  353.     
  354.     log( "重新分配无用信息: 新无用信息大小:%d 旧地址: %x 新地址:%xn",
  355.          new_hashsize , (unsigned int)previous, (unsigned int)newbuf );
  356.     return 0;
  357. }
  358. static int tableGetEntry( int dbi , char *k )
  359. {
  360.     int hashkey = dbHash( k );
  361.     struct hashentry *hash = dbt[dbi].hashtable;
  362.     if ( hash[hashkey].use == 0 ) return -1;
  363.     while ( 1 ) {
  364. // if ( hash[hashkey].use == 1 && strcmp( hash[hashkey].key , k ) == 0 ){
  365. if ( hash[hashkey].use == 1 ){
  366. if( strcmp( hash[hashkey].key , k ) == 0 )return hashkey;
  367. }
  368.     hashkey = hash[hashkey].next;
  369. if ( hashkey <= 0 ){
  370. // log("err not found hash[%x] -%s!n", hashkey, k)
  371. return -1;
  372.     }
  373. }
  374. static int tableInsertNode( int dbi , char *k , int dbind )
  375. {
  376.     int hashkey = dbHash( k );
  377.     int hashnext = -1;
  378.     int i;
  379.     struct hashentry *hash = dbt[dbi].hashtable;
  380.   
  381.     if ( hash[hashkey].use == 0 )  {
  382.      strcpy( hash[hashkey].key , k );
  383.     hash[hashkey].use = 1;
  384.      hash[hashkey].dbind = dbind;
  385.      hash[hashkey].prev = -1;
  386.      hash[hashkey].next = -1;
  387.      dbt[dbi].num++;
  388.         return hashkey;
  389.     }else {
  390.      for ( i=0; i<dbt[dbi].hashsize-HASH_PRIME; i++ ){
  391.          dbt[dbi].ent_finder++;
  392.          if ( dbt[dbi].ent_finder >= dbt[dbi].hashsize )
  393.              dbt[dbi].ent_finder = HASH_PRIME;
  394.          if ( hash[dbt[dbi].ent_finder].use == 0 )
  395.          {
  396.              hashnext = dbt[dbi].ent_finder;
  397.              break;
  398.          }
  399.      }
  400.      if ( hashnext < HASH_PRIME )
  401.      {
  402.             log( "tableInsertNode: hashentry array full. reallocating....n" );
  403.             if( reallocHash( dbi ) < 0 ){
  404.                 log( "tableInsertNode: reallocation failn" );
  405.                 return -1;
  406.             }
  407.             else
  408.             {
  409.              hash = dbt[dbi].hashtable;
  410.              hashnext = dbt[dbi].ent_finder;
  411.             }
  412.         }
  413.         strcpy( hash[hashnext].key , k );
  414.         hash[hashnext].use = 1;
  415.         hash[hashnext].dbind = dbind;
  416.         hash[hashnext].prev = hashkey;
  417.         hash[hashnext].next = hash[hashkey].next;
  418.         if ( hash[hashkey].next >= 0 )
  419.             hash[hash[hashkey].next].prev = hashnext;
  420.         hash[hashkey].next = hashnext;
  421.         dbt[dbi].num++;
  422.         return hashnext;
  423.     }
  424. }
  425. static void
  426. tableReleaseNode( int dbi , int ind )
  427. {
  428.     dbt[dbi].hashtable[ind].use = 0;
  429.     if ( dbt[dbi].hashtable[ind].prev >= 0 ){
  430.         dbt[dbi].hashtable[dbt[dbi].hashtable[ind].prev].next =
  431.         dbt[dbi].hashtable[ind].next;
  432.     }
  433.     if ( dbt[dbi].hashtable[ind].next >= 0 ){
  434.         dbt[dbi].hashtable[dbt[dbi].hashtable[ind].next].prev =
  435.         dbt[dbi].hashtable[ind].prev;
  436.     }
  437.     dbt[dbi].num--;
  438. }
  439. // Spock end
  440. /*
  441.   伉件弁及玄永皿毛芨尹日木凶日}平□毛  曰卞用□玉毛腹绸允月[
  442.   心勾井日卅中桦宁反巨仿□匹反卅中及匹0
  443.  */
  444. /* Spock deleted 2000/10/13
  445. static int
  446. dbExtractNodeByKey( int topind , char *k  )
  447. {
  448.     int cur = topind;
  449.     int prev = -1;
  450.     unsigned int h = hashpjw( k );
  451.     // 伉件弁互坞匹手心勾井日卅中分仃卅及匹0毛井尹允
  452.     if( topind == -1 ) return 0;
  453.     for(;;){
  454.         if( cur == -1 )break;
  455.         if( master_buf[cur].keyhash == h
  456.             && strcmp( master_buf[cur].key , k ) == 0 ){
  457.             // prev 及 戚互 cur 及戚卞卅月方丹卞允月
  458.             if( prev == -1 ){
  459.                 // 燮  分匀凶及匹伉件弁反中元日卅中
  460.             } else {                
  461.                 master_buf[prev].nextind = master_buf[cur].nextind;
  462.             }
  463.             // 公木匹愤坌互伉旦玄井日陆木月及匹荸  允月
  464.             dbReleaseNode( cur );
  465.             log( "find key %s deletedn", k );
  466.             return 0;
  467.         }
  468.         prev = cur;
  469.         cur = master_buf[cur].nextind;
  470.     }
  471.     // not found
  472.     log( "dbExtractNodeBykey: %s not foundn" , k );
  473.     return 0;
  474. }
  475. */
  476. // Spock 2000/10/13
  477. static int
  478. dbExtractNodeByKey( int dbi , char *k  )
  479. {
  480.     int hashind = tableGetEntry( dbi , k );
  481.     if ( hashind < 0 ){
  482.      log( "dbExtractNodeByKey: tableGetEntry fail, key:%sn" , k );
  483.      return -1;
  484.     }
  485.     if ( dbt[dbi].hashtable[hashind].dbind < 0 ){
  486.      log( "dbExtractNodeByKey: invalid dbind in hash, key:%sn" , k );
  487.      return -1;
  488.     }
  489.     dbReleaseNode( dbt[dbi].hashtable[hashind].dbind );
  490.     tableReleaseNode( dbi , hashind );
  491.     return 0;
  492. }
  493. // Spock end
  494. /* Spock deleted 2000/10/12
  495. static int 
  496. dbGetEntryByKey( int topind , char *k )
  497. {
  498.     int cur = topind;
  499.     unsigned int h = hashpjw( k );
  500.     if( topind == -1 ) return 0;
  501.     for(;;){
  502.         if( cur == -1 )break;
  503.         if( master_buf[cur].keyhash == h
  504.             && strcmp( master_buf[cur].key, k ) == 0 ){
  505.             return cur;
  506.         }
  507.         cur = master_buf[cur].nextind;
  508.     }
  509.     return -1;
  510. }
  511. */
  512. /*
  513.   伉件弁及玄永皿毛芨尹日木凶日}袄毛  曰卞用□玉毛腹绸仄化
  514.   赝濠卅午仇欠卞 Insert 允月[切中今中  井日云云五中  卞卅日氏匹中月午
  515.   移烂
  516.  */
  517. /* Spock deleted 2000/10/13
  518. static int
  519. dbInsertNodeByIValue( int topind , int ins )
  520. {
  521.     int cur = topind;
  522.     int prev = -1;
  523.     if( topind == -1 ) return -1;
  524.     
  525.     for(;;){
  526.         if( cur == -1 ){
  527.             //     引匹中匀凶及匹馨笛允月
  528.             master_buf[prev].nextind = ins;
  529.             master_buf[ins].nextind = -1;
  530.             return 0;
  531.         }
  532.         if( master_buf[cur].ivalue < master_buf[ins].ivalue ){
  533.             if( prev == -1 ){
  534.                 log( "top_node is badly configuredn" );
  535.                 return -1;
  536.             }
  537.             master_buf[prev].nextind = ins;
  538.             master_buf[ins].nextind = cur;
  539.             return 0;
  540.         }
  541.         prev = cur;
  542.         cur = master_buf[cur].nextind;
  543.     }
  544.     
  545.     return -1;
  546. }
  547. */
  548. // Spock 2000/10/13
  549. static int
  550. dbInsertNodeByIValue( int topind , int ins )
  551. {
  552.     int cur = topind;
  553.     if ( (topind < 0)||(topind >= dbsize)||(ins < 0)||(ins >= dbsize ) )
  554.         return -1;
  555.     while ( master_buf[cur].next >= 0 ){
  556.      if ( master_buf[master_buf[cur].next].ivalue < master_buf[ins].ivalue )
  557.          break;
  558.      cur = master_buf[cur].next;
  559.     }
  560.     master_buf[ins].prev = cur;
  561.     master_buf[ins].next = master_buf[cur].next;
  562.     if ( master_buf[cur].next >= 0 )
  563.         master_buf[master_buf[cur].next].prev = ins;
  564.     master_buf[cur].next = ins;
  565.     return 0;
  566. }
  567. // Spock end
  568. /* Spock deleted 2000/10/13
  569. static int
  570. dbAppendNode( int topind , int ins )
  571. {
  572.     int cur =topind;
  573.     int prev = -1;
  574.     if( topind == -1 ) return -1;
  575.     for(;;){
  576.         if( cur == -1 ){
  577.             master_buf[prev].nextind = ins;
  578.             master_buf[ins].nextind = -1;
  579.             return 0;
  580.         }
  581.         prev = cur;
  582.         cur = master_buf[cur].nextind;
  583.     }
  584.     return -1;
  585. }
  586. */
  587. // Spock 2000/10/13
  588. static int
  589. dbAppendNode( int topind , int ins )
  590. {
  591.     if ( (topind < 0)||(topind >= dbsize)||(ins < 0)||(ins >= dbsize ) )
  592.         return -1;
  593.     master_buf[ins].prev = topind;
  594.     master_buf[ins].next = master_buf[topind].next;
  595.     if ( master_buf[topind].next >= 0 )
  596.         master_buf[master_buf[topind].next].prev = ins;
  597.     master_buf[topind].next = ins;
  598.     return 0;
  599. }
  600. // Spock end
  601. /*
  602.   犯□正矛□旦及  蟆毛  月[db反醒互剂卅中及匹  骚卞strcmp仄化方中
  603.   DBTYPE :潘  [
  604.   云卅元卅引尹及  反}帮醒午  侬  及    卞绣箕允月仇午互匹五月[
  605.   
  606.  */
  607. static int
  608. dbGetTableIndex( char *tname , DBTYPE type )
  609. {
  610.     int i;
  611.     for(i=0;i<MAXTABLE;i++){
  612.         if( dbt[i].use && strcmp( dbt[i].name , tname ) == 0 &&
  613.             dbt[i].type == type ){
  614.             return i ;
  615.         }
  616.     }
  617.     /* 心勾井日卅井匀凶及匹蕙筋分 */
  618.     for(i=0;i<MAXTABLE;i++){
  619.         if( dbt[i].use == 0 ){
  620.             int topind;
  621.             dbt[i].use = 1;
  622.             dbt[i].type = type;
  623.             snprintf( dbt[i].name , sizeof( dbt[i].name ) , "%s", tname );
  624.             // Spock 2000/10/16
  625.             if ( reallocHash( i ) < 0 )
  626.             {
  627.              log( "重新分配无用信息失败n");
  628.              return -2;
  629.             }
  630.             dbt[i].ent_finder = HASH_PRIME;
  631.             // Spock end
  632.             //topind = dbAllocNode( type );
  633.             // Spock +1 2000/10/16
  634.             topind = dbAllocNode();
  635.             if( topind < 0 ){
  636.                 log( "数据分配节点失败n" );
  637.                 return -2;
  638.             }
  639.             /* Spock deleted 2000/10/16
  640.             snprintf( master_buf[topind].key ,
  641.                       sizeof(master_buf[topind].key), "top_node" );
  642.             master_buf[topind].keyhash = hashpjw( master_buf[topind].key );
  643.             master_buf[topind].nextind = -1;
  644.             */
  645.             
  646.             /* 玄永皿及用□玉毛赓渝祭允月卅曰[
  647.                侬  及桦宁手帮醒及桦宁手云卅元匹方中[
  648.              0x7fffffff午中丹袄反}  侬  及桦宁反今幻升啦  毛手凶卅中及分[*/
  649.             master_buf[topind].ivalue = 0x7fffffff;    
  650.             /* Spock deleted 2000/10/16
  651.             if( type == DB_INT_SORTED ){
  652.                 master_buf[topind].charvalue_index = -1;
  653.                 //dbSetString( master_buf[topind].charvalue_index, "" );
  654.             } else {
  655.                 dbSetString( master_buf[topind].charvalue_index, "" );
  656.             }
  657.     */
  658.             // Spock 2000/10/16
  659.             master_buf[topind].prev = -1;
  660.             master_buf[topind].next = -1;
  661.             strcpy( master_buf[topind].key , "top_node" );
  662.             master_buf[topind].charvalue[0] = 0;
  663.             // Spock end
  664.             dbt[i].toplinkindex = topind;
  665.             return i;
  666.         }
  667.     }
  668.     /*   互中匀天中分[ */
  669.     log( "dbGetTableIndex: table full. now tables are:n" );
  670.     dbShowAllTable();
  671.     return -1;
  672. }
  673. /*
  674.   午曰丐尹内 strtol 匹五月袄仄井扔禾□玄仄卅中方
  675.   腹绸仄化苇勾仃凶用□玉卞覆仄化}
  676.   伉件弁井日  五午匀化井日}漆蘸反末□玄允月及卞银丹袄毛凶方曰卞
  677.   腹绸仄化}中中桦赭毛心勾仃凶日}公仇卞犒仄仇戈[
  678.   
  679.  */
  680. /* Spock deleted 2000/10/16
  681. int dbUpdateEntryInt( char *table , char *key , int value, char *info )
  682. {
  683.     int r, dbi = dbGetTableIndex( table , DB_INT_SORTED );
  684.     int entind;
  685.     if( strlen(key) >= sizeof( master_buf[0].key) )return -1;
  686.     
  687.     if( dbi < 0 ) return -1;
  688.     r = dbExtractNodeByKey( dbt[dbi].toplinkindex , key );
  689.     if( r < 0 ){
  690.         log( "dbUpdateEntryInt: dbExtractNodeByKey fail! bug!!!!n" );
  691.         return -1;
  692.     }
  693.     entind = dbAllocNode(DB_INT_SORTED);
  694.     if( entind < 0 ) return -1;
  695.     master_buf[entind].ivalue = value;
  696.     snprintf( master_buf[entind].key ,
  697.               sizeof(master_buf[entind].key), "%s", key );
  698.     master_buf[entind].keyhash = hashpjw( master_buf[entind].key );
  699.     master_buf[entind].nextind = -1; 
  700. // 尥笛树  毛本永玄允月
  701.     dbSetString( master_buf[entind].charvalue_index, info );
  702.     r = dbInsertNodeByIValue( dbt[dbi].toplinkindex , entind );
  703.     if( r < 0 ){
  704.         log( "dbUpdateEntryInt: dbInsertNodeByIValue failedn" );
  705.         return -1;
  706.     }
  707.     log( "dbUpdateEntryInt: successfully updated entry %s:%s:%dn",
  708.              table, key, value );
  709.     return 0;    
  710.     
  711. }
  712. */
  713. // Spock 2000/10/16
  714. int dbUpdateEntryInt( char *table , char *key , int value, char *info )
  715. {
  716.     int dbi = dbGetTableIndex( table , DB_INT_SORTED );
  717.     int dbind, hashind, newpos;
  718.     // Spock 2000/10/23
  719.     if ( strlen( key ) >= KEY_MAX ) {
  720.      log( "dbUpdateEntryInt: key is too long, key:%sn", key );
  721.      return -1;
  722.     }
  723.     if ( strlen( info ) >= CHARVALUE_MAX ) {
  724.      log( "dbUpdateEntryInt: charvalue is too long, charvalue:%sn", info );
  725.      return -1;
  726.     }
  727.     // Spock end
  728.     if ( dbi < 0 ){
  729.      log( "dbUpdateEntryInt: dbGetTableIndex failn");
  730.      return -1;
  731.     }
  732.     hashind = tableGetEntry( dbi , key );
  733.     if ( hashind < 0 )
  734.     {
  735.      dbind = dbAllocNode();
  736.      if ( dbind < 0 )
  737.      {
  738.          log( "dbUpdateEntryInt: dbAllocNode failn" );
  739.          return -1;
  740.      }
  741.      master_buf[dbind].ivalue = value;
  742.      strcpy( master_buf[dbind].key , key );
  743.      strcpy( master_buf[dbind].charvalue , info );
  744.      if ( dbInsertNodeByIValue( dbt[dbi].toplinkindex , dbind ) < 0 )
  745.      {
  746.          master_buf[dbind].use = 0;
  747.          log( "dbUpdateEntryInt: dbInsertNodeByIValue failn" );
  748.          return -1;
  749.      }
  750.      if ( tableInsertNode( dbi , key , dbind ) < 0 )
  751.      {
  752.          dbReleaseNode( dbind );
  753.          log( "dbUpdateEntryInt: tableInsertNode failn" );
  754.          return -1;
  755.      }
  756.     }
  757.     else
  758.     {
  759.      dbind = dbt[dbi].hashtable[hashind].dbind;
  760.      master_buf[dbind].ivalue = value;
  761.      strcpy( master_buf[dbind].charvalue , info );
  762.      newpos = dbind;
  763.      while ( master_buf[newpos].prev >= 0 )
  764.      {
  765.            if ( value <= master_buf[master_buf[newpos].prev].ivalue )
  766.          {
  767.           break;
  768.          }
  769.          newpos = master_buf[newpos].prev;
  770.      }
  771.      if ( newpos != dbind )
  772.      {
  773.          master_buf[master_buf[dbind].prev].next = master_buf[dbind].next;
  774.             if ( master_buf[dbind].next >= 0 )
  775.              master_buf[master_buf[dbind].next].prev = master_buf[dbind].prev;
  776.          master_buf[dbind].prev = master_buf[newpos].prev;
  777.          master_buf[dbind].next = newpos;
  778.          if ( master_buf[newpos].prev >= 0 )
  779.              master_buf[master_buf[newpos].prev].next = dbind;
  780.          master_buf[newpos].prev = dbind;
  781.          dbt[dbi].updated = 1;
  782. /*
  783.     log( "dbUpdateEntryInt: successfully updated entry %s:%s:%dn",
  784.         table, key, value );
  785. */
  786.          return 0;
  787.      }
  788.      while ( master_buf[newpos].next >= 0 )
  789.      {
  790.          if ( value >= master_buf[master_buf[newpos].next].ivalue )
  791.          {
  792.           break;
  793.          }
  794.     newpos = master_buf[newpos].next;
  795.      }
  796.      if ( newpos != dbind )
  797.      {
  798.          master_buf[master_buf[dbind].prev].next = master_buf[dbind].next;
  799.          master_buf[master_buf[dbind].next].prev = master_buf[dbind].prev;
  800.          master_buf[dbind].prev = newpos;
  801.          master_buf[dbind].next = master_buf[newpos].next;
  802.          if ( master_buf[newpos].next >= 0 )
  803.              master_buf[master_buf[newpos].next].prev = dbind;
  804.          master_buf[newpos].next = dbind;
  805.      }
  806.     }
  807.     dbt[dbi].updated = 1;
  808. /*
  809.     log( "dbUpdateEntryInt: successfully updated entry %s:%s:%dn",
  810.              table, key, value );
  811.  */
  812.     return 0;
  813. }
  814. // Spock end
  815. int
  816. dbDeleteEntryInt( char *table, char *key )
  817. {
  818.     int dbi = dbGetTableIndex( table , DB_INT_SORTED );
  819.     int r;
  820.     if ( strlen( key ) >= KEY_MAX ) {
  821.      log( "dbDeleteEntryInt: key is too long, key:%sn", key );
  822.      return -1;
  823.     }
  824.     if( dbi < 0 ) {
  825.      log( "dbDeleteEntryInt: dbGetTableIndex failed for %sn", table );
  826.      return -1;
  827.     }
  828.     //r = dbExtractNodeByKey( dbt[dbi].toplinkindex , key );
  829.     // Spock fixed 2000/10/19
  830.     r = dbExtractNodeByKey( dbi , key );
  831.     if( r < 0 ){
  832.         log( "dbDeleteEntryInt: dbExtractNodeByKey failed for %s in %sn",
  833.              key,table );
  834.         return -1;
  835.     }
  836.     // Spock +1 2000/10/19
  837.     dbt[dbi].updated = 1;
  838.     log( "删除人物 %s 来至表 %sn", key, table );
  839.     return 0;
  840. }
  841. static void
  842. dbShowAllTable(void)
  843. {
  844.     int i;
  845.     for(i=0;i<MAXTABLE;i++){
  846.         if( dbt[i].use ){
  847.             log( "%d Name:%s Use:%d Type:%dn",i,
  848.                      dbt[i].name , dbt[i].num , dbt[i].type );
  849.         }
  850.     }
  851.     
  852. }
  853. /* 犯□正毛1蜊潸曰分允[
  854.  */
  855. int
  856. dbGetEntryInt( char *table, char *key, int *output )
  857. {
  858.     int dbi = dbGetTableIndex( table , DB_INT_SORTED );
  859.     int entind;
  860.     // Spock +1 2000/10/19
  861.     int hashind;
  862.  
  863.     // Spock deleted 2000/10/19
  864.     //if( strlen(key) >= sizeof( master_buf[entind].key) ) return -1;
  865.     if( dbi <0 ) {
  866.      log( "dbGetEntryInt: dbGetTableIndex failn" );
  867.      return -1;
  868.     }
  869.     // Spock 2000/10/19
  870.     if( strlen(key) >= KEY_MAX ) {
  871.      log( "dbGetEntryInt: key is too long, key:%sn" , key );
  872.      return -1;
  873.     }
  874.     hashind = tableGetEntry( dbi , key );
  875.     if( hashind < 0 ) return -1;
  876.     entind = dbt[dbi].hashtable[hashind].dbind;
  877.     //entind = dbGetEntryByKey( dbt[dbi].toplinkindex , key );
  878.     // Spock end
  879.     if( entind < 0 ) {
  880.      log( "dbGetEntryInt: Invalid dbind in hashtable of %sn" , table );
  881.      return -1;
  882.     }
  883.     /* 心勾井匀凶及匹袄毛请  卞  木化忒允 */
  884.     *output = master_buf[entind].ivalue;
  885.     return 0;
  886. }
  887. /*
  888.   巨仿□及桦宁反  [0分匀凶日岳  [
  889.   int *rank_out : 仿件弁及请  
  890.   int *count_out : 晓井日窒蜊  井及请  
  891.   int 犯□正矛□旦毁迕友
  892.   
  893.  */
  894. int
  895. dbGetEntryRank( char *table, char *key , int *rank_out, int *count_out)
  896. {
  897.     int dbi = dbGetTableIndex( table , DB_INT_SORTED );
  898.     // Spock deleted 2000/10/19
  899.     //unsigned int hash = hashpjw(key);
  900.     int cur;
  901.     int now_score = 0x7fffffff;     /*int 匹中切壬氏匹井中袄 */
  902.     int r = -1 , i=0;
  903.     // Spock 2000/10/23
  904.     //if( strlen(key) >= sizeof( master_buf[cur].key) ) return -1;
  905.     if( strlen(key) >= KEY_MAX ) {
  906.      log( "dbGetEntryRank: key is too long, key:%sn" , key );
  907.      return -1;
  908.     }
  909.     if( dbi <0 ) {
  910.      log( "dbGetEntryRank: dbGetTableIndex failn" );
  911.      return -1;
  912.     }
  913.     // Spock end
  914.     // Spock 2000/10/23
  915.     //cur = master_buf[dbt[dbi].toplinkindex].nextind;
  916.     cur = master_buf[dbt[dbi].toplinkindex].next;
  917.     //i=0;
  918.     //for(;;){
  919.     //    if( cur == -1 )break;
  920.     while ( cur >= 0 )
  921.     {
  922.     // Spock end
  923.         if( master_buf[cur].ivalue != now_score ){
  924.             r=i;
  925.             now_score = master_buf[cur].ivalue;
  926.         }
  927.         // Spock 2000/10/19
  928.         //if( hash == master_buf[cur].keyhash &&
  929.         //    strcmp( master_buf[cur].key, key )== 0 ){
  930.         if( strcmp( master_buf[cur].key , key ) == 0 )
  931.         {
  932.         // Spock end
  933.             *rank_out = r;
  934.             *count_out = i;
  935.             return 0;
  936.         }
  937.         //cur = master_buf[cur].nextind;
  938.         // Spock fixed 2000/10/19
  939.         cur = master_buf[cur].next;
  940.         i++;
  941.     }
  942.     *count_out = i;
  943.     *rank_out = r;
  944.     return 0;
  945. }
  946. /*
  947.   int 毁迕友
  948.  */
  949. int
  950. dbGetEntryRankRange( char *table,
  951.                      int start, int end, char *output, int outlen )
  952. {
  953. #define MAXHITS 1024        /* 赝癫支卅丐[匹手仇木匹蜗坌日仄中冗 ringo */
  954.     struct hitent{          /* 仇及厌瞻  卞甲永玄仄凶支勾毛凶户化中仁 */
  955.         int entind;
  956.         int rank;
  957.     };
  958.     int r=0;
  959.     struct hitent hits[MAXHITS];
  960.     int dbi = dbGetTableIndex( table , DB_INT_SORTED );
  961.     int cur;
  962.     int hitsuse = 0,i;
  963.     int now_score = 0x7fffffff;
  964.     if( dbi <0 ) return -1;
  965.     if( outlen <= 0 )return -1;
  966.     
  967.     cur = dbt[dbi].toplinkindex;
  968.     // Spock 2000/10/23
  969.     //for(;;){
  970.     //    if( cur == -1 )break;
  971.     while ( cur >= 0 )
  972.     {
  973.     // Spock end
  974.         if( master_buf[cur].ivalue != now_score ){
  975.             r++;
  976.             now_score = master_buf[cur].ivalue;
  977.         }
  978.         if( r >= start && r <= end ){
  979.             hits[hitsuse].entind = cur;
  980.             hits[hitsuse].rank = r;
  981.             hitsuse++;
  982.             //if( hitsuse == MAXHITS )break;
  983.             // Spock fixed 2000/10/23
  984.             if( hitsuse >= MAXHITS ) break;
  985.         }
  986.         //cur = master_buf[cur].nextind;
  987.         // Spock fixed 2000/10/19
  988.         cur = master_buf[cur].next;
  989.     }
  990.     output[0] = 0;
  991.     
  992.     for(i=0;i<hitsuse;i++){
  993.         char tmp[1024];
  994.         snprintf( tmp, sizeof(tmp),
  995.                   "%d,%s,%d,%s", hits[i].rank, master_buf[hits[i].entind].key,
  996.                   master_buf[hits[i].entind].ivalue,
  997. //             dbGetString( master_buf[i].charvalue_index ));
  998. // Spock fixed 2000/10/19
  999.   master_buf[hits[i].entind].charvalue );
  1000.         strcatsafe( output, outlen, tmp );
  1001.         if( i != ( hitsuse -1 ) ){
  1002.             strcatsafe( output, outlen, "|" );
  1003.         }
  1004.     }
  1005.     return 0;
  1006. }
  1007. int dbFlush( char *dir )
  1008. {
  1009.     int i;
  1010.     for(i=0;i<MAXTABLE;i++){
  1011.         FILE *fp;
  1012.         char filename[1024];
  1013.         int entind;
  1014.         //int j;
  1015.         if( !dbt[i].use ) continue;
  1016.         // Spock 2000/10/23
  1017.         if( dbt[i].updated == 0 )
  1018.         {
  1019.             log( "dbFlush: table %s not updatedn" , dbt[i].name );
  1020.             continue;
  1021.         }
  1022.         // Spock end
  1023.         if( dbt[i].type == DB_INT_SORTED ){
  1024.             snprintf( filename, sizeof(filename),
  1025.                       "%s/int/%s", dir, dbt[i].name );
  1026.         } else {
  1027.             snprintf( filename, sizeof( filename),
  1028.                       "%s/string/%s", dir, dbt[i].name );
  1029.         }
  1030.         
  1031.         fp = fopen( filename, "w" );
  1032.         if( fp == NULL ){
  1033.             log( "cannot open file: %s %sn", filename, strerror( errno ));
  1034.             continue;
  1035.         }
  1036.         // Spock 2000/10/19
  1037.         //entind = master_buf[dbt[i].toplinkindex].nextind;
  1038.         entind = master_buf[dbt[i].toplinkindex].next;
  1039.         //for(j=0;;j++){
  1040.         //    if( entind == -1 )break;
  1041.         while ( entind >= 0 )
  1042.         {
  1043.         // Spock end
  1044.             if( dbt[i].type == DB_INT_SORTED ){
  1045.                 fprintf( fp , "%s %d %sn", master_buf[entind].key,
  1046.                          master_buf[entind].ivalue,
  1047.                          //makeStringFromEscaped(
  1048.                          //    dbGetString(master_buf[entind].charvalue_index)));
  1049.                          // Spock fixed 2000/10/19
  1050.                          makeStringFromEscaped(master_buf[entind].charvalue));
  1051.             } else {
  1052.                 fprintf( fp , "%s %sn", master_buf[entind].key,
  1053.                          //makeStringFromEscaped(
  1054.                          //    dbGetString(master_buf[entind].charvalue_index)));
  1055.                          // Spock fixed 2000/10/19
  1056.                          makeStringFromEscaped(master_buf[entind].charvalue));
  1057.             }
  1058.             //entind = master_buf[entind].nextind;
  1059.             // Spock fixed 2000/10/19
  1060.             entind = master_buf[entind].next;
  1061.         }
  1062.         fclose(fp);
  1063.         dbt[i].updated = 0;
  1064.     }
  1065.     return 0;
  1066. }
  1067. int dbRead( char *dir )
  1068. {
  1069.     char dirname[1024];
  1070.     DIR *d;
  1071.     struct dirent *de;
  1072.     // Spock +1 2000/10/19
  1073.     memset( dbt , 0 , MAXTABLE * sizeof(struct table) );
  1074.     {
  1075.         char tmp[1024];
  1076.         snprintf( tmp, sizeof( tmp ), "%s/int" , dir );
  1077.         if( mkdir( tmp, 0755 )==0){
  1078.             log( "创建 %sn", tmp );
  1079.         }
  1080.         snprintf( tmp, sizeof( tmp ), "%s/string" , dir );
  1081.         if( mkdir( tmp, 0755 )==0){
  1082.             log( "创建 %sn", tmp );
  1083.         }        
  1084.     }
  1085.         
  1086.     snprintf( dirname, sizeof( dirname ),
  1087.               "%s/int" , dir );
  1088.     d = opendir(dirname);
  1089.     if( d == NULL ){
  1090.         log( "不能打开文件 %sn", dirname );
  1091.         return -1;
  1092.     }
  1093.     while(1){
  1094.         de = readdir( d );
  1095.         if( de == NULL )break;
  1096.         if( de->d_name[0] != '.' ){
  1097.             char filename[1024];
  1098.             FILE *fp;
  1099.             struct stat s;
  1100.             snprintf( filename, sizeof(filename),"%s/%s",dirname, de->d_name );
  1101. log( "读取数据:%sn..", filename);
  1102.             if( stat( filename, &s ) < 0 ){
  1103.                 continue;
  1104.             }
  1105.             if( !( s.st_mode & S_IFREG ) ){
  1106.                 continue;
  1107.             }
  1108.             
  1109.             fp = fopen( filename, "r" );            
  1110.             if( fp == NULL ){
  1111.                 log( "不能打开文件 %s %sn",
  1112.                          filename, strerror( errno ));
  1113.                 continue;
  1114.             }
  1115.             while(1){
  1116.                 char line[1024];
  1117.                 char k[1024] , v[1024], info[1024];
  1118.                 if( fgets( line , sizeof( line) , fp ) == NULL )break;
  1119.                 chop( line);
  1120. k[0] = '';
  1121.                 easyGetTokenFromString( line, 1, k, sizeof(k));
  1122. v[0] = '';
  1123.                 easyGetTokenFromString( line, 2, v, sizeof(v));
  1124.                 info[0] = '';
  1125.                 easyGetTokenFromString( line, 3, info, sizeof(info));
  1126.                 dbUpdateEntryInt( de->d_name, k, atoi(v), info);
  1127.             }
  1128.             fclose(fp);
  1129.         }
  1130.     }
  1131.     closedir(d);
  1132.     snprintf( dirname, sizeof( dirname), "%s/string" , dir );
  1133.     d = opendir( dirname );
  1134.     if( d == NULL ){
  1135.         log( "不能打开文件 %sn", dirname );
  1136.         return -1;
  1137.     }
  1138.     while(1){
  1139.         de = readdir( d );
  1140.         if( de == NULL )break;
  1141.         if( de->d_name[0] != '.' ){
  1142.             char filename[1024];
  1143.             FILE *fp;
  1144.             struct stat s;
  1145.             snprintf( filename, sizeof( filename),"%s/%s",dirname,de->d_name );
  1146. log( "读取数据:%sn..", filename);
  1147.             if( stat( filename, &s ) < 0 ){
  1148.                 continue;
  1149.             }
  1150.             if( !(s.st_mode & S_IFREG )){
  1151.                 continue;
  1152.             }
  1153.             fp = fopen( filename, "r" );
  1154.             if( fp == NULL ){
  1155.                 log( "不能打开文件 %s %sn",
  1156.                      filename, strerror(errno ));
  1157.                 continue;
  1158.             }
  1159.             while(1){
  1160.                 char line[CHARVALUE_MAX+1024];     
  1161.                 char k[1024];
  1162.                 if( fgets( line, sizeof( line), fp ) == NULL )break;
  1163.                 /* chop */
  1164.                 chop(line);
  1165. k[0] = '';
  1166.                 easyGetTokenFromString( line, 1, k,sizeof(k));
  1167.                 dbUpdateEntryString( de->d_name, k, line+strlen(k)+1);
  1168.             }
  1169.             // Nuke +1 1027: Close for safe
  1170.             fclose(fp); 
  1171.         }
  1172.     }
  1173.     closedir(d);
  1174.     return 0;
  1175. }
  1176. /* 隙烂仄凶匏  井日隙烂仄凶蜊醒潸曰分允[
  1177.  撩  仄凶日  }岳  仄凶日0[岳  仄化手坞及请  及午五互丐月冗[
  1178.    “num互0及午五午井}竟癫允月巨件玄伉互卅中午五[
  1179.  int 犯□正矛□旦毁迕分冗
  1180.  */
  1181. int dbGetEntryCountRange( char *table, int count_start, int  num,
  1182.                       char *output, int outlen )
  1183. {
  1184.     int dbi = dbGetTableIndex( table , DB_INT_SORTED );
  1185.     int cur;
  1186.     int i;
  1187.     int now_score = 0x7fffffff , r;
  1188.     if( dbi < 0) return -1;
  1189.     if( outlen < 1 ) return -1;
  1190.     output[0]=0;
  1191.     //cur = master_buf[dbt[dbi].toplinkindex].nextind;
  1192.     // Spock fixed 2000/10/19
  1193.     cur = master_buf[dbt[dbi].toplinkindex].next;
  1194.     i=0;
  1195.     r=0;
  1196.     for(;;){
  1197.         if( cur == -1 ) break;
  1198.         if( master_buf[cur].ivalue != now_score ){
  1199.             r=i;
  1200.             now_score = master_buf[cur].ivalue;
  1201.         }
  1202.         if( ( i >= count_start ) &&
  1203.             ( i < (count_start + num ) ) ){
  1204.             char tmp[1024];            
  1205.             if( (i !=count_start)){
  1206.                 strcatsafe( output, outlen, "|" );
  1207.             } 
  1208.               
  1209.             snprintf( tmp, sizeof( tmp),
  1210.                       "%d,%d,%s,%d,%s", i, r, master_buf[cur].key,
  1211.                       master_buf[cur].ivalue,
  1212.             //dbGetString( master_buf[cur].charvalue_index ));
  1213.       // Spock fixed 2000/10/19
  1214.       master_buf[cur].charvalue);
  1215.             strcatsafe( output, outlen,tmp );
  1216.         }
  1217.         i++;
  1218.         //cur = master_buf[cur].nextind;
  1219.         // Spock fixed 2000/10/19
  1220.         cur = master_buf[cur].next;
  1221.     }
  1222.     return 0;
  1223. }
  1224. /*
  1225.     侬  犯□正矛□旦及质  
  1226.  */
  1227. /* Spock deleted 2000/10/19
  1228. int
  1229. dbUpdateEntryString( char *table, char *key, char *value )
  1230. {
  1231.     int dbi = dbGetTableIndex(table, DB_STRING);
  1232.     int r, entind;
  1233.     
  1234.     log( "dbUpdateEntryString: [%s] [%s] [%s]n", table, key, value );
  1235.     
  1236.     if( strlen(key) >= sizeof(master_buf[0].key) )return -1;
  1237.     if( dbi < 0 )return -1;
  1238.     r = dbExtractNodeByKey( dbt[dbi].toplinkindex, key );
  1239.     if( r< 0 ){
  1240.         log( "dbUpdateEntryString dbExtractNodeByKey fail! bug!!n" );
  1241.         return -1;
  1242.     }
  1243.     entind = dbAllocNode( DB_STRING );
  1244.     if( entind < 0 ) return -1;
  1245.     master_buf[entind].ivalue = 0;
  1246.     dbSetString( master_buf[entind].charvalue_index, value );
  1247.     snprintf( master_buf[entind].key,
  1248.               sizeof(master_buf[0].key), "%s",key );
  1249.     master_buf[entind].keyhash = hashpjw( master_buf[entind].key );
  1250.     master_buf[entind].nextind = -1;
  1251.     if(  dbAppendNode( dbt[dbi].toplinkindex, entind ) < 0 ){
  1252.         log( "dbUpdateEntryString: dbAppendNode failedn" );
  1253.         return -1;
  1254.     }
  1255.     log( "dbUpdateEntryString: successfully updated entry %s:%s:%sn",
  1256.          table,key,value );
  1257.     return 0;
  1258. }
  1259. */
  1260. // Spock 2000/10/19
  1261. int dbUpdateEntryString( char *table, char *key, char *value )
  1262. {
  1263.     int dbi = dbGetTableIndex( table , DB_STRING );
  1264.     int dbind, hashind;
  1265.     if ( strlen( key ) >= KEY_MAX ) {
  1266.      log( "dbUpdateEntryString: key is too long, key:%sn", key );
  1267.      return -1;
  1268.     }
  1269.     if ( strlen( value ) >= CHARVALUE_MAX ) {
  1270.      log( "dbUpdateEntryString: charvalue is too long, charvalue:%sn", value );
  1271.      return -1;
  1272.     }
  1273.     if ( dbi < 0 ) {
  1274.      log( "dbUpdateEntryString: dbGetTableIndex fail, table:%sn", table );
  1275.      return -1;
  1276.     }
  1277.     hashind = tableGetEntry( dbi , key );
  1278.     if ( hashind < 0 )
  1279.     {
  1280.      dbind = dbAllocNode();
  1281.      if ( dbind < 0 )
  1282.      {
  1283.          log( "dbUpdateEntryString: dbAllocNode failn" );
  1284.          return -1;
  1285.      }
  1286.      strcpy( master_buf[dbind].key , key );
  1287.      strcpy( master_buf[dbind].charvalue , value );
  1288.      if ( dbAppendNode( dbt[dbi].toplinkindex , dbind ) < 0 )
  1289.      {
  1290.          master_buf[dbind].use = 0;
  1291.          log( "dbUpdateEntryString: dbAppendNode failn" );
  1292.          return -1;
  1293.      }
  1294.      if ( tableInsertNode( dbi , key , dbind ) < 0 )
  1295.      {
  1296.          dbReleaseNode( dbind );
  1297.     log( "dbUpdateEntryString: tableInsertNode failn" );
  1298.     return -1;
  1299. }
  1300.     }
  1301.     else
  1302.     {
  1303.      dbind = dbt[dbi].hashtable[hashind].dbind;
  1304.      strcpy( master_buf[dbind].charvalue , value );
  1305.     }
  1306.     dbt[dbi].updated = 1;
  1307. /*
  1308.     log( "dbUpdateEntryString: successfully updated entry %s:%s:%sn",
  1309.          table,key,value );
  1310.  */
  1311.     return 0;
  1312. }
  1313. // Spock end
  1314. int
  1315. dbGetEntryString( char *table, char *key, char *output, int outlen )
  1316. {
  1317.     int dbi = dbGetTableIndex( table, DB_STRING );
  1318.     int entind;
  1319.     // Spock +1 2000/10/19
  1320.     int hashind;
  1321.     // Spock 2000/10/23
  1322.     //if( strlen(key) >= sizeof( master_buf[entind].key) ) return -1;
  1323.     if ( strlen(key) >= KEY_MAX ) {
  1324.      log( "dbGetEntryString: key is too long, key:%sn", key );
  1325.      return -1;
  1326.     }
  1327.     if( dbi <0 ) {
  1328.      log( "dbGetEntryString: dbGetTableIndex failn" );
  1329.      return -1;
  1330.     }
  1331.     // Spock 2000/10/19
  1332.     hashind = tableGetEntry( dbi , key );
  1333.     if ( hashind < 0 ){
  1334. log("err hashind <0n")
  1335. return -1;
  1336. }
  1337.     entind = dbt[dbi].hashtable[hashind].dbind;
  1338.     if ( entind < 0 ){
  1339. log( "entind < 0 ");
  1340. return -1;
  1341. }
  1342.     snprintf( output , outlen , "%s" , master_buf[entind].charvalue );
  1343.     return 0;
  1344. }
  1345. int
  1346. dbDeleteEntryString( char *table, char *key )
  1347. {
  1348.     int dbi = dbGetTableIndex( table, DB_STRING );
  1349.     int r;
  1350.     // Spock 2000/10/23
  1351.     //if( strlen(key) >= sizeof( master_buf[entind].key) ) return -1;
  1352.     if ( strlen(key) >= KEY_MAX ) {
  1353.      log( "dbDeleteEntryString: key is too long, key:%sn", key );
  1354.      return -1;
  1355.     }
  1356.     if( dbi <0 ) {
  1357.      log( "dbDeleteEntryString: dbGetTableIndex failn" );
  1358.      return -1;
  1359.     }
  1360.     // Spock end
  1361.     //r = dbExtractNodeByKey( dbt[dbi].toplinkindex, key );
  1362.     // Spock fixed 2000/10/19
  1363.     r = dbExtractNodeByKey( dbi , key );
  1364.     if( r < 0 ){
  1365.         log( "dbDeleteEntryString: dbExtractNodeByKey failed for %s in %sn",
  1366.              key,table );
  1367.         return -1;
  1368.     }
  1369.     dbt[dbi].updated = 1;
  1370.     log( "删除人物 %s 来至表 %sn", key, table );
  1371.     return 0;
  1372. }