strings-table.c

来自「subversion-1.4.3-1.tar.gz 配置svn的源码」· C语言 代码 · 共 541 行 · 第 1/2 页

C
541
字号
static svn_error_t *get_key_and_bump(svn_fs_t *fs,                  const char **key,                  trail_t *trail,                 apr_pool_t *pool){  base_fs_data_t *bfd = fs->fsap_data;  DBC *cursor;  char next_key[MAX_KEY_SIZE];  apr_size_t key_len;  int db_err;  DBT query;  DBT result;  /* ### todo: see issue #409 for why bumping the key as part of this     trail is problematic. */  /* Open a cursor and move it to the 'next-key' value. We can then fetch     the contents and use the cursor to overwrite those contents. Since     this database allows duplicates, we can't do an arbitrary 'put' to     write the new value -- that would append, not overwrite.  */  svn_fs_base__trail_debug(trail, "strings", "cursor");  SVN_ERR(BDB_WRAP(fs, "creating cursor for reading a string",                   bfd->strings->cursor(bfd->strings, trail->db_txn,                                        &cursor, 0)));  /* Advance the cursor to 'next-key' and read it. */  db_err = cursor->c_get(cursor,                         svn_fs_base__str_to_dbt(&query, NEXT_KEY_KEY),                         svn_fs_base__result_dbt(&result),                         DB_SET);  if (db_err)    {      cursor->c_close(cursor);      return BDB_WRAP(fs, "getting next-key value", db_err);    }  svn_fs_base__track_dbt(&result, pool);  *key = apr_pstrmemdup(pool, result.data, result.size);  /* Bump to future key. */  key_len = result.size;  svn_fs_base__next_key(result.data, &key_len, next_key);  /* Shove the new key back into the database, at the cursor position. */  db_err = cursor->c_put(cursor, &query,                         svn_fs_base__str_to_dbt(&result, next_key),                         DB_CURRENT);  if (db_err)    {      cursor->c_close(cursor); /* ignore the error, the original is                                   more important. */      return BDB_WRAP(fs, "bumping next string key", db_err);    }  return BDB_WRAP(fs, "closing string-reading cursor",                  cursor->c_close(cursor));}svn_error_t *svn_fs_bdb__string_append(svn_fs_t *fs,                          const char **key,                          apr_size_t len,                          const char *buf,                          trail_t *trail,                          apr_pool_t *pool){  base_fs_data_t *bfd = fs->fsap_data;  DBT query, result;  /* If the passed-in key is NULL, we graciously generate a new string     using the value of the `next-key' record in the strings table. */  if (*key == NULL)    {      SVN_ERR(get_key_and_bump(fs, key, trail, pool));    }  /* Store a new record into the database. */  svn_fs_base__trail_debug(trail, "strings", "put");  SVN_ERR(BDB_WRAP(fs, "appending string",                   bfd->strings->put                   (bfd->strings, trail->db_txn,                    svn_fs_base__str_to_dbt(&query, *key),                    svn_fs_base__set_dbt(&result, buf, len),                    0)));  return SVN_NO_ERROR;}svn_error_t *svn_fs_bdb__string_clear(svn_fs_t *fs,                         const char *key,                         trail_t *trail,                         apr_pool_t *pool){  base_fs_data_t *bfd = fs->fsap_data;  int db_err;  DBT query, result;  svn_fs_base__str_to_dbt(&query, key);  /* Torch the prior contents */  svn_fs_base__trail_debug(trail, "strings", "del");  db_err = bfd->strings->del(bfd->strings, trail->db_txn, &query, 0);  /* If there's no such node, return an appropriately specific error.  */  if (db_err == DB_NOTFOUND)    return svn_error_createf      (SVN_ERR_FS_NO_SUCH_STRING, 0,       "No such string '%s'", key);  /* Handle any other error conditions.  */  SVN_ERR(BDB_WRAP(fs, "clearing string", db_err));  /* Shove empty data back in for this key. */  svn_fs_base__clear_dbt(&result);  result.data = 0;  result.size = 0;  result.flags |= DB_DBT_USERMEM;  svn_fs_base__trail_debug(trail, "strings", "put");  return BDB_WRAP(fs, "storing empty contents",                  bfd->strings->put(bfd->strings, trail->db_txn,                                    &query, &result, 0));}svn_error_t *svn_fs_bdb__string_size(svn_filesize_t *size,                        svn_fs_t *fs,                        const char *key,                        trail_t *trail,                        apr_pool_t *pool){  int db_err;  DBT query;  DBC *cursor;  apr_size_t length;  svn_filesize_t total;  svn_fs_base__str_to_dbt(&query, key);  SVN_ERR(locate_key(&length, &cursor, &query, fs, trail, pool));  total = length;  while (1)    {      /* Remember, if any error happens, our cursor has been closed         for us. */      db_err = get_next_length(&length, cursor, &query);      /* No more records? Then return the total length. */      if (db_err == DB_NOTFOUND)        {          *size = total;          return SVN_NO_ERROR;        }      if (db_err)        return BDB_WRAP(fs, "fetching string length", db_err);      total += length;    }  /* NOTREACHED */}svn_error_t *svn_fs_bdb__string_delete(svn_fs_t *fs,                          const char *key,                          trail_t *trail,                          apr_pool_t *pool){  base_fs_data_t *bfd = fs->fsap_data;  int db_err;  DBT query;  svn_fs_base__trail_debug(trail, "strings", "del");  db_err = bfd->strings->del(bfd->strings, trail->db_txn,                             svn_fs_base__str_to_dbt(&query, key), 0);  /* If there's no such node, return an appropriately specific error.  */  if (db_err == DB_NOTFOUND)    return svn_error_createf      (SVN_ERR_FS_NO_SUCH_STRING, 0,       "No such string '%s'", key);  /* Handle any other error conditions.  */  SVN_ERR(BDB_WRAP(fs, "deleting string", db_err));  return SVN_NO_ERROR;}svn_error_t *svn_fs_bdb__string_copy(svn_fs_t *fs,                        const char **new_key,                        const char *key,                        trail_t *trail,                        apr_pool_t *pool){  base_fs_data_t *bfd = fs->fsap_data;  DBT query;  DBT result;  DBT copykey;  DBC *cursor;  int db_err;  /* Copy off the old key in case the caller is sharing storage     between the old and new keys. */  const char *old_key = apr_pstrdup(pool, key);  SVN_ERR(get_key_and_bump(fs, new_key, trail, pool));  svn_fs_base__trail_debug(trail, "strings", "cursor");  SVN_ERR(BDB_WRAP(fs, "creating cursor for reading a string",                   bfd->strings->cursor(bfd->strings, trail->db_txn,                                        &cursor, 0)));  svn_fs_base__str_to_dbt(&query, old_key);  svn_fs_base__str_to_dbt(&copykey, *new_key);  svn_fs_base__clear_dbt(&result);  /* Move to the first record and fetch its data (under BDB's mem mgmt). */  db_err = cursor->c_get(cursor, &query, &result, DB_SET);  if (db_err)    {      cursor->c_close(cursor);      return BDB_WRAP(fs, "getting next-key value", db_err);    }  while (1)    {      /* ### can we pass a BDB-provided buffer to another BDB function?         ### they are supposed to have a duration up to certain points         ### of calling back into BDB, but I'm not sure what the exact         ### rules are. it is definitely nicer to use BDB buffers here         ### to simplify things and reduce copies, but... hrm.      */      /* Write the data to the database */      svn_fs_base__trail_debug(trail, "strings", "put");      db_err = bfd->strings->put(bfd->strings, trail->db_txn,                                 &copykey, &result, 0);      if (db_err)        {          cursor->c_close(cursor);          return BDB_WRAP(fs, "writing copied data", db_err);        }      /* Read the next chunk. Terminate loop if we're done. */      svn_fs_base__clear_dbt(&result);      db_err = cursor->c_get(cursor, &query, &result, DB_NEXT_DUP);      if (db_err == DB_NOTFOUND)        break;      if (db_err)        {          cursor->c_close(cursor);          return BDB_WRAP(fs, "fetching string data for a copy", db_err);        }    }  return BDB_WRAP(fs, "closing string-reading cursor",                  cursor->c_close(cursor));}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?