1
/* locks-table.c : operations on the `locks' 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"
22
#include "svn_pools.h"
26
#include "../util/skel.h"
27
#include "../util/fs_skels.h"
29
#include "../../libsvn_fs/fs-loader.h"
31
#include "locks-table.h"
32
#include "lock-tokens-table.h"
37
svn_fs_bdb__open_locks_table (DB **locks_p,
41
const u_int32_t open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
45
BDB_ERR (svn_fs_bdb__check_version ());
46
BDB_ERR (db_create (&locks, env, 0));
47
error = locks->open (SVN_BDB_OPEN_PARAMS(locks, NULL),
49
open_flags | SVN_BDB_AUTO_COMMIT,
52
/* Create the table if it doesn't yet exist. This is a form of
53
automagical repository upgrading. */
54
if (error == ENOENT && (! create))
56
BDB_ERR (locks->close (locks, 0));
57
return svn_fs_bdb__open_locks_table (locks_p, env, TRUE);
68
svn_fs_bdb__lock_add (svn_fs_t *fs,
69
const char *lock_token,
74
base_fs_data_t *bfd = fs->fsap_data;
78
/* Convert native type to skel. */
79
SVN_ERR (svn_fs_base__unparse_lock_skel (&lock_skel, lock, pool));
81
svn_fs_base__str_to_dbt (&key, lock_token);
82
svn_fs_base__skel_to_dbt (&value, lock_skel, pool);
83
svn_fs_base__trail_debug (trail, "lock", "add");
84
SVN_ERR (BDB_WRAP (fs, "storing lock record",
85
bfd->locks->put (bfd->locks, trail->db_txn,
94
svn_fs_bdb__lock_delete (svn_fs_t *fs,
95
const char *lock_token,
99
base_fs_data_t *bfd = fs->fsap_data;
103
svn_fs_base__str_to_dbt (&key, lock_token);
104
svn_fs_base__trail_debug (trail, "locks", "del");
105
db_err = bfd->locks->del (bfd->locks, trail->db_txn, &key, 0);
107
if (db_err == DB_NOTFOUND)
108
return svn_fs_base__err_bad_lock_token (fs, lock_token);
109
SVN_ERR (BDB_WRAP (fs, "deleting lock from 'locks' table", db_err));
117
svn_fs_bdb__lock_get (svn_lock_t **lock_p,
119
const char *lock_token,
123
base_fs_data_t *bfd = fs->fsap_data;
129
svn_fs_base__trail_debug (trail, "lock", "get");
130
db_err = bfd->locks->get (bfd->locks, trail->db_txn,
131
svn_fs_base__str_to_dbt (&key, lock_token),
132
svn_fs_base__result_dbt (&value),
134
svn_fs_base__track_dbt (&value, pool);
136
if (db_err == DB_NOTFOUND)
137
return svn_fs_base__err_bad_lock_token (fs, lock_token);
138
SVN_ERR (BDB_WRAP (fs, "reading lock", db_err));
140
/* Parse TRANSACTION skel */
141
skel = svn_fs_base__parse_skel (value.data, value.size, pool);
143
return svn_fs_base__err_corrupt_lock (fs, lock_token);
145
/* Convert skel to native type. */
146
SVN_ERR (svn_fs_base__parse_lock_skel (&lock, skel, pool));
148
/* Possibly auto-expire the lock. */
149
if (lock->expiration_date && (apr_time_now () > lock->expiration_date))
151
SVN_ERR (svn_fs_bdb__lock_delete (fs, lock_token, trail, pool));
152
return svn_fs_base__err_lock_expired (fs, lock_token);
161
get_lock (svn_lock_t **lock_p,
164
const char *lock_token,
168
svn_error_t *err = SVN_NO_ERROR;
171
/* Make sure the token points to an existing, non-expired lock, by
172
doing a lookup in the `locks' table. Use 'pool'. */
173
err = svn_fs_bdb__lock_get (lock_p, fs, lock_token, trail, pool);
174
if (err && ((err->apr_err == SVN_ERR_FS_LOCK_EXPIRED)
175
|| (err->apr_err == SVN_ERR_FS_BAD_LOCK_TOKEN)))
177
svn_error_clear (err);
179
/* If `locks' doesn't have the lock, then we should lose it
180
from `lock-tokens' table as well, then skip to the next
181
matching path-key. */
182
err = svn_fs_bdb__lock_token_delete (fs, path, trail, pool);
189
svn_fs_bdb__locks_get (svn_fs_t *fs,
191
svn_fs_get_locks_callback_t get_locks_func,
192
void *get_locks_baton,
196
base_fs_data_t *bfd = fs->fsap_data;
200
apr_pool_t *subpool = svn_pool_create (pool);
201
const char *lock_token;
204
const char *lookup_path = path;
206
/* First, try to lookup PATH itself. */
207
err = svn_fs_bdb__lock_token_get (&lock_token, fs, path, trail, pool);
208
if (err && ((err->apr_err == SVN_ERR_FS_LOCK_EXPIRED)
209
|| (err->apr_err == SVN_ERR_FS_BAD_LOCK_TOKEN)
210
|| (err->apr_err == SVN_ERR_FS_NO_SUCH_LOCK)))
212
svn_error_clear (err);
220
SVN_ERR (get_lock (&lock, fs, path, lock_token, trail, pool));
221
if (lock && get_locks_func)
222
SVN_ERR (get_locks_func (get_locks_baton, lock, pool));
225
/* Now go hunt for possible children of PATH. */
226
if (strcmp (path, "/") != 0)
227
lookup_path = apr_pstrcat (pool, path, "/", NULL);
229
svn_fs_base__trail_debug (trail, "lock-tokens", "cursor");
230
db_err = bfd->lock_tokens->cursor (bfd->lock_tokens, trail->db_txn,
232
SVN_ERR (BDB_WRAP (fs, "creating cursor for reading lock tokens", db_err));
234
/* Since the key is going to be returned as well as the value make
235
sure BDB malloc's the returned key. */
236
svn_fs_base__str_to_dbt (&key, lookup_path);
237
key.flags |= DB_DBT_MALLOC;
239
/* Get the first matching key that is either equal or greater than
240
the one passed in, by passing in the DB_RANGE_SET flag. */
241
db_err = cursor->c_get (cursor, &key, svn_fs_base__result_dbt (&value),
244
/* As long as the prefix of the returned KEY matches LOOKUP_PATH we
245
know it is either LOOKUP_PATH or a decendant thereof. */
247
&& strncmp (lookup_path, key.data, strlen (lookup_path)) == 0)
249
const char *child_path;
251
svn_pool_clear (subpool);
253
svn_fs_base__track_dbt (&key, subpool);
254
svn_fs_base__track_dbt (&value, subpool);
256
/* Create a usable path and token in temporary memory. */
257
child_path = apr_pstrmemdup (subpool, key.data, key.size);
258
lock_token = apr_pstrmemdup (subpool, value.data, value.size);
260
/* Get the lock for CHILD_PATH. */
261
err = get_lock (&lock, fs, child_path, lock_token, trail, subpool);
264
cursor->c_close (cursor);
268
/* Lock is verified, return it in the hash. */
269
if (lock && get_locks_func)
271
err = get_locks_func (get_locks_baton, lock, subpool);
274
cursor->c_close (cursor);
279
svn_fs_base__result_dbt (&key);
280
svn_fs_base__result_dbt (&value);
281
db_err = cursor->c_get (cursor, &key, &value, DB_NEXT);
284
svn_pool_destroy (subpool);
285
cursor->c_close (cursor);
287
if (db_err && (db_err != DB_NOTFOUND))
288
SVN_ERR (BDB_WRAP (fs, "fetching lock tokens", db_err));