⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 strings-table.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 2 页
字号:

/* Get the current 'next-key' value and bump the record. */
static svn_error_t *
get_key_and_bump (svn_fs_t *fs, const char **key, trail_t *trail)
{
  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, trail->pool);
  *key = apr_pstrmemdup (trail->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)
{
  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));
    }

  /* 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)
{
  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)
{
  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));

  total = length;
  while (1)
    {
      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)
{
  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)
{
  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 (trail->pool, key);

  SVN_ERR (get_key_and_bump (fs, new_key, trail));

  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 + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -