1 /* nodes-table.c : working with the `nodes' table
3 * ====================================================================
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
20 * ====================================================================
26 #include "bdb_compat.h"
29 #include "private/svn_skel.h"
34 #include "../util/fs_skels.h"
36 #include "../key-gen.h"
38 #include "../../libsvn_fs/fs-loader.h"
40 #include "nodes-table.h"
42 #include "svn_private_config.h"
46 /* Opening/creating the `nodes' table. */
50 svn_fs_bdb__open_nodes_table(DB **nodes_p,
54 const u_int32_t open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
57 BDB_ERR(svn_fs_bdb__check_version());
58 BDB_ERR(db_create(&nodes, env, 0));
59 BDB_ERR((nodes->open)(SVN_BDB_OPEN_PARAMS(nodes, NULL),
63 /* Create the `next-key' table entry (use '1' because '0' is
64 reserved for the root directory to use). */
69 BDB_ERR(nodes->put(nodes, 0,
70 svn_fs_base__str_to_dbt(&key, NEXT_KEY_KEY),
71 svn_fs_base__str_to_dbt(&value, "1"), 0));
80 /* Choosing node revision ID's. */
83 svn_fs_bdb__new_node_id(svn_fs_id_t **id_p,
90 base_fs_data_t *bfd = fs->fsap_data;
93 char next_key[MAX_KEY_SIZE];
95 const char *next_node_id;
97 SVN_ERR_ASSERT(txn_id);
99 /* Get the current value associated with the `next-key' key in the table. */
100 svn_fs_base__str_to_dbt(&query, NEXT_KEY_KEY);
101 svn_fs_base__trail_debug(trail, "nodes", "get");
102 SVN_ERR(BDB_WRAP(fs, N_("allocating new node ID (getting 'next-key')"),
103 bfd->nodes->get(bfd->nodes, trail->db_txn,
105 svn_fs_base__result_dbt(&result),
107 svn_fs_base__track_dbt(&result, pool);
109 /* Squirrel away our next node id value. */
110 next_node_id = apr_pstrmemdup(pool, result.data, result.size);
112 /* Bump to future key. */
114 svn_fs_base__next_key(result.data, &len, next_key);
115 svn_fs_base__trail_debug(trail, "nodes", "put");
116 db_err = bfd->nodes->put(bfd->nodes, trail->db_txn,
117 svn_fs_base__str_to_dbt(&query, NEXT_KEY_KEY),
118 svn_fs_base__str_to_dbt(&result, next_key),
120 SVN_ERR(BDB_WRAP(fs, N_("bumping next node ID key"), db_err));
122 /* Create and return the new node id. */
123 *id_p = svn_fs_base__id_create(next_node_id, copy_id, txn_id, pool);
129 svn_fs_bdb__new_successor_id(svn_fs_id_t **successor_p,
131 const svn_fs_id_t *id,
140 SVN_ERR_ASSERT(txn_id);
142 /* Create and return the new successor ID. */
143 new_id = svn_fs_base__id_create(svn_fs_base__id_node_id(id),
145 : svn_fs_base__id_copy_id(id),
148 /* Now, make sure this NEW_ID doesn't already exist in FS. */
149 err = svn_fs_bdb__get_node_revision(NULL, fs, new_id, trail, trail->pool);
150 if ((! err) || (err->apr_err != SVN_ERR_FS_ID_NOT_FOUND))
152 svn_string_t *id_str = svn_fs_base__id_unparse(id, pool);
153 svn_string_t *new_id_str = svn_fs_base__id_unparse(new_id, pool);
154 return svn_error_createf
155 (SVN_ERR_FS_ALREADY_EXISTS, err,
156 _("Successor id '%s' (for '%s') already exists in filesystem '%s'"),
157 new_id_str->data, id_str->data, fs->path);
160 /* err is SVN_ERR_FS_ID_NOT_FOUND, meaning the ID is available. But
161 we don't want this error. */
162 svn_error_clear(err);
164 /* Return the new node revision ID. */
165 *successor_p = new_id;
171 /* Removing node revisions. */
173 svn_fs_bdb__delete_nodes_entry(svn_fs_t *fs,
174 const svn_fs_id_t *id,
178 base_fs_data_t *bfd = fs->fsap_data;
181 svn_fs_base__trail_debug(trail, "nodes", "del");
182 return BDB_WRAP(fs, N_("deleting entry from 'nodes' table"),
183 bfd->nodes->del(bfd->nodes,
185 svn_fs_base__id_to_dbt(&key, id, pool),
192 /* Storing and retrieving NODE-REVISIONs. */
196 svn_fs_bdb__get_node_revision(node_revision_t **noderev_p,
198 const svn_fs_id_t *id,
202 base_fs_data_t *bfd = fs->fsap_data;
203 node_revision_t *noderev;
208 svn_fs_base__trail_debug(trail, "nodes", "get");
209 db_err = bfd->nodes->get(bfd->nodes, trail->db_txn,
210 svn_fs_base__id_to_dbt(&key, id, pool),
211 svn_fs_base__result_dbt(&value),
213 svn_fs_base__track_dbt(&value, pool);
215 /* If there's no such node, return an appropriately specific error. */
216 if (db_err == DB_NOTFOUND)
217 return svn_fs_base__err_dangling_id(fs, id);
219 /* Handle any other error conditions. */
220 SVN_ERR(BDB_WRAP(fs, N_("reading node revision"), db_err));
222 /* If our caller doesn't really care about the return value here,
223 just return successfully. */
227 /* Parse and the NODE-REVISION skel. */
228 skel = svn_skel__parse(value.data, value.size, pool);
230 /* Convert to a native FS type. */
231 SVN_ERR(svn_fs_base__parse_node_revision_skel(&noderev, skel, pool));
232 *noderev_p = noderev;
238 svn_fs_bdb__put_node_revision(svn_fs_t *fs,
239 const svn_fs_id_t *id,
240 node_revision_t *noderev,
244 base_fs_data_t *bfd = fs->fsap_data;
245 DB_TXN *db_txn = trail->db_txn;
249 /* Convert from native type into skel */
250 SVN_ERR(svn_fs_base__unparse_node_revision_skel(&skel, noderev,
252 svn_fs_base__trail_debug(trail, "nodes", "put");
253 return BDB_WRAP(fs, N_("storing node revision"),
254 bfd->nodes->put(bfd->nodes, db_txn,
255 svn_fs_base__id_to_dbt(&key, id, pool),
256 svn_fs_base__skel_to_dbt(&value, skel,