1 /* nodes-table.c : working with the `nodes' table
3 * ====================================================================
4 * Copyright (c) 2000-2004 CollabNet. All rights reserved.
6 * This software is licensed as described in the file COPYING, which
7 * you should have received as part of this distribution. The terms
8 * are also available at http://subversion.tigris.org/license-1.html.
9 * If newer versions of this license are posted there, you may use a
10 * newer version instead, at your option.
12 * This software consists of voluntary contributions made by many
13 * individuals. For exact contribution history, see the revision
14 * history and logs, available at http://subversion.tigris.org/.
15 * ====================================================================
20 #include "bdb_compat.h"
27 #include "../util/skel.h"
28 #include "../util/fs_skels.h"
30 #include "../key-gen.h"
32 #include "../../libsvn_fs/fs-loader.h"
34 #include "nodes-table.h"
37 #include "svn_private_config.h"
40 /* Opening/creating the `nodes' table. */
44 svn_fs_bdb__open_nodes_table(DB
**nodes_p
,
48 const u_int32_t open_flags
= (create
? (DB_CREATE
| DB_EXCL
) : 0);
51 BDB_ERR(svn_fs_bdb__check_version());
52 BDB_ERR(db_create(&nodes
, env
, 0));
53 BDB_ERR((nodes
->open
)(SVN_BDB_OPEN_PARAMS(nodes
, NULL
),
57 /* Create the `next-key' table entry (use '1' because '0' is
58 reserved for the root directory to use). */
63 BDB_ERR(nodes
->put(nodes
, 0,
64 svn_fs_base__str_to_dbt(&key
, NEXT_KEY_KEY
),
65 svn_fs_base__str_to_dbt(&value
, "1"), 0));
74 /* Choosing node revision ID's. */
77 svn_fs_bdb__new_node_id(svn_fs_id_t
**id_p
,
84 base_fs_data_t
*bfd
= fs
->fsap_data
;
87 char next_key
[MAX_KEY_SIZE
];
89 const char *next_node_id
;
91 /* TXN_ID is required! */
94 /* Get the current value associated with the `next-key' key in the table. */
95 svn_fs_base__str_to_dbt(&query
, NEXT_KEY_KEY
);
96 svn_fs_base__trail_debug(trail
, "nodes", "get");
97 SVN_ERR(BDB_WRAP(fs
, _("allocating new node ID (getting 'next-key')"),
98 bfd
->nodes
->get(bfd
->nodes
, trail
->db_txn
,
100 svn_fs_base__result_dbt(&result
),
102 svn_fs_base__track_dbt(&result
, pool
);
104 /* Squirrel away our next node id value. */
105 next_node_id
= apr_pstrmemdup(pool
, result
.data
, result
.size
);
107 /* Bump to future key. */
109 svn_fs_base__next_key(result
.data
, &len
, next_key
);
110 svn_fs_base__trail_debug(trail
, "nodes", "put");
111 db_err
= bfd
->nodes
->put(bfd
->nodes
, trail
->db_txn
,
112 svn_fs_base__str_to_dbt(&query
, NEXT_KEY_KEY
),
113 svn_fs_base__str_to_dbt(&result
, next_key
),
115 SVN_ERR(BDB_WRAP(fs
, _("bumping next node ID key"), db_err
));
117 /* Create and return the new node id. */
118 *id_p
= svn_fs_base__id_create(next_node_id
, copy_id
, txn_id
, pool
);
124 svn_fs_bdb__new_successor_id(svn_fs_id_t
**successor_p
,
126 const svn_fs_id_t
*id
,
135 /* TXN_ID is required! */
138 /* Create and return the new successor ID. */
139 new_id
= svn_fs_base__id_create(svn_fs_base__id_node_id(id
),
141 : svn_fs_base__id_copy_id(id
),
144 /* Now, make sure this NEW_ID doesn't already exist in FS. */
145 err
= svn_fs_bdb__get_node_revision(NULL
, fs
, new_id
, trail
, trail
->pool
);
146 if ((! err
) || (err
->apr_err
!= SVN_ERR_FS_ID_NOT_FOUND
))
148 svn_string_t
*id_str
= svn_fs_base__id_unparse(id
, pool
);
149 svn_string_t
*new_id_str
= svn_fs_base__id_unparse(new_id
, pool
);
150 return svn_error_createf
151 (SVN_ERR_FS_ALREADY_EXISTS
, err
,
152 _("Successor id '%s' (for '%s') already exists in filesystem '%s'"),
153 new_id_str
->data
, id_str
->data
, fs
->path
);
156 /* err is SVN_ERR_FS_ID_NOT_FOUND, meaning the ID is available. But
157 we don't want this error. */
158 svn_error_clear(err
);
160 /* Return the new node revision ID. */
161 *successor_p
= new_id
;
167 /* Removing node revisions. */
169 svn_fs_bdb__delete_nodes_entry(svn_fs_t
*fs
,
170 const svn_fs_id_t
*id
,
174 base_fs_data_t
*bfd
= fs
->fsap_data
;
177 svn_fs_base__trail_debug(trail
, "nodes", "del");
178 SVN_ERR(BDB_WRAP(fs
, _("deleting entry from 'nodes' table"),
179 bfd
->nodes
->del(bfd
->nodes
,
181 svn_fs_base__id_to_dbt(&key
, id
, pool
),
190 /* Storing and retrieving NODE-REVISIONs. */
194 svn_fs_bdb__get_node_revision(node_revision_t
**noderev_p
,
196 const svn_fs_id_t
*id
,
200 base_fs_data_t
*bfd
= fs
->fsap_data
;
201 node_revision_t
*noderev
;
206 svn_fs_base__trail_debug(trail
, "nodes", "get");
207 db_err
= bfd
->nodes
->get(bfd
->nodes
, trail
->db_txn
,
208 svn_fs_base__id_to_dbt(&key
, id
, pool
),
209 svn_fs_base__result_dbt(&value
),
211 svn_fs_base__track_dbt(&value
, pool
);
213 /* If there's no such node, return an appropriately specific error. */
214 if (db_err
== DB_NOTFOUND
)
215 return svn_fs_base__err_dangling_id(fs
, id
);
217 /* Handle any other error conditions. */
218 SVN_ERR(BDB_WRAP(fs
, _("reading node revision"), db_err
));
220 /* If our caller doesn't really care about the return value here,
221 just return successfully. */
225 /* Parse and the NODE-REVISION skel. */
226 skel
= svn_fs_base__parse_skel(value
.data
, value
.size
, pool
);
228 /* Convert to a native FS type. */
229 SVN_ERR(svn_fs_base__parse_node_revision_skel(&noderev
, skel
, pool
));
230 *noderev_p
= noderev
;
236 svn_fs_bdb__put_node_revision(svn_fs_t
*fs
,
237 const svn_fs_id_t
*id
,
238 node_revision_t
*noderev
,
242 base_fs_data_t
*bfd
= fs
->fsap_data
;
243 DB_TXN
*db_txn
= trail
->db_txn
;
247 /* Convert from native type into skel */
248 SVN_ERR(svn_fs_base__unparse_node_revision_skel(&skel
, noderev
,
250 svn_fs_base__trail_debug(trail
, "nodes", "put");
251 return BDB_WRAP(fs
, _("storing node revision"),
252 bfd
->nodes
->put(bfd
->nodes
, db_txn
,
253 svn_fs_base__id_to_dbt(&key
, id
, pool
),
254 svn_fs_base__skel_to_dbt(&value
, skel
,