Hatena::Grouptechmemo

msyktの日記

2011-08-13

[TCTDB]tctdbput

22:54

/* Store a record into a table database object. */
bool tctdbput(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols){
  assert(tdb && pkbuf && pksiz >= 0 && cols);
  int vsiz;
  if(tcmapget(cols, "", 0, &vsiz)){
    tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
    return false;  }
  if(!TDBLOCKMETHOD(tdb, true)) return false;
  if(!tdb->open || !tdb->wmode){
    tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
    TDBUNLOCKMETHOD(tdb);
    return false;
  }
  bool rv = tctdbputimpl(tdb, pkbuf, pksiz, cols, TDBPDOVER);
  TDBUNLOCKMETHOD(tdb);
  return rv;
}
  1. table databaseのロックを取得
  2. tctdbputimpl
  3. table databaseのロックを解放

[TCTDB]tctdbputimpl

22:54

/* Store a record into a table database object.                                                                                                                              
   `tdb' specifies the table database object.                                                                                                                                
   `pkbuf' specifies the pointer to the region of the primary key.                                                                                                           
   `pksiz' specifies the size of the region of the primary key.                                                                                                              
   `cols' specifies a map object containing columns.                                                                                                                         
   `dmode' specifies behavior when the key overlaps.                                                                                                                         
   If successful, the return value is true, else, it is false. */
=>atic bool tctdbputimpl(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols, int dmode){
  assert(tdb && pkbuf && pksiz >= 0 && cols);
  bool err = false;
  int osiz;
  char *obuf = tchdbget(tdb->hdb, pkbuf, pksiz, &osiz);
  if(obuf){
    if(dmode == TDBPDKEEP){
      tctdbsetecode(tdb, TCEKEEP, __FILE__, __LINE__, __func__);
      TCFREE(obuf);
      return false;
    }
    TCMAP *ocols = tcmapload(obuf, osiz);
    if(dmode == TDBPDCAT){
      TCMAP *ncols = tcmapnew2(TCMAPRNUM(cols) + 1);
      tcmapiterinit(cols);
      const char *kbuf;
      int ksiz;
      while((kbuf = tcmapiternext(cols, &ksiz)) != NULL){
        int vsiz;
        const char *vbuf = tcmapiterval(kbuf, &vsiz);
        if(tcmapputkeep(ocols, kbuf, ksiz, vbuf, vsiz)) tcmapput(ncols, kbuf, ksiz, vbuf, vsiz);
      }
      if(!tctdbidxput(tdb, pkbuf, pksiz, ncols)) err = true;
      tcmapdel(ncols);
      int csiz;
      char *cbuf = tcmapdump(ocols, &csiz);
      if(!tchdbput(tdb->hdb, pkbuf, pksiz, cbuf, csiz)) err = true;
      TCFREE(cbuf);
    } else {      
      TCMAP *ncols = tcmapnew2(TCMAPRNUM(cols) + 1);
      tcmapiterinit(cols);
      const char *kbuf;
      int ksiz;
      while((kbuf = tcmapiternext(cols, &ksiz)) != NULL){
        int vsiz;
        const char *vbuf = tcmapiterval(kbuf, &vsiz);
        int osiz;
        const char *obuf = tcmapget(ocols, kbuf, ksiz, &osiz);
        if(obuf && osiz == vsiz && !memcmp(obuf, vbuf, osiz)){
          tcmapout(ocols, kbuf, ksiz);
        } else {
          tcmapput(ncols, kbuf, ksiz, vbuf, vsiz);
        }
      }
      if(!tctdbidxout(tdb, pkbuf, pksiz, ocols)) err = true;
      if(!tctdbidxput(tdb, pkbuf, pksiz, ncols)) err = true;
      tcmapdel(ncols);
      int csiz;      
      char *cbuf = tcmapdump(cols, &csiz);
      if(!tchdbput(tdb->hdb, pkbuf, pksiz, cbuf, csiz)) err = true;
      TCFREE(cbuf);
    }
    tcmapdel(ocols);
    TCFREE(obuf);
  } else {
    if(!tctdbidxput(tdb, pkbuf, pksiz, cols)) err = true;
    int csiz;
    char *cbuf = tcmapdump(cols, &csiz);
    if(!tchdbput(tdb->hdb, pkbuf, pksiz, cbuf, csiz)) err = true;
    TCFREE(cbuf);
  }
  return !err;
}
  1. 指定されたkeyで、hash databaseからエントリを取得
  2. エントリが存在していた場合、以下を実行
    1. dmodeがTDBPDKEEPならエラーで戻る
    2. dmodeがTDBPDCATの場合、以下を実行
      1. 元のmapにcolsの内容を加える
      2. 加えた分のindexを作成
    3. dmodeが(TDBPDKEEP/TDBPDCAT)以外の場合
      1. エントリ内に同一のkeyがあれば当該レコードを削除?(ncolsには登録しない?)
      2. エントリ内に同一のkeyがなければ新しいmapに詰めてhash databaseにput
      3. 旧エントリのindexを削除
      4. 新エントリのindexを作成
  3. エントリが存在していない場合、以下を実行
    1. 指定されたcolsをhash databaseにput

DenverDenver 2011/11/29 14:05 You really found a way to make this whole prosecs easier.

ruwxiysvruwxiysv 2011/11/30 00:36 TQ0a7a <a href="http://srfcwslcgnra.com/">srfcwslcgnra</a>

bkyurjuesmsbkyurjuesms 2011/12/02 23:56 GB3oru <a href="http://mlsskdztafdv.com/">mlsskdztafdv</a>

ゲスト



トラックバック - http://techmemo.g.hatena.ne.jp/msykt/20110813
リンク元