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(©key, *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, ©key, &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 + -
显示快捷键?