Hatena::Grouptechmemo

msyktの日記

2011-08-12

[TCTDB]tctdbclose

23:24

/* Close a table database object. */
bool tctdbclose(TCTDB *tdb){
  assert(tdb);
  if(!TDBLOCKMETHOD(tdb, true)) return false;
  if(!tdb->open){
    tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
    TDBUNLOCKMETHOD(tdb);
    return false;
  }
  bool rv = tctdbcloseimpl(tdb);
  TDBUNLOCKMETHOD(tdb);
  return rv;
}
  1. メソッドロック取得
  2. table databaseをclose(tctdbcloseimpl)
  3. メソッドロックを解放

[TCTDB]tctdbcloseimpl

00:00

/* Abort the transaction of a table database object.                                                                                                                         
   `tdb' specifies the table database object.                                                                                                                                
   If successful, the return value is true, else, it is false. */
static bool tctdbtranabortimpl(TCTDB *tdb){
  assert(tdb);
  bool err = false;
  if(!tchdbtranabort(tdb->hdb)) err = true;
  TDBIDX *idxs = tdb->idxs;
  int inum = tdb->inum;
  for(int i = 0; i < inum; i++){
    TDBIDX *idx = idxs + i;
    switch(idx->type){
      case TDBITTOKEN:
      case TDBITQGRAM:
        tcmapclear(idx->cc);
        break;
    }
  }  
  for(int i = 0; i < inum; i++){
    TDBIDX *idx = idxs + i;
    switch(idx->type){
      case TDBITLEXICAL:
      case TDBITDECIMAL:
      case TDBITTOKEN:
      case TDBITQGRAM:
        if(!tcbdbtranabort(idx->db)){
          tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
          err = true;
        }
        break;
    }
  }
  return !err;
}
  1. hash databaseのtransactionをabort
  2. 各indexに対応するB+tree databaseのtransactionをabort
/* Abort the transaction of a hash database object. */
=>ol tchdbtranabort(TCHDB *hdb){  assert(hdb);
  if(!HDBLOCKMETHOD(hdb, true)) return false;
  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER) || !hdb->tran){
    tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
    HDBUNLOCKMETHOD(hdb);
    return false;
  }
  bool err = false;
  if(hdb->async && !tchdbflushdrp(hdb)) err = true;
  if(!tchdbmemsync(hdb, false)) err = true;
  if(!tchdbwalrestore(hdb, hdb->path)) err = true;
  char hbuf[HDBHEADSIZ];
  if(lseek(hdb->fd, 0, SEEK_SET) == -1){
    tchdbsetecode(hdb, TCESEEK, __FILE__, __LINE__, __func__);
    err = false;
  } else if(!tcread(hdb->fd, hbuf, HDBHEADSIZ)){
    tchdbsetecode(hdb, TCEREAD, __FILE__, __LINE__, __func__);
    err = false;
  } else {
    tchdbloadmeta(hdb, hbuf);
  }
  hdb->dfcur = hdb->frec;
  hdb->iter = 0;
  hdb->xfsiz = 0;
  hdb->fbpnum = 0;
  if(hdb->recc) tcmdbvanish(hdb->recc);
  hdb->tran = false;
  HDBUNLOCKMETHOD(hdb);
  return !err;
}
  1. 非同期であれば、deleyed record poolの内容をmapped memory書き込み
  2. hash database等のメタ情報をmapped memoryに書き込み
  3. Write-Ahead Logging (WAL)によるリストア
  4. メタ情報をmapped memoryから読み直してhash databaseに設定する
/* Abort the transaction of a B+ tree database object. */
=>ol tcbdbtranabort(TCBDB *bdb){  assert(bdb);
  if(!BDBLOCKMETHOD(bdb, true)) return false;
  if(!bdb->open || !bdb->wmode || !bdb->tran){
    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
    BDBUNLOCKMETHOD(bdb);
    return false;
  }
  tcbdbcachepurge(bdb);
  memcpy(bdb->opaque, bdb->rbopaque, BDBOPAQUESIZ);
  tcbdbloadmeta(bdb);
  TCFREE(bdb->rbopaque);
  bdb->tran = false;
  bdb->rbopaque = NULL;
  bdb->hleaf = 0;
  bdb->lleaf = 0;
  bdb->clock++;
  bool err = false;
  if(!tcbdbcacheadjust(bdb)) err = true;
  if(!tchdbtranvoid(bdb->hdb)) err = true;
  BDBUNLOCKMETHOD(bdb);
  return !err;
}
  1. dirtyなcache pageをクリア
  2. opaqueバッファロールバックopaqueバッファの内容を書き込む
  3. opaqueバッファからメタデータを取り出し、B+ tree databaseに設定する
  4. B+ tree databaseのcache(leaf/node)のアジャスト
  5. 内部のhash databaseのロックを取って、hdb->tran = false

[TCTDB]tchdbmemsync

00:00

/* Synchronize updating contents on memory of a hash database object. */
=>ol tchdbmemsync(TCHDB *hdb, bool phys){  assert(hdb);
  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
    tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
    return false;
  }
  bool err = false;
  char hbuf[HDBHEADSIZ];
  tchdbdumpmeta(hdb, hbuf);
  memcpy(hdb->map, hbuf, HDBOPAQUEOFF);
  if(phys){
    size_t xmsiz = (hdb->xmsiz > hdb->msiz) ? hdb->xmsiz : hdb->msiz;
    if(msync(hdb->map, xmsiz, MS_SYNC) == -1){
      tchdbsetecode(hdb, TCEMMAP, __FILE__, __LINE__, __func__);
      err = true;
    }    if(fsync(hdb->fd) == -1){
      tchdbsetecode(hdb, TCESYNC, __FILE__, __LINE__, __func__);
      err = true;
    }
  }
  return !err;
}
  1. hbufにhash databaseのメタ情報(下記コード参照)を書き込む
  2. hash databaseのmapped memoryにメタ情報をコピー
  3. pyhsがtrueの場合、mapped memoryをファイルに同期する
/* Serialize meta data into a buffer.                                                                                                                                        
   `hdb' specifies the hash database object.                                                                                                                                 
   `hbuf' specifies the buffer. */
=>atic void tchdbdumpmeta(TCHDB *hdb, char *hbuf){  memset(hbuf, 0, HDBHEADSIZ);
  sprintf(hbuf, "%s\n%s:%d\n", HDBMAGICDATA, _TC_FORMATVER, _TC_LIBVER);
  memcpy(hbuf + HDBTYPEOFF, &(hdb->type), sizeof(hdb->type));
  memcpy(hbuf + HDBFLAGSOFF, &(hdb->flags), sizeof(hdb->flags));
  memcpy(hbuf + HDBAPOWOFF, &(hdb->apow), sizeof(hdb->apow));
  memcpy(hbuf + HDBFPOWOFF, &(hdb->fpow), sizeof(hdb->fpow));
  memcpy(hbuf + HDBOPTSOFF, &(hdb->opts), sizeof(hdb->opts));
  uint64_t llnum;
  llnum = hdb->bnum;
  llnum = TCHTOILL(llnum);
  memcpy(hbuf + HDBBNUMOFF, &llnum, sizeof(llnum));
  llnum = hdb->rnum;
  llnum = TCHTOILL(llnum);
  memcpy(hbuf + HDBRNUMOFF, &llnum, sizeof(llnum));
  llnum = hdb->fsiz;  llnum = TCHTOILL(llnum);
  memcpy(hbuf + HDBFSIZOFF, &llnum, sizeof(llnum));
  llnum = hdb->frec;
  llnum = TCHTOILL(llnum);
  memcpy(hbuf + HDBFRECOFF, &llnum, sizeof(llnum));
}