~svn/ubuntu/raring/subversion/ppa

« back to all changes in this revision

Viewing changes to subversion/libsvn_fs_base/bdb/locks-table.c

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-12-05 01:26:14 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051205012614-qom4xfypgtsqc2xq
Tags: 1.2.3dfsg1-3ubuntu1
Merge with the final Debian release of 1.2.3dfsg1-3, bringing in
fixes to the clean target, better documentation of the libdb4.3
upgrade and build fixes to work with swig1.3_1.3.27.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* locks-table.c : operations on the `locks' table
 
2
 *
 
3
 * ====================================================================
 
4
 * Copyright (c) 2000-2004 CollabNet.  All rights reserved.
 
5
 *
 
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.
 
11
 *
 
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
 * ====================================================================
 
16
 */
 
17
 
 
18
#include <string.h>
 
19
#include <assert.h>
 
20
#include "bdb_compat.h"
 
21
 
 
22
#include "svn_pools.h"
 
23
#include "dbt.h"
 
24
#include "../err.h"
 
25
#include "../fs.h"
 
26
#include "../util/skel.h"
 
27
#include "../util/fs_skels.h"
 
28
#include "../trail.h"
 
29
#include "../../libsvn_fs/fs-loader.h"
 
30
#include "bdb-err.h"
 
31
#include "locks-table.h"
 
32
#include "lock-tokens-table.h"
 
33
 
 
34
 
 
35
 
 
36
int
 
37
svn_fs_bdb__open_locks_table (DB **locks_p,
 
38
                              DB_ENV *env,
 
39
                              svn_boolean_t create)
 
40
{
 
41
  const u_int32_t open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
 
42
  DB *locks;
 
43
  int error;
 
44
 
 
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),
 
48
                       "locks", 0, DB_BTREE,
 
49
                       open_flags | SVN_BDB_AUTO_COMMIT,
 
50
                       0666);
 
51
 
 
52
  /* Create the table if it doesn't yet exist.  This is a form of
 
53
     automagical repository upgrading. */
 
54
  if (error == ENOENT && (! create))
 
55
    {
 
56
      BDB_ERR (locks->close (locks, 0));
 
57
      return svn_fs_bdb__open_locks_table (locks_p, env, TRUE);
 
58
    }
 
59
  BDB_ERR (error);
 
60
 
 
61
  *locks_p = locks;
 
62
  return 0;
 
63
}
 
64
 
 
65
 
 
66
 
 
67
svn_error_t *
 
68
svn_fs_bdb__lock_add (svn_fs_t *fs,
 
69
                      const char *lock_token,
 
70
                      svn_lock_t *lock,
 
71
                      trail_t *trail,
 
72
                      apr_pool_t *pool)
 
73
{
 
74
  base_fs_data_t *bfd = fs->fsap_data;
 
75
  skel_t *lock_skel;
 
76
  DBT key, value;
 
77
 
 
78
  /* Convert native type to skel. */
 
79
  SVN_ERR (svn_fs_base__unparse_lock_skel (&lock_skel, lock, pool));
 
80
 
 
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,
 
86
                                      &key, &value, 0)));
 
87
 
 
88
  return SVN_NO_ERROR;
 
89
}
 
90
 
 
91
 
 
92
 
 
93
svn_error_t *
 
94
svn_fs_bdb__lock_delete (svn_fs_t *fs,
 
95
                         const char *lock_token,
 
96
                         trail_t *trail,
 
97
                         apr_pool_t *pool)
 
98
{
 
99
  base_fs_data_t *bfd = fs->fsap_data;
 
100
  DBT key;
 
101
  int db_err;
 
102
 
 
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);
 
106
  
 
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));
 
110
 
 
111
  return SVN_NO_ERROR;
 
112
}
 
113
 
 
114
 
 
115
 
 
116
svn_error_t *
 
117
svn_fs_bdb__lock_get (svn_lock_t **lock_p,
 
118
                      svn_fs_t *fs,
 
119
                      const char *lock_token,
 
120
                      trail_t *trail,
 
121
                      apr_pool_t *pool)
 
122
{
 
123
  base_fs_data_t *bfd = fs->fsap_data;
 
124
  DBT key, value;
 
125
  int db_err;
 
126
  skel_t *skel;
 
127
  svn_lock_t *lock;
 
128
 
 
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),
 
133
                            0);
 
134
  svn_fs_base__track_dbt (&value, pool);
 
135
 
 
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));
 
139
 
 
140
  /* Parse TRANSACTION skel */
 
141
  skel = svn_fs_base__parse_skel (value.data, value.size, pool);
 
142
  if (! skel)
 
143
    return svn_fs_base__err_corrupt_lock (fs, lock_token);
 
144
 
 
145
  /* Convert skel to native type. */
 
146
  SVN_ERR (svn_fs_base__parse_lock_skel (&lock, skel, pool));
 
147
 
 
148
  /* Possibly auto-expire the lock. */
 
149
  if (lock->expiration_date && (apr_time_now () > lock->expiration_date))
 
150
    {
 
151
      SVN_ERR (svn_fs_bdb__lock_delete (fs, lock_token, trail, pool));
 
152
      return svn_fs_base__err_lock_expired (fs, lock_token); 
 
153
    }
 
154
 
 
155
  *lock_p = lock;
 
156
  return SVN_NO_ERROR;
 
157
}
 
158
 
 
159
 
 
160
static svn_error_t *
 
161
get_lock (svn_lock_t **lock_p,
 
162
          svn_fs_t *fs,
 
163
          const char *path,
 
164
          const char *lock_token,
 
165
          trail_t *trail,
 
166
          apr_pool_t *pool)
 
167
{
 
168
  svn_error_t *err = SVN_NO_ERROR;
 
169
  *lock_p = NULL;
 
170
 
 
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)))
 
176
    {
 
177
      svn_error_clear (err);
 
178
 
 
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);
 
183
    }
 
184
  return err;
 
185
}
 
186
 
 
187
 
 
188
svn_error_t *
 
189
svn_fs_bdb__locks_get (svn_fs_t *fs,
 
190
                       const char *path,
 
191
                       svn_fs_get_locks_callback_t get_locks_func,
 
192
                       void *get_locks_baton,
 
193
                       trail_t *trail,
 
194
                       apr_pool_t *pool)
 
195
{
 
196
  base_fs_data_t *bfd = fs->fsap_data;
 
197
  DBC *cursor;
 
198
  DBT key, value;
 
199
  int db_err;
 
200
  apr_pool_t *subpool = svn_pool_create (pool);
 
201
  const char *lock_token;
 
202
  svn_lock_t *lock;
 
203
  svn_error_t *err;
 
204
  const char *lookup_path = path;
 
205
 
 
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)))
 
211
    {
 
212
      svn_error_clear (err);
 
213
    }
 
214
  else if (err)
 
215
    {
 
216
      return err;
 
217
    }
 
218
  else
 
219
    {
 
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));
 
223
    }
 
224
 
 
225
  /* Now go hunt for possible children of PATH. */
 
226
  if (strcmp (path, "/") != 0)
 
227
    lookup_path = apr_pstrcat (pool, path, "/", NULL);
 
228
 
 
229
  svn_fs_base__trail_debug (trail, "lock-tokens", "cursor");
 
230
  db_err = bfd->lock_tokens->cursor (bfd->lock_tokens, trail->db_txn,
 
231
                                     &cursor, 0);  
 
232
  SVN_ERR (BDB_WRAP (fs, "creating cursor for reading lock tokens", db_err));
 
233
 
 
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;
 
238
 
 
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),
 
242
                          DB_SET_RANGE);
 
243
 
 
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.  */
 
246
  while ((! db_err) 
 
247
         && strncmp (lookup_path, key.data, strlen (lookup_path)) == 0)
 
248
    {
 
249
      const char *child_path;
 
250
 
 
251
      svn_pool_clear (subpool);
 
252
 
 
253
      svn_fs_base__track_dbt (&key, subpool);      
 
254
      svn_fs_base__track_dbt (&value, subpool);
 
255
 
 
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);
 
259
 
 
260
      /* Get the lock for CHILD_PATH.  */
 
261
      err = get_lock (&lock, fs, child_path, lock_token, trail, subpool);
 
262
      if (err)
 
263
        {
 
264
          cursor->c_close (cursor);
 
265
          return err;
 
266
        }
 
267
 
 
268
      /* Lock is verified, return it in the hash. */
 
269
      if (lock && get_locks_func)
 
270
        {
 
271
          err = get_locks_func (get_locks_baton, lock, subpool);
 
272
          if (err)
 
273
            {
 
274
              cursor->c_close (cursor);
 
275
              return err;
 
276
            }
 
277
        }
 
278
 
 
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);
 
282
    }
 
283
 
 
284
  svn_pool_destroy (subpool);
 
285
  cursor->c_close (cursor);
 
286
 
 
287
  if (db_err && (db_err != DB_NOTFOUND)) 
 
288
    SVN_ERR (BDB_WRAP (fs, "fetching lock tokens", db_err));
 
289
 
 
290
  return SVN_NO_ERROR;
 
291
}
 
292