source: valtobtest/subversion-1.6.2/subversion/libsvn_fs_base/bdb/env.c @ 3

Last change on this file since 3 was 3, checked in by valtob, 15 years ago

subversion source 1.6.2 as test

File size: 22.4 KB
Line 
1/* env.h : managing the BDB environment
2 *
3 * ====================================================================
4 * Copyright (c) 2000-2005 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 <assert.h>
19
20#include <apr.h>
21#if APR_HAS_THREADS
22#include <apr_thread_mutex.h>
23#include <apr_thread_proc.h>
24#include <apr_time.h>
25#endif
26
27#include <apr_strings.h>
28#include <apr_hash.h>
29
30#include "svn_path.h"
31#include "svn_pools.h"
32#include "svn_utf.h"
33#include "private/svn_atomic.h"
34
35#include "bdb-err.h"
36#include "bdb_compat.h"
37
38#include "env.h"
39
40/* A note about the BDB environment descriptor cache.
41
42   With the advent of DB_REGISTER in BDB-4.4, a process may only open
43   an environment handle once.  This means that we must maintain a
44   cache of open environment handles, with reference counts.  We
45   allocate each environment descriptor (a bdb_env_t) from its own
46   pool.  The cache itself (and the cache pool) are shared between
47   threads, so all direct or indirect access to the pool is serialized
48   with a global mutex.
49
50   Because several threads can now use the same DB_ENV handle, we must
51   use the DB_THREAD flag when opening the environments, otherwise the
52   env handles (and all of libsvn_fs_base) won't be thread-safe.
53
54   If we use DB_THREAD, however, all of the code that reads data from
55   the database without a cursor must use either DB_DBT_MALLOC,
56   DB_DBT_REALLOC, or DB_DBT_USERMEM, as described in the BDB
57   documentation.
58
59   (Oh, yes -- using DB_THREAD might not work on some systems. But
60   then, it's quite probable that threading is seriously broken on
61   those systems anyway, so we'll rely on APR_HAS_THREADS.)
62*/
63
64
65/* The cache key for a Berkeley DB environment descriptor.  This is a
66   combination of the device ID and INODE number of the Berkeley DB
67   config file.
68
69   XXX FIXME: Although the dev+inode combination is supposed do be
70   unique, apparently that's not always the case with some remote
71   filesystems.  We /should/ be safe using this as a unique hash key,
72   because the database must be on a local filesystem.  We can hope,
73   anyway. */
74typedef struct
75{
76  apr_dev_t device;
77  apr_ino_t inode;
78} bdb_env_key_t;
79
80/* The cached Berkeley DB environment descriptor. */
81struct bdb_env_t
82{
83  /**************************************************************************/
84  /* Error Reporting */
85
86  /* A (char *) casted pointer to this structure is passed to BDB's
87     set_errpfx(), which treats it as a NUL-terminated character
88     string to prefix all BDB error messages.  However, svn also
89     registers bdb_error_gatherer() as an error handler with
90     set_errcall() which turns off BDB's default printing of errors to
91     stderr and anytime thereafter when BDB reports an error and
92     before the BDB function returns, it calls bdb_error_gatherer()
93     and passes the same error prefix (char *) pointer given to
94     set_errpfx().  The bdb_error_gatherer() callback casts the
95     (char *) it back to a (bdb_env_t *).
96
97     To avoid problems should BDB ever try to interpret our baton as a
98     string, the first field in the structure is a char
99     errpfx_string[].  Initializers of this structure must strcpy the
100     value of BDB_ERRPFX_STRING into this array.  */
101  char errpfx_string[sizeof(BDB_ERRPFX_STRING)];
102
103  /* Extended error information. */
104#if APR_HAS_THREADS
105  apr_threadkey_t *error_info;   /* Points to a bdb_error_info_t. */
106#else
107  bdb_error_info_t error_info;
108#endif
109
110  /**************************************************************************/
111  /* BDB Environment Cache */
112
113  /* The Berkeley DB environment. */
114  DB_ENV *env;
115
116  /* The flags with which this environment was opened.  Reopening the
117     environment with a different set of flags is not allowed.  Trying
118     to change the state of the DB_PRIVATE flag is an especially bad
119     idea, so svn_fs_bdb__open() forbids any flag changes. */
120  u_int32_t flags;
121
122  /* The home path of this environment; a canonical SVN path encoded in
123     UTF-8 and allocated from this decriptor's pool. */
124  const char *path;
125
126  /* The home path of this environment, in the form expected by BDB. */
127  const char *path_bdb;
128
129  /* The reference count for this environment handle; this is
130     essentially the difference between the number of calls to
131     svn_fs_bdb__open and svn_fs_bdb__close. */
132  unsigned refcount;
133
134  /* If this flag is TRUE, someone has detected that the environment
135     descriptor is in a panicked state and should be removed from the
136     cache.
137
138     Note 1: Once this flag is set, it must not be cleared again.
139
140     Note 2: Unlike other fields in this structure, this field is not
141             protected by the cache mutex on threaded platforms, and
142             should only be accesses via the svn_atomic functions. */
143  volatile svn_atomic_t panic;
144
145  /* The key for the environment descriptor cache. */
146  bdb_env_key_t key;
147
148  /* The handle of the open DB_CONFIG file.
149
150     We keep the DB_CONFIG file open in this process as long as the
151     environment handle itself is open.  On Windows, this guarantees
152     that the cache key remains unique; here's what the Windows SDK
153     docs have to say about the file index (interpreted as the INODE
154     number by APR):
155
156        "This value is useful only while the file is open by at least
157        one process.  If no processes have it open, the index may
158        change the next time the file is opened."
159
160     Now, we certainly don't want a unique key to change while it's
161     being used, do we... */
162  apr_file_t *dbconfig_file;
163
164  /* The pool associated with this environment descriptor.
165
166     Because the descriptor has a life of its own, the structure and
167     any data associated with it are allocated from their own global
168     pool. */
169  apr_pool_t *pool;
170
171};
172
173
174#if APR_HAS_THREADS
175/* Get the thread-specific error info from a bdb_env_t. */
176static bdb_error_info_t *
177get_error_info(bdb_env_t *bdb)
178{
179  void *priv;
180  apr_threadkey_private_get(&priv, bdb->error_info);
181  if (!priv)
182    {
183      priv = calloc(1, sizeof(bdb_error_info_t));
184      apr_threadkey_private_set(priv, bdb->error_info);
185    }
186  return priv;
187}
188#else
189#define get_error_info(bdb) (&(bdb)->error_info)
190#endif /* APR_HAS_THREADS */
191
192
193/* Convert a BDB error to a Subversion error. */
194static svn_error_t *
195convert_bdb_error(bdb_env_t *bdb, int db_err)
196{
197  if (db_err)
198    {
199      bdb_env_baton_t bdb_baton;
200      bdb_baton.env = bdb->env;
201      bdb_baton.bdb = bdb;
202      bdb_baton.error_info = get_error_info(bdb);
203      SVN_BDB_ERR(&bdb_baton, db_err);
204    }
205  return SVN_NO_ERROR;
206}
207
208
209/* Allocating an appropriate Berkeley DB environment object.  */
210
211/* BDB error callback.  See bdb_error_info_t in env.h for more info.
212   Note: bdb_error_gatherer is a macro with BDB < 4.3, so be careful how
213   you use it! */
214static void
215bdb_error_gatherer(const DB_ENV *dbenv, const char *baton, const char *msg)
216{
217  /* See the documentation at bdb_env_t's definition why the
218     (bdb_env_t *) cast is safe and why it is done. */
219  bdb_error_info_t *error_info = get_error_info((bdb_env_t *) baton);
220  svn_error_t *new_err;
221
222  SVN_BDB_ERROR_GATHERER_IGNORE(dbenv);
223
224  new_err = svn_error_createf(SVN_NO_ERROR, NULL, "bdb: %s", msg);
225  if (error_info->pending_errors)
226    svn_error_compose(error_info->pending_errors, new_err);
227  else
228    error_info->pending_errors = new_err;
229
230  if (error_info->user_callback)
231    error_info->user_callback(NULL, (char *)msg); /* ### I hate this cast... */
232}
233
234
235/* Pool cleanup for the cached environment descriptor. */
236static apr_status_t
237cleanup_env(void *data)
238{
239  bdb_env_t *bdb = data;
240  bdb->pool = NULL;
241  bdb->dbconfig_file = NULL;   /* will be closed during pool destruction */
242#if APR_HAS_THREADS
243  apr_threadkey_private_delete(bdb->error_info);
244#endif /* APR_HAS_THREADS */
245
246  /* If there are no references to this descriptor, free its memory here,
247     so that we don't leak it if create_env returns an error.
248     See bdb_close, which takes care of freeing this memory if the
249     environment is still open when the cache is destroyed. */
250  if (!bdb->refcount)
251    free(data);
252
253  return APR_SUCCESS;
254}
255
256#if APR_HAS_THREADS
257/* This cleanup is the fall back plan.  If the thread exits and the
258   environment hasn't been closed it's responsible for cleanup of the
259   thread local error info variable, which would otherwise be leaked.
260   Normally it will not be called, because svn_fs_bdb__close will
261   set the thread's error info to NULL after cleaning it up. */
262static void
263cleanup_error_info(void *baton)
264{
265  bdb_error_info_t *error_info = baton;
266
267  if (error_info)
268    svn_error_clear(error_info->pending_errors);
269
270  free(error_info);
271}
272#endif /* APR_HAS_THREADS */
273
274/* Create a Berkeley DB environment. */
275static svn_error_t *
276create_env(bdb_env_t **bdbp, const char *path, apr_pool_t *pool)
277{
278  int db_err;
279  bdb_env_t *bdb;
280  const char *path_bdb;
281  char *tmp_path, *tmp_path_bdb;
282  apr_size_t path_size, path_bdb_size;
283
284#if SVN_BDB_PATH_UTF8
285  path_bdb = svn_path_local_style(path, pool);
286#else
287  SVN_ERR(svn_utf_cstring_from_utf8(&path_bdb,
288                                    svn_path_local_style(path, pool),
289                                    pool));
290#endif
291
292  /* Allocate the whole structure, including strings, from the heap,
293     because it must survive the cache pool cleanup. */
294  path_size = strlen(path) + 1;
295  path_bdb_size = strlen(path_bdb) + 1;
296  bdb = calloc(1, sizeof(*bdb) + path_size + path_bdb_size);
297
298  /* We must initialize this now, as our callers may assume their bdb
299     pointer is valid when checking for errors.  */
300  apr_pool_cleanup_register(pool, bdb, cleanup_env, apr_pool_cleanup_null);
301  apr_cpystrn(bdb->errpfx_string, BDB_ERRPFX_STRING,
302              sizeof(bdb->errpfx_string));
303  bdb->path = tmp_path = (char*)(bdb + 1);
304  bdb->path_bdb = tmp_path_bdb = tmp_path + path_size;
305  apr_cpystrn(tmp_path, path, path_size);
306  apr_cpystrn(tmp_path_bdb, path_bdb, path_bdb_size);
307  bdb->pool = pool;
308  *bdbp = bdb;
309
310#if APR_HAS_THREADS
311  {
312    apr_status_t apr_err = apr_threadkey_private_create(&bdb->error_info,
313                                                        cleanup_error_info,
314                                                        pool);
315    if (apr_err)
316      return svn_error_create(apr_err, NULL,
317                              "Can't allocate thread-specific storage"
318                              " for the Berkeley DB environment descriptor");
319  }
320#endif /* APR_HAS_THREADS */
321
322  db_err = db_env_create(&(bdb->env), 0);
323  if (!db_err)
324    {
325      /* See the documentation at bdb_env_t's definition why the
326         (char *) cast is safe and why it is done. */
327      bdb->env->set_errpfx(bdb->env, (char *) bdb);
328
329      /* bdb_error_gatherer is in parens to stop macro expansion. */
330      bdb->env->set_errcall(bdb->env, (bdb_error_gatherer));
331
332      /* Needed on Windows in case Subversion and Berkeley DB are using
333         different C runtime libraries  */
334      db_err = bdb->env->set_alloc(bdb->env, malloc, realloc, free);
335
336      /* If we detect a deadlock, select a transaction to abort at
337         random from those participating in the deadlock.  */
338      if (!db_err)
339        db_err = bdb->env->set_lk_detect(bdb->env, DB_LOCK_RANDOM);
340    }
341  return convert_bdb_error(bdb, db_err);
342}
343
344
345
346/* The environment descriptor cache. */
347
348/* The global pool used for this cache. */
349static apr_pool_t *bdb_cache_pool = NULL;
350
351/* The cache.  The items are bdb_env_t structures. */
352static apr_hash_t *bdb_cache = NULL;
353
354#if APR_HAS_THREADS
355/* The mutex that protects bdb_cache. */
356static apr_thread_mutex_t *bdb_cache_lock = NULL;
357
358/* Cleanup callback to NULL out the cache and its lock, so we don't try to
359   use them after the pool has been cleared during global shutdown. */
360static apr_status_t
361clear_cache(void *data)
362{
363  bdb_cache = NULL;
364  bdb_cache_lock = NULL;
365  return APR_SUCCESS;
366}
367#endif /* APR_HAS_THREADS */
368
369static volatile svn_atomic_t bdb_cache_state;
370
371static svn_error_t *
372bdb_init_cb(apr_pool_t *pool)
373{
374#if APR_HAS_THREADS
375  apr_status_t apr_err;
376#endif
377  bdb_cache_pool = svn_pool_create(pool);
378  bdb_cache = apr_hash_make(bdb_cache_pool);
379#if APR_HAS_THREADS
380  apr_err = apr_thread_mutex_create(&bdb_cache_lock,
381                                    APR_THREAD_MUTEX_DEFAULT,
382                                    bdb_cache_pool);
383  if (apr_err)
384    {
385      return svn_error_create(apr_err, NULL,
386                              "Couldn't initialize the cache of"
387                              " Berkeley DB environment descriptors");
388    }
389  apr_pool_cleanup_register(bdb_cache_pool, NULL, clear_cache,
390                            apr_pool_cleanup_null);
391#endif /* APR_HAS_THREADS */
392
393  return SVN_NO_ERROR;
394}
395
396svn_error_t *
397svn_fs_bdb__init(apr_pool_t* pool)
398{
399  return svn_atomic__init_once(&bdb_cache_state, bdb_init_cb, pool);
400}
401
402static APR_INLINE void
403acquire_cache_mutex(void)
404{
405#if APR_HAS_THREADS
406  if (bdb_cache_lock)
407    apr_thread_mutex_lock(bdb_cache_lock);
408#endif
409}
410
411
412static APR_INLINE void
413release_cache_mutex(void)
414{
415#if APR_HAS_THREADS
416  if (bdb_cache_lock)
417    apr_thread_mutex_unlock(bdb_cache_lock);
418#endif
419}
420
421
422/* Construct a cache key for the BDB environment at PATH in *KEYP.
423   if DBCONFIG_FILE is not NULL, return the opened file handle.
424   Allocate from POOL. */
425static svn_error_t *
426bdb_cache_key(bdb_env_key_t *keyp, apr_file_t **dbconfig_file,
427              const char *path, apr_pool_t *pool)
428{
429  const char *dbcfg_file_name = svn_path_join(path, BDB_CONFIG_FILE, pool);
430  apr_file_t *dbcfg_file;
431  apr_status_t apr_err;
432  apr_finfo_t finfo;
433
434  SVN_ERR(svn_io_file_open(&dbcfg_file, dbcfg_file_name,
435                           APR_READ, APR_OS_DEFAULT, pool));
436
437  apr_err = apr_file_info_get(&finfo, APR_FINFO_DEV | APR_FINFO_INODE,
438                              dbcfg_file);
439  if (apr_err)
440    return svn_error_wrap_apr
441      (apr_err, "Can't create BDB environment cache key");
442
443  /* Make sure that any padding in the key is always cleared, so that
444     the key's hash deterministic. */
445  memset(keyp, 0, sizeof *keyp);
446  keyp->device = finfo.device;
447  keyp->inode = finfo.inode;
448
449  if (dbconfig_file)
450    *dbconfig_file = dbcfg_file;
451  else
452    apr_file_close(dbcfg_file);
453
454  return SVN_NO_ERROR;
455}
456
457
458/* Find a BDB environment in the cache.
459   Return the environment's panic state in *PANICP.
460
461   Note: You MUST acquire the cache mutex before calling this function.
462*/
463static bdb_env_t *
464bdb_cache_get(const bdb_env_key_t *keyp, svn_boolean_t *panicp)
465{
466  bdb_env_t *bdb = apr_hash_get(bdb_cache, keyp, sizeof *keyp);
467  if (bdb && bdb->env)
468    {
469      *panicp = !!svn_atomic_read(&bdb->panic);
470#if SVN_BDB_VERSION_AT_LEAST(4,2)
471      if (!*panicp)
472        {
473          u_int32_t flags;
474          if (bdb->env->get_flags(bdb->env, &flags)
475              || (flags & DB_PANIC_ENVIRONMENT))
476            {
477              /* Something is wrong with the environment. */
478              svn_atomic_set(&bdb->panic, TRUE);
479              *panicp = TRUE;
480              bdb = NULL;
481            }
482        }
483#endif /* at least bdb-4.2 */
484    }
485  else
486    {
487      *panicp = FALSE;
488    }
489  return bdb;
490}
491
492
493
494/* Close and destroy a BDB environment descriptor. */
495static svn_error_t *
496bdb_close(bdb_env_t *bdb)
497{
498  svn_error_t *err = SVN_NO_ERROR;
499
500  /* This bit is delcate; we must propagate the error from
501     DB_ENV->close to the caller, and always destroy the pool. */
502  int db_err = bdb->env->close(bdb->env, 0);
503
504  /* If automatic database recovery is enabled, ignore DB_RUNRECOVERY
505     errors, since they're dealt with eventually by BDB itself. */
506  if (db_err && (!SVN_BDB_AUTO_RECOVER || db_err != DB_RUNRECOVERY))
507    err = convert_bdb_error(bdb, db_err);
508
509  /* Free the environment descriptor. The pool cleanup will do this unless
510     the cache has already been destroyed. */
511  if (bdb->pool)
512    svn_pool_destroy(bdb->pool);
513  else
514    free(bdb);
515  return err;
516}
517
518
519svn_error_t *
520svn_fs_bdb__close(bdb_env_baton_t *bdb_baton)
521{
522  svn_error_t *err = SVN_NO_ERROR;
523  bdb_env_t *bdb = bdb_baton->bdb;
524
525  SVN_ERR_ASSERT(bdb_baton->env == bdb_baton->bdb->env);
526
527  /* Neutralize bdb_baton's pool cleanup to prevent double-close. See
528     cleanup_env_baton(). */
529  bdb_baton->bdb = NULL;
530
531  /* Note that we only bother with this cleanup if the pool is non-NULL, to
532     guard against potential races between this and the cleanup_env cleanup
533     callback.  It's not clear if that can actually happen, but better safe
534     than sorry. */
535  if (0 == --bdb_baton->error_info->refcount && bdb->pool)
536    {
537      svn_error_clear(bdb_baton->error_info->pending_errors);
538#if APR_HAS_THREADS
539      free(bdb_baton->error_info);
540      apr_threadkey_private_set(NULL, bdb->error_info);
541#endif
542    }
543
544  acquire_cache_mutex();
545  if (--bdb->refcount != 0)
546    {
547      release_cache_mutex();
548
549      /* If the environment is panicked and automatic recovery is not
550         enabled, return an appropriate error. */
551#if !SVN_BDB_AUTO_RECOVER
552      if (svn_atomic_read(&bdb->panic))
553        err = svn_error_create(SVN_ERR_FS_BERKELEY_DB, NULL,
554                               db_strerror(DB_RUNRECOVERY));
555#endif
556    }
557  else
558    {
559      /* If the bdb cache has been set to NULL that means we are
560         shutting down, and the pool that holds the bdb cache has
561         already been destroyed, so accessing it here would be a Bad
562         Thing (tm) */
563      if (bdb_cache)
564        apr_hash_set(bdb_cache, &bdb->key, sizeof bdb->key, NULL);
565      err = bdb_close(bdb);
566      release_cache_mutex();
567    }
568  return err;
569}
570
571
572
573/* Open and initialize a BDB environment. */
574static svn_error_t *
575bdb_open(bdb_env_t *bdb, u_int32_t flags, int mode)
576{
577#if APR_HAS_THREADS
578  flags |= DB_THREAD;
579#endif
580  SVN_ERR(convert_bdb_error
581          (bdb, (bdb->env->open)(bdb->env, bdb->path_bdb, flags, mode)));
582
583#if SVN_BDB_AUTO_COMMIT
584  /* Assert the BDB_AUTO_COMMIT flag on the opened environment. This
585     will force all operations on the environment (and handles that
586     are opened within the environment) to be transactional. */
587
588  SVN_ERR(convert_bdb_error
589          (bdb, bdb->env->set_flags(bdb->env, SVN_BDB_AUTO_COMMIT, 1)));
590#endif
591
592  return bdb_cache_key(&bdb->key, &bdb->dbconfig_file,
593                       bdb->path, bdb->pool);
594}
595
596
597/* Pool cleanup for the environment baton. */
598static apr_status_t
599cleanup_env_baton(void *data)
600{
601  bdb_env_baton_t *bdb_baton = data;
602
603  if (bdb_baton->bdb)
604    svn_error_clear(svn_fs_bdb__close(bdb_baton));
605
606  return APR_SUCCESS;
607}
608
609
610svn_error_t *
611svn_fs_bdb__open(bdb_env_baton_t **bdb_batonp, const char *path,
612                 u_int32_t flags, int mode,
613                 apr_pool_t *pool)
614{
615  svn_error_t *err = SVN_NO_ERROR;
616  bdb_env_key_t key;
617  bdb_env_t *bdb;
618  svn_boolean_t panic;
619
620  acquire_cache_mutex();
621
622  /* We can safely discard the open DB_CONFIG file handle.  If the
623     environment descriptor is in the cache, the key's immutability is
624     guaranteed.  If it's not, we don't care if the key changes,
625     between here and the actual insertion of the newly-created
626     environment into the cache, because no other thread can touch the
627     cache in the meantime. */
628  err = bdb_cache_key(&key, NULL, path, pool);
629  if (err)
630    {
631      release_cache_mutex();
632      return err;
633    }
634
635  bdb = bdb_cache_get(&key, &panic);
636  if (panic)
637    {
638      release_cache_mutex();
639      return svn_error_create(SVN_ERR_FS_BERKELEY_DB, NULL,
640                              db_strerror(DB_RUNRECOVERY));
641    }
642
643  /* Make sure that the environment's open flags haven't changed. */
644  if (bdb && bdb->flags != flags)
645    {
646      release_cache_mutex();
647
648      /* Handle changes to the DB_PRIVATE flag specially */
649      if ((flags ^ bdb->flags) & DB_PRIVATE)
650        {
651          if (flags & DB_PRIVATE)
652            return svn_error_create(SVN_ERR_FS_BERKELEY_DB, NULL,
653                                    "Reopening a public Berkeley DB"
654                                    " environment with private attributes");
655          else
656            return svn_error_create(SVN_ERR_FS_BERKELEY_DB, NULL,
657                                    "Reopening a private Berkeley DB"
658                                    " environment with public attributes");
659        }
660
661      /* Otherwise return a generic "flags-mismatch" error. */
662      return svn_error_create(SVN_ERR_FS_BERKELEY_DB, NULL,
663                              "Reopening a Berkeley DB environment"
664                              " with different attributes");
665    }
666
667  if (!bdb)
668    {
669      err = create_env(&bdb, path, svn_pool_create(bdb_cache_pool));
670      if (!err)
671        {
672          err = bdb_open(bdb, flags, mode);
673          if (!err)
674            {
675              apr_hash_set(bdb_cache, &bdb->key, sizeof bdb->key, bdb);
676              bdb->flags = flags;
677              bdb->refcount = 1;
678            }
679          else
680            {
681              /* Clean up, and we can't do anything about returned errors. */
682              svn_error_clear(bdb_close(bdb));
683            }
684        }
685    }
686  else
687    {
688      ++bdb->refcount;
689    }
690
691  if (!err)
692    {
693      *bdb_batonp = apr_palloc(pool, sizeof **bdb_batonp);
694      (*bdb_batonp)->env = bdb->env;
695      (*bdb_batonp)->bdb = bdb;
696      (*bdb_batonp)->error_info = get_error_info(bdb);
697      ++(*bdb_batonp)->error_info->refcount;
698      apr_pool_cleanup_register(pool, *bdb_batonp, cleanup_env_baton,
699                                apr_pool_cleanup_null);
700    }
701
702  release_cache_mutex();
703  return err;
704}
705
706
707svn_boolean_t
708svn_fs_bdb__get_panic(bdb_env_baton_t *bdb_baton)
709{
710  /* An invalid baton is equivalent to a panicked environment; in both
711     cases, database cleanups should be skipped. */
712  if (!bdb_baton->bdb)
713    return TRUE;
714
715  assert(bdb_baton->env == bdb_baton->bdb->env);
716  return !!svn_atomic_read(&bdb_baton->bdb->panic);
717}
718
719void
720svn_fs_bdb__set_panic(bdb_env_baton_t *bdb_baton)
721{
722  if (!bdb_baton->bdb)
723    return;
724
725  assert(bdb_baton->env == bdb_baton->bdb->env);
726  svn_atomic_set(&bdb_baton->bdb->panic, TRUE);
727}
728
729
730/* This function doesn't actually open the environment, so it doesn't
731   have to look in the cache.  Callers are supposed to own an
732   exclusive lock on the filesystem anyway. */
733svn_error_t *
734svn_fs_bdb__remove(const char *path, apr_pool_t *pool)
735{
736  bdb_env_t *bdb;
737
738  SVN_ERR(create_env(&bdb, path, pool));
739  return convert_bdb_error
740    (bdb, bdb->env->remove(bdb->env, bdb->path_bdb, DB_FORCE));
741}
Note: See TracBrowser for help on using the repository browser.