~svn/ubuntu/raring/subversion/ppa

« back to all changes in this revision

Viewing changes to subversion/libsvn_fs_base/bdb/txn-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
/* txn-table.c : operations on the `transactions' 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 "../key-gen.h"
 
27
#include "../util/skel.h"
 
28
#include "../util/fs_skels.h"
 
29
#include "../trail.h"
 
30
#include "../../libsvn_fs/fs-loader.h"
 
31
#include "bdb-err.h"
 
32
#include "txn-table.h"
 
33
 
 
34
#include "svn_private_config.h"
 
35
 
 
36
 
 
37
static svn_boolean_t
 
38
is_committed (transaction_t *txn)
 
39
{
 
40
  return (txn->kind == transaction_kind_committed) ? TRUE : FALSE;
 
41
}
 
42
 
 
43
 
 
44
int
 
45
svn_fs_bdb__open_transactions_table (DB **transactions_p,
 
46
                                     DB_ENV *env,
 
47
                                     svn_boolean_t create)
 
48
{
 
49
  const u_int32_t open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
 
50
  DB *txns;
 
51
 
 
52
  BDB_ERR (svn_fs_bdb__check_version());
 
53
  BDB_ERR (db_create (&txns, env, 0));
 
54
  BDB_ERR (txns->open (SVN_BDB_OPEN_PARAMS(txns, NULL),
 
55
                      "transactions", 0, DB_BTREE,
 
56
                      open_flags | SVN_BDB_AUTO_COMMIT,
 
57
                      0666));
 
58
 
 
59
  /* Create the `next-id' table entry.  */
 
60
  if (create)
 
61
  {
 
62
    DBT key, value;
 
63
 
 
64
    BDB_ERR (txns->put (txns, 0,
 
65
                       svn_fs_base__str_to_dbt (&key, NEXT_KEY_KEY),
 
66
                       svn_fs_base__str_to_dbt (&value, "0"),
 
67
                       SVN_BDB_AUTO_COMMIT));
 
68
  }
 
69
 
 
70
  *transactions_p = txns;
 
71
  return 0;
 
72
}
 
73
 
 
74
 
 
75
svn_error_t *
 
76
svn_fs_bdb__put_txn (svn_fs_t *fs,
 
77
                     const transaction_t *txn,
 
78
                     const char *txn_name,
 
79
                     trail_t *trail,
 
80
                     apr_pool_t *pool)
 
81
{
 
82
  base_fs_data_t *bfd = fs->fsap_data;
 
83
  skel_t *txn_skel;
 
84
  DBT key, value;
 
85
 
 
86
  /* Convert native type to skel. */
 
87
  SVN_ERR (svn_fs_base__unparse_transaction_skel (&txn_skel, txn, pool));
 
88
 
 
89
  /* Only in the context of this function do we know that the DB call
 
90
     will not attempt to modify txn_name, so the cast belongs here.  */
 
91
  svn_fs_base__str_to_dbt (&key, txn_name);
 
92
  svn_fs_base__skel_to_dbt (&value, txn_skel, pool);
 
93
  svn_fs_base__trail_debug (trail, "transactions", "put");
 
94
  SVN_ERR (BDB_WRAP (fs, _("storing transaction record"),
 
95
                     bfd->transactions->put (bfd->transactions, trail->db_txn,
 
96
                                             &key, &value, 0)));
 
97
 
 
98
  return SVN_NO_ERROR;
 
99
}
 
100
 
 
101
 
 
102
/* Allocate a Subversion transaction ID in FS, as part of TRAIL.  Set
 
103
   *ID_P to the new transaction ID, allocated in POOL.  */
 
104
static svn_error_t *
 
105
allocate_txn_id (const char **id_p,
 
106
                 svn_fs_t *fs,
 
107
                 trail_t *trail,
 
108
                 apr_pool_t *pool)
 
109
{
 
110
  base_fs_data_t *bfd = fs->fsap_data;
 
111
  DBT query, result;
 
112
  apr_size_t len;
 
113
  char next_key[MAX_KEY_SIZE];
 
114
  int db_err;
 
115
 
 
116
  svn_fs_base__str_to_dbt (&query, NEXT_KEY_KEY);
 
117
 
 
118
  /* Get the current value associated with the `next-key' key in the table.  */
 
119
  svn_fs_base__trail_debug (trail, "transactions", "get");
 
120
  SVN_ERR (BDB_WRAP (fs, "allocating new transaction ID (getting 'next-key')",
 
121
                     bfd->transactions->get (bfd->transactions, trail->db_txn,
 
122
                                             &query,
 
123
                                             svn_fs_base__result_dbt (&result),
 
124
                                             0)));
 
125
  svn_fs_base__track_dbt (&result, pool);
 
126
 
 
127
  /* Set our return value. */
 
128
  *id_p = apr_pstrmemdup (pool, result.data, result.size);
 
129
 
 
130
  /* Bump to future key. */
 
131
  len = result.size;
 
132
  svn_fs_base__next_key (result.data, &len, next_key);
 
133
  svn_fs_base__str_to_dbt (&query, NEXT_KEY_KEY);
 
134
  svn_fs_base__str_to_dbt (&result, next_key);
 
135
  svn_fs_base__trail_debug (trail, "transactions", "put");
 
136
  db_err = bfd->transactions->put (bfd->transactions, trail->db_txn,
 
137
                                   &query, &result, 0);
 
138
 
 
139
  SVN_ERR (BDB_WRAP (fs, "bumping next transaction key", db_err));
 
140
  return SVN_NO_ERROR;
 
141
}
 
142
 
 
143
 
 
144
svn_error_t *
 
145
svn_fs_bdb__create_txn (const char **txn_name_p,
 
146
                        svn_fs_t *fs,
 
147
                        const svn_fs_id_t *root_id,
 
148
                        trail_t *trail,
 
149
                        apr_pool_t *pool)
 
150
{
 
151
  const char *txn_name;
 
152
  transaction_t txn;
 
153
 
 
154
  SVN_ERR (allocate_txn_id (&txn_name, fs, trail, pool));
 
155
  txn.kind = transaction_kind_normal;
 
156
  txn.root_id = root_id;
 
157
  txn.base_id = root_id;
 
158
  txn.proplist = NULL;
 
159
  txn.copies = NULL;
 
160
  txn.revision = SVN_INVALID_REVNUM;
 
161
  SVN_ERR (svn_fs_bdb__put_txn (fs, &txn, txn_name, trail, pool));
 
162
 
 
163
  *txn_name_p = txn_name;
 
164
  return SVN_NO_ERROR;
 
165
}
 
166
 
 
167
 
 
168
svn_error_t *
 
169
svn_fs_bdb__delete_txn (svn_fs_t *fs,
 
170
                        const char *txn_name,
 
171
                        trail_t *trail,
 
172
                        apr_pool_t *pool)
 
173
{
 
174
  base_fs_data_t *bfd = fs->fsap_data;
 
175
  DBT key;
 
176
  transaction_t *txn;
 
177
 
 
178
  /* Make sure TXN is dead. */
 
179
  SVN_ERR (svn_fs_bdb__get_txn (&txn, fs, txn_name, trail, pool));
 
180
  if (is_committed (txn))
 
181
    return svn_fs_base__err_txn_not_mutable (fs, txn_name);
 
182
 
 
183
  /* Delete the transaction from the `transactions' table. */
 
184
  svn_fs_base__str_to_dbt (&key, txn_name);
 
185
  svn_fs_base__trail_debug (trail, "transactions", "del");
 
186
  SVN_ERR (BDB_WRAP (fs, "deleting entry from 'transactions' table",
 
187
                     bfd->transactions->del (bfd->transactions,
 
188
                                             trail->db_txn, &key, 0)));
 
189
 
 
190
  return SVN_NO_ERROR;
 
191
}
 
192
 
 
193
 
 
194
svn_error_t *
 
195
svn_fs_bdb__get_txn (transaction_t **txn_p,
 
196
                     svn_fs_t *fs,
 
197
                     const char *txn_name,
 
198
                     trail_t *trail,
 
199
                     apr_pool_t *pool)
 
200
{
 
201
  base_fs_data_t *bfd = fs->fsap_data;
 
202
  DBT key, value;
 
203
  int db_err;
 
204
  skel_t *skel;
 
205
  transaction_t *transaction;
 
206
 
 
207
  /* Only in the context of this function do we know that the DB call
 
208
     will not attempt to modify txn_name, so the cast belongs here.  */
 
209
  svn_fs_base__trail_debug (trail, "transactions", "get");
 
210
  db_err = bfd->transactions->get (bfd->transactions, trail->db_txn,
 
211
                                   svn_fs_base__str_to_dbt (&key, txn_name),
 
212
                                   svn_fs_base__result_dbt (&value),
 
213
                                   0);
 
214
  svn_fs_base__track_dbt (&value, pool);
 
215
 
 
216
  if (db_err == DB_NOTFOUND)
 
217
    return svn_fs_base__err_no_such_txn (fs, txn_name);
 
218
  SVN_ERR (BDB_WRAP (fs, "reading transaction", db_err));
 
219
 
 
220
  /* Parse TRANSACTION skel */
 
221
  skel = svn_fs_base__parse_skel (value.data, value.size, pool);
 
222
  if (! skel)
 
223
    return svn_fs_base__err_corrupt_txn (fs, txn_name);
 
224
 
 
225
  /* Convert skel to native type. */
 
226
  SVN_ERR (svn_fs_base__parse_transaction_skel (&transaction, skel, pool));
 
227
  *txn_p = transaction;
 
228
  return SVN_NO_ERROR;
 
229
}
 
230
 
 
231
 
 
232
svn_error_t *
 
233
svn_fs_bdb__get_txn_list (apr_array_header_t **names_p,
 
234
                          svn_fs_t *fs,
 
235
                          trail_t *trail,
 
236
                          apr_pool_t *pool)
 
237
{
 
238
  base_fs_data_t *bfd = fs->fsap_data;
 
239
  apr_size_t const next_id_key_len = strlen (NEXT_KEY_KEY);
 
240
  apr_pool_t *subpool = svn_pool_create (pool);
 
241
  apr_array_header_t *names;
 
242
  DBC *cursor;
 
243
  DBT key, value;
 
244
  int db_err, db_c_err;
 
245
 
 
246
  /* Allocate the initial names array */
 
247
  names = apr_array_make (pool, 4, sizeof (const char *));
 
248
 
 
249
  /* Create a database cursor to list the transaction names. */
 
250
  svn_fs_base__trail_debug (trail, "transactions", "cursor");
 
251
  SVN_ERR (BDB_WRAP (fs, "reading transaction list (opening cursor)",
 
252
                     bfd->transactions->cursor (bfd->transactions,
 
253
                                                trail->db_txn, &cursor, 0)));
 
254
 
 
255
  /* Build a null-terminated array of keys in the transactions table. */
 
256
  for (db_err = cursor->c_get (cursor,
 
257
                               svn_fs_base__result_dbt (&key),
 
258
                               svn_fs_base__result_dbt (&value),
 
259
                               DB_FIRST);
 
260
       db_err == 0;
 
261
       db_err = cursor->c_get (cursor,
 
262
                               svn_fs_base__result_dbt (&key),
 
263
                               svn_fs_base__result_dbt (&value),
 
264
                               DB_NEXT))
 
265
    {
 
266
      transaction_t *txn;
 
267
      skel_t *txn_skel;
 
268
      svn_error_t *err;
 
269
 
 
270
      /* Clear the per-iteration subpool */
 
271
      svn_pool_clear (subpool);
 
272
 
 
273
      /* Track the memory alloc'd for fetching the key and value here
 
274
         so that when the containing pool is cleared, this memory is
 
275
         freed. */
 
276
      svn_fs_base__track_dbt (&key, subpool);
 
277
      svn_fs_base__track_dbt (&value, subpool);
 
278
 
 
279
      /* Ignore the "next-id" key. */
 
280
      if (key.size == next_id_key_len
 
281
          && 0 == memcmp (key.data, NEXT_KEY_KEY, next_id_key_len))
 
282
        continue;
 
283
 
 
284
      /* Parse TRANSACTION skel */
 
285
      txn_skel = svn_fs_base__parse_skel (value.data, value.size, subpool);
 
286
      if (! txn_skel)
 
287
        {
 
288
          cursor->c_close (cursor);
 
289
          return svn_fs_base__err_corrupt_txn
 
290
            (fs, apr_pstrmemdup (pool, key.data, key.size));
 
291
        }
 
292
 
 
293
      /* Convert skel to native type. */
 
294
      if ((err = svn_fs_base__parse_transaction_skel (&txn, txn_skel,
 
295
                                                      subpool)))
 
296
        {
 
297
          cursor->c_close (cursor);
 
298
          return err;
 
299
        }
 
300
 
 
301
      /* If this is an immutable "committed" transaction, ignore it. */
 
302
      if (is_committed (txn))
 
303
        continue;
 
304
 
 
305
      /* Add the transaction name to the NAMES array, duping it into POOL. */
 
306
      (*((const char **) apr_array_push (names))) 
 
307
        = apr_pstrmemdup (pool, key.data, key.size);
 
308
    }
 
309
 
 
310
  /* Check for errors, but close the cursor first. */
 
311
  db_c_err = cursor->c_close (cursor);
 
312
  if (db_err != DB_NOTFOUND)
 
313
    {
 
314
      SVN_ERR (BDB_WRAP (fs, "reading transaction list (listing keys)",
 
315
                         db_err));
 
316
    }
 
317
  SVN_ERR (BDB_WRAP (fs, "reading transaction list (closing cursor)",
 
318
                     db_c_err));
 
319
 
 
320
  /* Destroy the per-iteration subpool */
 
321
  svn_pool_destroy (subpool);
 
322
 
 
323
  *names_p = names;
 
324
  return SVN_NO_ERROR;
 
325
}