summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Bostic <keith@wiredtiger.com>2013-05-30 10:05:45 -0400
committerKeith Bostic <keith@wiredtiger.com>2013-05-30 10:05:45 -0400
commit89875776720570a20bad157b7dfd50fb498308e8 (patch)
treedd06acde9c177d0e38eeed7e42bcacfc404352fb
parent6660da16da1edbc0255452c72af8fa72a3f8a3ec (diff)
downloadmongo-89875776720570a20bad157b7dfd50fb498308e8.tar.gz
Change hot-backup to acquire a handle on each underlying file object to ensure
schema level operations (for example, drop), will be blocked until the backup cursor closes.
-rw-r--r--src/cursor/cur_backup.c67
-rw-r--r--src/include/cursor.h10
-rw-r--r--src/include/wt_internal.h2
-rw-r--r--src/lsm/lsm_worker.c24
4 files changed, 61 insertions, 42 deletions
diff --git a/src/cursor/cur_backup.c b/src/cursor/cur_backup.c
index 53b1729aa0f..e5f3880753e 100644
--- a/src/cursor/cur_backup.c
+++ b/src/cursor/cur_backup.c
@@ -32,13 +32,13 @@ __curbackup_next(WT_CURSOR *cursor)
cb = (WT_CURSOR_BACKUP *)cursor;
CURSOR_API_CALL(cursor, session, next, NULL);
- if (cb->list == NULL || cb->list[cb->next] == NULL) {
+ if (cb->list == NULL || cb->list[cb->next].name == NULL) {
F_CLR(cursor, WT_CURSTD_KEY_SET);
WT_ERR(WT_NOTFOUND);
}
- cb->iface.key.data = cb->list[cb->next];
- cb->iface.key.size = WT_STORE_SIZE(strlen(cb->list[cb->next]) + 1);
+ cb->iface.key.data = cb->list[cb->next].name;
+ cb->iface.key.size = WT_STORE_SIZE(strlen(cb->list[cb->next].name) + 1);
++cb->next;
F_SET(cursor, WT_CURSTD_KEY_RET);
@@ -76,22 +76,28 @@ static int
__curbackup_close(WT_CURSOR *cursor)
{
WT_CURSOR_BACKUP *cb;
+ WT_CURSOR_BACKUP_ENTRY *p;
WT_DECL_RET;
WT_SESSION_IMPL *session;
- char **p;
int tret;
cb = (WT_CURSOR_BACKUP *)cursor;
CURSOR_API_CALL(cursor, session, close, NULL);
- /* Free the list of files. */
+ /* Release the handles, free the file names, free the list itself. */
if (cb->list != NULL) {
- for (p = cb->list; *p != NULL; ++p)
- __wt_free(session, *p);
+ for (p = cb->list; p->name != NULL; ++p) {
+ if (p->handle != NULL)
+ WT_WITH_DHANDLE(session, p->handle,
+ WT_TRET(
+ __wt_session_release_btree(session)));
+ __wt_free(session, p->name);
+ }
+
__wt_free(session, cb->list);
}
- ret = __wt_cursor_close(cursor);
+ WT_TRET(__wt_cursor_close(cursor));
session->bkp_cursor = NULL;
WT_WITH_SCHEMA_LOCK(session,
@@ -313,8 +319,7 @@ __backup_all(WT_SESSION_IMPL *session, WT_CURSOR_BACKUP *cb)
break;
if (strcmp(uri, WT_METADATA_URI) == 0)
continue;
- WT_ERR(
- __backup_list_append(session, cb, uri + strlen("file:")));
+ WT_ERR(__backup_list_append(session, cb, uri));
}
WT_ERR_NOTFOUND_OK(ret);
@@ -416,10 +421,9 @@ __wt_backup_list_append(WT_SESSION_IMPL *session, const char *name)
WT_RET_TEST(
(fprintf(cb->bfp, "%s\n%s\n", name, value) < 0), __wt_errno());
- /* Add to the list of files needing to be copied. */
+ /* Add file type objects to the list of files to be copied. */
if (WT_PREFIX_MATCH(name, "file:"))
- WT_RET(
- __backup_list_append(session, cb, name + strlen("file:")));
+ WT_RET(__backup_list_append(session, cb, name));
return (0);
}
@@ -430,12 +434,28 @@ __wt_backup_list_append(WT_SESSION_IMPL *session, const char *name)
*/
static int
__backup_list_append(
- WT_SESSION_IMPL *session, WT_CURSOR_BACKUP *cb, const char *name)
+ WT_SESSION_IMPL *session, WT_CURSOR_BACKUP *cb, const char *uri)
{
+ WT_CURSOR_BACKUP_ENTRY *p;
+ WT_DATA_HANDLE *old_dhandle;
+ WT_DECL_RET;
+ const char *name;
+ int need_handle;
+
/* Leave a NULL at the end to mark the end of the list. */
if (cb->list_next + 1 * sizeof(char *) >= cb->list_allocated)
WT_RET(__wt_realloc(session, &cb->list_allocated,
(cb->list_next + 100) * sizeof(char *), &cb->list));
+ p = &cb->list[cb->list_next];
+ p[0].name = p[1].name = NULL;
+ p[0].handle = p[1].handle = NULL;
+
+ need_handle = 0;
+ name = uri;
+ if (WT_PREFIX_MATCH(uri, "file:")) {
+ need_handle = 1;
+ name += strlen("file:");
+ }
/*
* !!!
@@ -446,9 +466,22 @@ __backup_list_append(
* that for now, that block manager might not even support physical
* copying of files by applications.
*/
- WT_RET(__wt_strdup(
- session, name, &cb->list[cb->list_next++]));
- cb->list[cb->list_next] = NULL;
+ WT_RET(__wt_strdup(session, name, &p->name));
+
+ /*
+ * If it's a file in the database, get a handle for the underlying
+ * object (this handle blocks schema level operations, for example
+ * WT_SESSION.drop or an LSM file discard after level merging).
+ */
+ if (need_handle) {
+ old_dhandle = session->dhandle;
+ if ((ret =
+ __wt_session_get_btree(session, uri, NULL, NULL, 0)) == 0)
+ p->handle = session->dhandle;
+ session->dhandle = old_dhandle;
+ WT_RET(ret);
+ }
+ ++cb->list_next;
return (0);
}
diff --git a/src/include/cursor.h b/src/include/cursor.h
index d1af0aa2798..a86b4b5f702 100644
--- a/src/include/cursor.h
+++ b/src/include/cursor.h
@@ -52,15 +52,19 @@
0 /* uint32_t flags */ \
}
+struct __wt_cursor_backup_entry {
+ char *name; /* File name */
+ WT_DATA_HANDLE *handle; /* Handle */
+};
struct __wt_cursor_backup {
WT_CURSOR iface;
size_t next; /* Cursor position */
+ FILE *bfp; /* Backup file */
- size_t list_allocated; /* List of files */
+ WT_CURSOR_BACKUP_ENTRY *list; /* List of files to be copied. */
+ size_t list_allocated;
size_t list_next;
- char **list;
- FILE *bfp;
};
struct __wt_cursor_btree {
diff --git a/src/include/wt_internal.h b/src/include/wt_internal.h
index 71c5c433035..690d8c9fba3 100644
--- a/src/include/wt_internal.h
+++ b/src/include/wt_internal.h
@@ -99,6 +99,8 @@ struct __wt_connection_stats;
typedef struct __wt_connection_stats WT_CONNECTION_STATS;
struct __wt_cursor_backup;
typedef struct __wt_cursor_backup WT_CURSOR_BACKUP;
+struct __wt_cursor_backup_entry;
+ typedef struct __wt_cursor_backup_entry WT_CURSOR_BACKUP_ENTRY;
struct __wt_cursor_btree;
typedef struct __wt_cursor_btree WT_CURSOR_BTREE;
struct __wt_cursor_bulk;
diff --git a/src/lsm/lsm_worker.c b/src/lsm/lsm_worker.c
index e039c3e20f8..bc892b3309a 100644
--- a/src/lsm/lsm_worker.c
+++ b/src/lsm/lsm_worker.c
@@ -432,17 +432,11 @@ __lsm_discard_handle(
static int
__lsm_drop_file(WT_SESSION_IMPL *session, const char *uri)
{
- WT_CONNECTION_IMPL *conn;
WT_DECL_RET;
const char *drop_cfg[] = {
WT_CONFIG_BASE(session, session_drop), "remove_files=false", NULL
};
- conn = S2C(session);
- /* Give up early if a hot backup is in progress. */
- if (conn->hot_backup != 0)
- return (EBUSY);
-
/*
* We need to grab the schema lock to drop the file, so first try to
* make sure there is minimal work to freeing space in the cache.
@@ -452,27 +446,13 @@ __lsm_drop_file(WT_SESSION_IMPL *session, const char *uri)
WT_RET(__lsm_discard_handle(session, uri, "WiredTigerCheckpoint"));
/*
- * Take the hot backup lock to prevent new backups starting. Don't
- * proceed if a backup has started since we first checked.
- */
- __wt_spin_lock(session, &conn->hot_backup_lock);
- if (conn->hot_backup != 0) {
- __wt_spin_unlock(session, &conn->hot_backup_lock);
- return (EBUSY);
- }
-
- /*
* Take the schema lock for the drop operation. Play games with the
* hot backup lock. Since __wt_schema_drop results in the hot backup
* lock being taken when it updates the metadata (which would be too
* late to prevent our drop).
*/
- __wt_spin_lock(session, &S2C(session)->schema_lock);
- F_SET(session, WT_SESSION_SCHEMA_LOCKED);
- __wt_spin_unlock(session, &conn->hot_backup_lock);
- ret = __wt_schema_drop(session, uri, drop_cfg);
- F_CLR(session, WT_SESSION_SCHEMA_LOCKED);
- __wt_spin_unlock(session, &S2C(session)->schema_lock);
+ WT_WITH_SCHEMA_LOCK(session,
+ ret = __wt_schema_drop(session, uri, drop_cfg));
if (ret == 0)
ret = __wt_remove(session, uri + strlen("file:"));