Hatena::Grouptechmemo

msyktの日記

2011-08-11TokyoCabinetのTDBのコードを読む

[TCTDB]tctdbopenimpl

22:57

/* Open a database file and connect a table database object.                         
   `tdb' specifies the table database object.                                        
   `path' specifies the path of the internal database file.                          
   `omode' specifies the connection mode.                                            
   If successful, the return value is true, else, it is false. */
=>atic bool tctdbopenimpl(TCTDB *tdb, const char *path, int omode){
  assert(tdb && path);
  int dbgfd = tchdbdbgfd(tdb->hdb);
  TCCODEC enc, dec;
  void *encop, *decop;
  tchdbcodecfunc(tdb->hdb, &enc, &encop, &dec, &decop);
  int homode = HDBOREADER;
  int bomode = BDBOREADER;
  if(omode & TDBOWRITER){
    homode = HDBOWRITER;
    bomode = BDBOWRITER;
    if(omode & TDBOCREAT){
      homode |= HDBOCREAT;
      bomode |= BDBOCREAT;
    }
    if(omode & TDBOTRUNC){
      homode |= HDBOTRUNC;
      bomode |= BDBOTRUNC;
    }
    tdb->wmode = true;
  } else {
    tdb->wmode = false;
  }
  if(omode & TDBONOLCK){
    homode |= HDBONOLCK;
    bomode |= BDBONOLCK;
  }
  if(omode & TDBOLCKNB){
    homode |= HDBOLCKNB;
    bomode |= BDBOLCKNB;
  }
  if(omode & TDBOTSYNC){
    homode |= HDBOTSYNC;
    bomode |= BDBOTSYNC;
  }
  tchdbsettype(tdb->hdb, TCDBTTABLE);
  if(!tchdbopen(tdb->hdb, path, homode)) return false;
  char *tpath = tcsprintf("%s%c%s%c*", path, MYEXTCHR, TDBIDXSUFFIX, MYEXTCHR);
  if((omode & TDBOWRITER) && (omode & TDBOTRUNC)){
    TCLIST *paths = tcglobpat(tpath);
    int pnum = TCLISTNUM(paths);
    for(int i = 0; i < pnum; i++){
      unlink(TCLISTVALPTR(paths, i));
    }
    tclistdel(paths);
  }
  TCLIST *paths = tcglobpat(tpath);
  int pnum = TCLISTNUM(paths);
  TCMALLOC(tdb->idxs, sizeof(tdb->idxs[0]) * pnum + 1);
  TDBIDX *idxs = tdb->idxs;
  int inum = 0;
  for(int i = 0; i < pnum; i++){
    const char *ipath = TCLISTVALPTR(paths, i);
    if(!tcstrfwm(ipath, path)) continue;
    const char *rp = ipath + strlen(path);
    if(*rp != MYEXTCHR) continue;
    rp++;
    if(!tcstrfwm(rp, TDBIDXSUFFIX)) continue;
    rp += strlen(TDBIDXSUFFIX);
    if(*rp != MYEXTCHR) continue;
    rp++;
    char *stem = tcstrdup(rp);
    char *ep = strrchr(stem, MYEXTCHR);
    if(!ep) continue;
    *(ep++) = '\0';
    int nsiz;
    char *name = tcurldecode(stem, &nsiz);
    if(!strcmp(ep, "lex") || !strcmp(ep, "dec") || !strcmp(ep, "tok") || !strcmp(ep,\
 "qgr")){
      TCBDB *bdb = tcbdbnew();
      if(dbgfd >= 0) tcbdbsetdbgfd(bdb, dbgfd);
      if(tdb->mmtx) tcbdbsetmutex(bdb);
      if(enc && dec) tcbdbsetcodecfunc(bdb, enc, encop, dec, decop);
      tcbdbsetcache(bdb, tdb->lcnum, tdb->ncnum);
      tcbdbsetxmsiz(bdb, tchdbxmsiz(tdb->hdb));
      tcbdbsetdfunit(bdb, tchdbdfunit(tdb->hdb));
      tcbdbsetlsmax(bdb, TDBIDXLSMAX);
      if(tcbdbopen(bdb, ipath, bomode)){
        idxs[inum].name = tcstrdup(name);
        idxs[inum].type = TDBITLEXICAL;
        if(!strcmp(ep, "dec")){
          idxs[inum].type = TDBITDECIMAL;
        } else if(!strcmp(ep, "tok")){
          idxs[inum].type = TDBITTOKEN;
        } else if(!strcmp(ep, "qgr")){
          idxs[inum].type = TDBITQGRAM;
        }
        idxs[inum].db = bdb;
        idxs[inum].cc = NULL;
        if(idxs[inum].type == TDBITTOKEN){
          idxs[inum].cc = tcmapnew2(TDBIDXICCBNUM);
        } else if(idxs[inum].type == TDBITQGRAM){
          idxs[inum].cc = tcmapnew2(TDBIDXICCBNUM);
        }
        inum++;
      } else {
        tcbdbdel(bdb);
      }
    }
    TCFREE(name);
    TCFREE(stem);
  }
  tclistdel(paths);
  TCFREE(tpath);
  tdb->inum = inum;
  tdb->open = true;
  uint8_t hopts = tchdbopts(tdb->hdb);
  uint8_t opts = 0;
  if(hopts & HDBTLARGE) opts |= TDBTLARGE;
  if(hopts & HDBTDEFLATE) opts |= TDBTDEFLATE;
  if(hopts & HDBTBZIP) opts |= TDBTBZIP;
  if(hopts & HDBTTCBS) opts |= TDBTTCBS;
  if(hopts & HDBTEXCODEC) opts |= TDBTEXCODEC;
  tdb->opts = opts;
  tdb->tran = false;
  return true;
}
  1. tchdbdbgfd(hash databaseのファイルディスクリプタ(デバッグ用))を取得
  2. カスタムコーデック関数を取得
  3. 引数で指定されたomodeによって、hash database、B+tree databaseのモードを決める
  4. hash databaseのtypeにtable databaseセットする
  5. hash databaseをopen
  6. TDBOWRITER 且つ TDBOTRUNCであればインデックスファイルを消す?
  7. インデックス用のB+tree databaseをopen
  8. hash databaseのoptionを取り出して、その一部をtable databaseのoptionとして再設定
/* Get the custom codec functions of a hash database object. */
void tchdbcodecfunc(TCHDB *hdb, TCCODEC *ep, void **eop, TCCODEC *dp, void **dop){
  assert(hdb && ep && eop && dp && dop);
  *ep = hdb->enc;
  *eop = hdb->encop;
  *dp = hdb->dec;
  *dop = hdb->decop;
}
/* type of the pointer to a encoding or decoding function.                           
   `ptr' specifies the pointer to the region.                                        
   `size' specifies the size of the region.                                          
   `sp' specifies the pointer to the variable into which the size of the region of the return                                                                            
   value is assigned.                                                                
   `op' specifies the pointer to the optional opaque object.                         
   If successful, the return value is the pointer to the result object allocated with `malloc'                                                                           
   call, else, it is `NULL'. */
=>pedef void *(*TCCODEC)(const void *ptr, int size, int *sp, void *op);
enum {                                   /* enumeration for database type */
  TCDBTHASH,                             /* hash table */
  TCDBTBTREE,                            /* B+ tree */
  TCDBTFIXED,                            /* fixed-length */=>TCDBTTABLE                             /* table */
};