summaryrefslogtreecommitdiff
path: root/src/os_common/os_fs_inmemory.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/os_common/os_fs_inmemory.c')
-rw-r--r--src/os_common/os_fs_inmemory.c685
1 files changed, 399 insertions, 286 deletions
diff --git a/src/os_common/os_fs_inmemory.c b/src/os_common/os_fs_inmemory.c
index 260514eac66..53da3f10e5c 100644
--- a/src/os_common/os_fs_inmemory.c
+++ b/src/os_common/os_fs_inmemory.c
@@ -8,475 +8,588 @@
#include "wt_internal.h"
-static int __im_handle_size(WT_SESSION_IMPL *, WT_FH *, wt_off_t *);
-
/*
- * In-memory information.
+ * File system interface for in-memory implementation.
*/
typedef struct {
+ WT_FILE_SYSTEM iface;
+
+ TAILQ_HEAD(__wt_fhhash_inmem,
+ __wt_file_handle_inmem) fhhash[WT_HASH_ARRAY_SIZE];
+ TAILQ_HEAD(__wt_fh_inmem_qh, __wt_file_handle_inmem) fhqh;
+
WT_SPINLOCK lock;
-} WT_IM;
+} WT_FILE_SYSTEM_INMEM;
+
+static int __im_file_size(WT_FILE_HANDLE *, WT_SESSION *, wt_off_t *);
/*
- * __im_directory_list --
- * Get a list of files from a directory, in-memory version.
+ * __im_handle_search --
+ * Return a matching handle, if one exists.
*/
-static int
-__im_directory_list(WT_SESSION_IMPL *session, const char *dir,
- const char *prefix, uint32_t flags, char ***dirlist, u_int *countp)
+static WT_FILE_HANDLE_INMEM *
+__im_handle_search(WT_FILE_SYSTEM *file_system, const char *name)
{
- WT_UNUSED(session);
- WT_UNUSED(dir);
- WT_UNUSED(prefix);
- WT_UNUSED(flags);
- WT_UNUSED(dirlist);
- WT_UNUSED(countp);
+ WT_FILE_HANDLE_INMEM *im_fh;
+ WT_FILE_SYSTEM_INMEM *im_fs;
+ uint64_t bucket, hash;
+
+ im_fs = (WT_FILE_SYSTEM_INMEM *)file_system;
- WT_RET_MSG(session, ENOTSUP, "directory-list");
+ hash = __wt_hash_city64(name, strlen(name));
+ bucket = hash % WT_HASH_ARRAY_SIZE;
+ TAILQ_FOREACH(im_fh, &im_fs->fhhash[bucket], hashq)
+ if (strcmp(im_fh->iface.name, name) == 0)
+ break;
+
+ return (im_fh);
}
/*
- * __im_directory_sync --
- * Flush a directory to ensure file creation is durable.
+ * __im_handle_remove --
+ * Destroy an in-memory file handle. Should only happen on remove or
+ * shutdown.
*/
static int
-__im_directory_sync(WT_SESSION_IMPL *session, const char *path)
+__im_handle_remove(WT_SESSION_IMPL *session,
+ WT_FILE_SYSTEM *file_system, WT_FILE_HANDLE_INMEM *im_fh)
{
- WT_UNUSED(session);
- WT_UNUSED(path);
+ WT_FILE_HANDLE *fhp;
+ WT_FILE_SYSTEM_INMEM *im_fs;
+ uint64_t bucket;
+
+ im_fs = (WT_FILE_SYSTEM_INMEM *)file_system;
+
+ if (im_fh->ref != 0)
+ WT_RET_MSG(session, EBUSY,
+ "%s: file-remove", im_fh->iface.name);
+
+ bucket = im_fh->name_hash % WT_HASH_ARRAY_SIZE;
+ WT_FILE_HANDLE_REMOVE(im_fs, im_fh, bucket);
+
+ /* Clean up private information. */
+ __wt_buf_free(session, &im_fh->buf);
+
+ /* Clean up public information. */
+ fhp = (WT_FILE_HANDLE *)im_fh;
+ __wt_free(session, fhp->name);
+
+ __wt_free(session, im_fh);
+
return (0);
}
/*
- * __im_file_exist --
- * Return if the file exists.
+ * __im_handle_size --
+ * Return the handle's data size.
*/
-static int
-__im_file_exist(WT_SESSION_IMPL *session, const char *name, bool *existp)
+static void
+__im_handle_size(WT_FILE_HANDLE_INMEM *im_fh, wt_off_t *sizep)
{
- *existp = __wt_handle_search(session, name, false, NULL, NULL);
- return (0);
+ /*
+ * XXX
+ * This function exists as a place for this comment. MongoDB assumes
+ * any file with content will have a non-zero size. In memory tables
+ * generally are zero-sized, make MongoDB happy.
+ */
+ *sizep = im_fh->buf.size == 0 ? 1024 : (wt_off_t)im_fh->buf.size;
}
/*
- * __im_file_remove --
- * POSIX remove.
+ * __im_fs_directory_list --
+ * Return the directory contents.
*/
static int
-__im_file_remove(WT_SESSION_IMPL *session, const char *name)
+__im_fs_directory_list(WT_FILE_SYSTEM *file_system,
+ WT_SESSION *wt_session, const char *directory,
+ const char *prefix, char ***dirlistp, uint32_t *countp)
{
WT_DECL_RET;
- WT_FH *fh;
+ WT_FILE_HANDLE_INMEM *im_fh;
+ WT_FILE_SYSTEM_INMEM *im_fs;
+ WT_SESSION_IMPL *session;
+ size_t dirallocsz, len;
+ uint32_t count;
+ char *name, **entries;
+
+ im_fs = (WT_FILE_SYSTEM_INMEM *)file_system;
+ session = (WT_SESSION_IMPL *)wt_session;
+
+ *dirlistp = NULL;
+ *countp = 0;
+
+ dirallocsz = 0;
+ len = strlen(directory);
+ entries = NULL;
+
+ __wt_spin_lock(session, &im_fs->lock);
+
+ count = 0;
+ TAILQ_FOREACH(im_fh, &im_fs->fhqh, q) {
+ name = im_fh->iface.name;
+ if (strncmp(name, directory, len) != 0 ||
+ (prefix != NULL && !WT_PREFIX_MATCH(name + len, prefix)))
+ continue;
+
+ WT_ERR(__wt_realloc_def(
+ session, &dirallocsz, count + 1, &entries));
+ WT_ERR(__wt_strdup(session, name, &entries[count]));
+ ++count;
+ }
- if (__wt_handle_search(session, name, true, NULL, &fh)) {
- WT_ASSERT(session, fh->ref == 1);
+ *dirlistp = entries;
+ *countp = count;
+
+err: __wt_spin_unlock(session, &im_fs->lock);
+ if (ret == 0)
+ return (0);
- /* Force a discard of the handle. */
- F_CLR(fh, WT_FH_IN_MEMORY);
- ret = __wt_close(session, &fh);
+ if (entries != NULL) {
+ while (count > 0)
+ __wt_free(session, entries[--count]);
+ __wt_free(session, entries);
}
- return (ret);
+
+ WT_RET_MSG(session, ret,
+ "%s: directory-list, prefix \"%s\"",
+ directory, prefix == NULL ? "" : prefix);
}
/*
- * __im_file_rename --
- * POSIX rename.
+ * __im_fs_directory_list_free --
+ * Free memory returned by __im_fs_directory_list.
*/
static int
-__im_file_rename(WT_SESSION_IMPL *session, const char *from, const char *to)
+__im_fs_directory_list_free(WT_FILE_SYSTEM *file_system,
+ WT_SESSION *wt_session, char **dirlist, uint32_t count)
{
- WT_CONNECTION_IMPL *conn;
- WT_DECL_RET;
- WT_FH *fh;
- uint64_t bucket, hash;
- char *to_name;
-
- conn = S2C(session);
-
- /* We'll need a copy of the target name. */
- WT_RET(__wt_strdup(session, to, &to_name));
+ WT_SESSION_IMPL *session;
- __wt_spin_lock(session, &conn->fh_lock);
+ WT_UNUSED(file_system);
- /* Make sure the target name isn't active. */
- hash = __wt_hash_city64(to, strlen(to));
- bucket = hash % WT_HASH_ARRAY_SIZE;
- TAILQ_FOREACH(fh, &conn->fhhash[bucket], hashq)
- if (strcmp(to, fh->name) == 0)
- WT_ERR(EPERM);
-
- /* Find the source name. */
- hash = __wt_hash_city64(from, strlen(from));
- bucket = hash % WT_HASH_ARRAY_SIZE;
- TAILQ_FOREACH(fh, &conn->fhhash[bucket], hashq)
- if (strcmp(from, fh->name) == 0)
- break;
- if (fh == NULL)
- WT_ERR(ENOENT);
-
- /* Remove source from the list. */
- WT_CONN_FILE_REMOVE(conn, fh, bucket);
+ session = (WT_SESSION_IMPL *)wt_session;
- /* Swap the names. */
- __wt_free(session, fh->name);
- fh->name = to_name;
- to_name = NULL;
-
- /* Put source back on the list. */
- hash = __wt_hash_city64(to, strlen(to));
- bucket = hash % WT_HASH_ARRAY_SIZE;
- WT_CONN_FILE_INSERT(conn, fh, bucket);
-
- if (0) {
-err: __wt_free(session, to_name);
+ if (dirlist != NULL) {
+ while (count > 0)
+ __wt_free(session, dirlist[--count]);
+ __wt_free(session, dirlist);
}
- __wt_spin_unlock(session, &conn->fh_lock);
-
- return (ret);
+ return (0);
}
/*
- * __im_file_size --
- * Get the size of a file in bytes, by file name.
+ * __im_fs_exist --
+ * Return if the file exists.
*/
static int
-__im_file_size(
- WT_SESSION_IMPL *session, const char *name, bool silent, wt_off_t *sizep)
+__im_fs_exist(WT_FILE_SYSTEM *file_system,
+ WT_SESSION *wt_session, const char *name, bool *existp)
{
- WT_DECL_RET;
- WT_FH *fh;
- WT_IM *im;
+ WT_FILE_SYSTEM_INMEM *im_fs;
+ WT_SESSION_IMPL *session;
- WT_UNUSED(silent);
+ im_fs = (WT_FILE_SYSTEM_INMEM *)file_system;
+ session = (WT_SESSION_IMPL *)wt_session;
- im = S2C(session)->inmemory;
- __wt_spin_lock(session, &im->lock);
+ __wt_spin_lock(session, &im_fs->lock);
- if (__wt_handle_search(session, name, true, NULL, &fh)) {
- WT_ERR(__im_handle_size(session, fh, sizep));
- WT_ERR(__wt_close(session, &fh));
- } else
- ret = ENOENT;
+ *existp = __im_handle_search(file_system, name) != NULL;
-err: __wt_spin_unlock(session, &im->lock);
- return (ret);
+ __wt_spin_unlock(session, &im_fs->lock);
+ return (0);
}
/*
- * __im_handle_advise --
- * POSIX fadvise.
+ * __im_fs_remove --
+ * POSIX remove.
*/
static int
-__im_handle_advise(WT_SESSION_IMPL *session,
- WT_FH *fh, wt_off_t offset, wt_off_t len, int advice)
+__im_fs_remove(
+ WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, const char *name)
{
- WT_UNUSED(session);
- WT_UNUSED(fh);
- WT_UNUSED(offset);
- WT_UNUSED(len);
- WT_UNUSED(advice);
- return (ENOTSUP);
+ WT_DECL_RET;
+ WT_FILE_HANDLE_INMEM *im_fh;
+ WT_FILE_SYSTEM_INMEM *im_fs;
+ WT_SESSION_IMPL *session;
+
+ im_fs = (WT_FILE_SYSTEM_INMEM *)file_system;
+ session = (WT_SESSION_IMPL *)wt_session;
+
+ __wt_spin_lock(session, &im_fs->lock);
+
+ ret = ENOENT;
+ if ((im_fh = __im_handle_search(file_system, name)) != NULL)
+ ret = __im_handle_remove(session, file_system, im_fh);
+
+ __wt_spin_unlock(session, &im_fs->lock);
+ return (ret);
}
/*
- * __im_handle_close --
- * ANSI C close/fclose.
+ * __im_fs_rename --
+ * POSIX rename.
*/
static int
-__im_handle_close(WT_SESSION_IMPL *session, WT_FH *fh)
+__im_fs_rename(WT_FILE_SYSTEM *file_system,
+ WT_SESSION *wt_session, const char *from, const char *to)
{
- __wt_buf_free(session, &fh->buf);
+ WT_DECL_RET;
+ WT_FILE_HANDLE_INMEM *im_fh;
+ WT_FILE_SYSTEM_INMEM *im_fs;
+ WT_SESSION_IMPL *session;
+ uint64_t bucket;
+ char *copy;
+
+ im_fs = (WT_FILE_SYSTEM_INMEM *)file_system;
+ session = (WT_SESSION_IMPL *)wt_session;
+
+ __wt_spin_lock(session, &im_fs->lock);
+
+ ret = ENOENT;
+ if ((im_fh = __im_handle_search(file_system, from)) != NULL) {
+ WT_ERR(__wt_strdup(session, to, &copy));
+ __wt_free(session, im_fh->iface.name);
+ im_fh->iface.name = copy;
+
+ bucket = im_fh->name_hash % WT_HASH_ARRAY_SIZE;
+ WT_FILE_HANDLE_REMOVE(im_fs, im_fh, bucket);
+ im_fh->name_hash = __wt_hash_city64(to, strlen(to));
+ bucket = im_fh->name_hash % WT_HASH_ARRAY_SIZE;
+ WT_FILE_HANDLE_INSERT(im_fs, im_fh, bucket);
+ }
- return (0);
+err: __wt_spin_unlock(session, &im_fs->lock);
+ return (ret);
}
/*
- * __im_handle_getc --
- * ANSI C fgetc.
+ * __im_fs_size --
+ * Get the size of a file in bytes, by file name.
*/
static int
-__im_handle_getc(WT_SESSION_IMPL *session, WT_FH *fh, int *chp)
+__im_fs_size(WT_FILE_SYSTEM *file_system,
+ WT_SESSION *wt_session, const char *name, wt_off_t *sizep)
{
- WT_IM *im;
+ WT_DECL_RET;
+ WT_FILE_HANDLE_INMEM *im_fh;
+ WT_FILE_SYSTEM_INMEM *im_fs;
+ WT_SESSION_IMPL *session;
- im = S2C(session)->inmemory;
- __wt_spin_lock(session, &im->lock);
+ im_fs = (WT_FILE_SYSTEM_INMEM *)file_system;
+ session = (WT_SESSION_IMPL *)wt_session;
- if (fh->off >= fh->buf.size)
- *chp = EOF;
+ __wt_spin_lock(session, &im_fs->lock);
+
+ /* Search for the handle, then get its size. */
+ if ((im_fh = __im_handle_search(file_system, name)) == NULL)
+ ret = ENOENT;
else
- *chp = ((char *)fh->buf.data)[fh->off++];
+ __im_handle_size(im_fh, sizep);
- __wt_spin_unlock(session, &im->lock);
- return (0);
-}
+ __wt_spin_unlock(session, &im_fs->lock);
-/*
- * __im_handle_lock --
- * Lock/unlock a file.
- */
-static int
-__im_handle_lock(WT_SESSION_IMPL *session, WT_FH *fh, bool lock)
-{
- WT_UNUSED(session);
- WT_UNUSED(fh);
- WT_UNUSED(lock);
- return (0);
+ return (ret);
}
/*
- * __im_handle_printf --
- * ANSI C vfprintf.
+ * __im_file_close --
+ * ANSI C close.
*/
static int
-__im_handle_printf(
- WT_SESSION_IMPL *session, WT_FH *fh, const char *fmt, va_list ap)
+__im_file_close(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session)
{
- va_list ap_copy;
- WT_DECL_ITEM(tmp);
- WT_DECL_RET;
- WT_IM *im;
- size_t len;
-
- im = S2C(session)->inmemory;
-
- /* Build the string we're writing. */
- WT_RET(__wt_scr_alloc(session, strlen(fmt) * 2 + 128, &tmp));
- for (;;) {
- va_copy(ap_copy, ap);
- len = (size_t)vsnprintf(tmp->mem, tmp->memsize, fmt, ap_copy);
- va_end(ap_copy);
- if (len < tmp->memsize) {
- tmp->data = tmp->mem;
- tmp->size = len;
- break;
- }
- WT_ERR(__wt_buf_extend(session, tmp, len + 1));
- }
+ WT_FILE_HANDLE_INMEM *im_fh;
+ WT_FILE_SYSTEM_INMEM *im_fs;
+ WT_SESSION_IMPL *session;
- __wt_spin_lock(session, &im->lock);
+ im_fh = (WT_FILE_HANDLE_INMEM *)file_handle;
+ im_fs = (WT_FILE_SYSTEM_INMEM *)file_handle->file_system;
+ session = (WT_SESSION_IMPL *)wt_session;
- /* Grow the handle's buffer as necessary. */
- WT_ERR(__wt_buf_grow(session, &fh->buf, fh->off + len));
+ __wt_spin_lock(session, &im_fs->lock);
- /* Copy the data into place and update the offset. */
- memcpy((uint8_t *)fh->buf.mem + fh->off, tmp->data, len);
- fh->off += len;
+ --im_fh->ref;
-err: __wt_spin_unlock(session, &im->lock);
+ __wt_spin_unlock(session, &im_fs->lock);
- __wt_scr_free(session, &tmp);
- return (ret);
+ return (0);
}
/*
- * __im_handle_read --
+ * __im_file_read --
* POSIX pread.
*/
static int
-__im_handle_read(
- WT_SESSION_IMPL *session, WT_FH *fh, wt_off_t offset, size_t len, void *buf)
+__im_file_read(WT_FILE_HANDLE *file_handle,
+ WT_SESSION *wt_session, wt_off_t offset, size_t len, void *buf)
{
WT_DECL_RET;
- WT_IM *im;
+ WT_FILE_HANDLE_INMEM *im_fh;
+ WT_FILE_SYSTEM_INMEM *im_fs;
+ WT_SESSION_IMPL *session;
size_t off;
- im = S2C(session)->inmemory;
- __wt_spin_lock(session, &im->lock);
+ im_fh = (WT_FILE_HANDLE_INMEM *)file_handle;
+ im_fs = (WT_FILE_SYSTEM_INMEM *)file_handle->file_system;
+ session = (WT_SESSION_IMPL *)wt_session;
+
+ __wt_spin_lock(session, &im_fs->lock);
off = (size_t)offset;
- if (off < fh->buf.size) {
- len = WT_MIN(len, fh->buf.size - off);
- memcpy(buf, (uint8_t *)fh->buf.mem + off, len);
- fh->off = off + len;
+ if (off < im_fh->buf.size) {
+ len = WT_MIN(len, im_fh->buf.size - off);
+ memcpy(buf, (uint8_t *)im_fh->buf.mem + off, len);
+ im_fh->off = off + len;
} else
ret = WT_ERROR;
- __wt_spin_unlock(session, &im->lock);
+ __wt_spin_unlock(session, &im_fs->lock);
if (ret == 0)
return (0);
WT_RET_MSG(session, WT_ERROR,
"%s: handle-read: failed to read %" WT_SIZET_FMT " bytes at "
"offset %" WT_SIZET_FMT,
- fh->name, len, off);
+ file_handle->name, len, off);
}
/*
- * __im_handle_size --
+ * __im_file_size --
* Get the size of a file in bytes, by file handle.
*/
static int
-__im_handle_size(WT_SESSION_IMPL *session, WT_FH *fh, wt_off_t *sizep)
+__im_file_size(
+ WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, wt_off_t *sizep)
{
- WT_UNUSED(session);
+ WT_FILE_HANDLE_INMEM *im_fh;
+ WT_FILE_SYSTEM_INMEM *im_fs;
+ WT_SESSION_IMPL *session;
- /*
- * XXX hack - MongoDB assumes that any file with content will have a
- * non-zero size. In memory tables generally are zero-sized, make
- * MongoDB happy.
- */
- *sizep = fh->buf.size == 0 ? 1024 : (wt_off_t)fh->buf.size;
- return (0);
-}
+ im_fh = (WT_FILE_HANDLE_INMEM *)file_handle;
+ im_fs = (WT_FILE_SYSTEM_INMEM *)file_handle->file_system;
+ session = (WT_SESSION_IMPL *)wt_session;
-/*
- * __im_handle_sync --
- * POSIX fflush/fsync.
- */
-static int
-__im_handle_sync(WT_SESSION_IMPL *session, WT_FH *fh, bool block)
-{
- WT_UNUSED(session);
- WT_UNUSED(fh);
+ __wt_spin_lock(session, &im_fs->lock);
- /*
- * Callers attempting asynchronous flush handle ENOTSUP returns, and
- * won't make further attempts.
- */
- return (block ? 0 : ENOTSUP);
+ __im_handle_size(im_fh, sizep);
+
+ __wt_spin_unlock(session, &im_fs->lock);
+
+ return (0);
}
/*
- * __im_handle_truncate --
+ * __im_file_truncate --
* POSIX ftruncate.
*/
static int
-__im_handle_truncate(WT_SESSION_IMPL *session, WT_FH *fh, wt_off_t offset)
+__im_file_truncate(
+ WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, wt_off_t offset)
{
WT_DECL_RET;
- WT_IM *im;
+ WT_FILE_HANDLE_INMEM *im_fh;
+ WT_FILE_SYSTEM_INMEM *im_fs;
+ WT_SESSION_IMPL *session;
size_t off;
- im = S2C(session)->inmemory;
- __wt_spin_lock(session, &im->lock);
+ im_fh = (WT_FILE_HANDLE_INMEM *)file_handle;
+ im_fs = (WT_FILE_SYSTEM_INMEM *)file_handle->file_system;
+ session = (WT_SESSION_IMPL *)wt_session;
+
+ __wt_spin_lock(session, &im_fs->lock);
/*
- * Grow the buffer as necessary, clear any new space in the file,
- * and reset the file's data length.
+ * Grow the buffer as necessary, clear any new space in the file, and
+ * reset the file's data length.
*/
off = (size_t)offset;
- WT_ERR(__wt_buf_grow(session, &fh->buf, off));
- if (fh->buf.size < off)
- memset((uint8_t *)
- fh->buf.data + fh->buf.size, 0, off - fh->buf.size);
- fh->buf.size = off;
+ WT_ERR(__wt_buf_grow(session, &im_fh->buf, off));
+ if (im_fh->buf.size < off)
+ memset((uint8_t *)im_fh->buf.data + im_fh->buf.size,
+ 0, off - im_fh->buf.size);
+ im_fh->buf.size = off;
-err: __wt_spin_unlock(session, &im->lock);
+err: __wt_spin_unlock(session, &im_fs->lock);
return (ret);
}
/*
- * __im_handle_write --
+ * __im_file_write --
* POSIX pwrite.
*/
static int
-__im_handle_write(WT_SESSION_IMPL *session,
- WT_FH *fh, wt_off_t offset, size_t len, const void *buf)
+__im_file_write(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session,
+ wt_off_t offset, size_t len, const void *buf)
{
WT_DECL_RET;
- WT_IM *im;
+ WT_FILE_HANDLE_INMEM *im_fh;
+ WT_FILE_SYSTEM_INMEM *im_fs;
+ WT_SESSION_IMPL *session;
size_t off;
- im = S2C(session)->inmemory;
- __wt_spin_lock(session, &im->lock);
+ im_fh = (WT_FILE_HANDLE_INMEM *)file_handle;
+ im_fs = (WT_FILE_SYSTEM_INMEM *)file_handle->file_system;
+ session = (WT_SESSION_IMPL *)wt_session;
+
+ __wt_spin_lock(session, &im_fs->lock);
off = (size_t)offset;
- WT_ERR(__wt_buf_grow(session, &fh->buf, off + len + 1024));
+ WT_ERR(__wt_buf_grow(session, &im_fh->buf, off + len + 1024));
- memcpy((uint8_t *)fh->buf.data + off, buf, len);
- if (off + len > fh->buf.size)
- fh->buf.size = off + len;
- fh->off = off + len;
+ memcpy((uint8_t *)im_fh->buf.data + off, buf, len);
+ if (off + len > im_fh->buf.size)
+ im_fh->buf.size = off + len;
+ im_fh->off = off + len;
-err: __wt_spin_unlock(session, &im->lock);
+err: __wt_spin_unlock(session, &im_fs->lock);
if (ret == 0)
return (0);
WT_RET_MSG(session, ret,
"%s: handle-write: failed to write %" WT_SIZET_FMT " bytes at "
"offset %" WT_SIZET_FMT,
- fh->name, len, off);
+ file_handle->name, len, off);
}
/*
- * __im_handle_open --
+ * __im_file_open --
* POSIX fopen/open.
*/
static int
-__im_handle_open(WT_SESSION_IMPL *session,
- WT_FH *fh, const char *path, uint32_t file_type, uint32_t flags)
+__im_file_open(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
+ const char *name, WT_OPEN_FILE_TYPE file_type, uint32_t flags,
+ WT_FILE_HANDLE **file_handlep)
{
- WT_UNUSED(session);
- WT_UNUSED(path);
+ WT_DECL_RET;
+ WT_FILE_HANDLE *file_handle;
+ WT_FILE_HANDLE_INMEM *im_fh;
+ WT_FILE_SYSTEM_INMEM *im_fs;
+ WT_SESSION_IMPL *session;
+ uint64_t bucket, hash;
+
WT_UNUSED(file_type);
WT_UNUSED(flags);
- fh->off = 0;
- F_SET(fh, WT_FH_IN_MEMORY);
+ im_fs = (WT_FILE_SYSTEM_INMEM *)file_system;
+ session = (WT_SESSION_IMPL *)wt_session;
- fh->fh_advise = __im_handle_advise;
- fh->fh_close = __im_handle_close;
- fh->fh_getc = __im_handle_getc;
- fh->fh_lock = __im_handle_lock;
- fh->fh_printf = __im_handle_printf;
- fh->fh_read = __im_handle_read;
- fh->fh_size = __im_handle_size;
- fh->fh_sync = __im_handle_sync;
- fh->fh_truncate = __im_handle_truncate;
- fh->fh_write = __im_handle_write;
+ __wt_spin_lock(session, &im_fs->lock);
- return (0);
+ /*
+ * First search the file queue, if we find it, assert there's only a
+ * single reference, in-memory only supports a single handle on any
+ * file, for now.
+ */
+ im_fh = __im_handle_search(file_system, name);
+ if (im_fh != NULL) {
+
+ if (im_fh->ref != 0)
+ WT_ERR_MSG(session, EBUSY,
+ "%s: file-open: already open", name);
+
+ im_fh->ref = 1;
+ im_fh->off = 0;
+
+ *file_handlep = (WT_FILE_HANDLE *)im_fh;
+
+ __wt_spin_unlock(session, &im_fs->lock);
+ return (0);
+ }
+
+ /* The file hasn't been opened before, create a new one. */
+ WT_ERR(__wt_calloc_one(session, &im_fh));
+
+ /* Initialize public information. */
+ file_handle = (WT_FILE_HANDLE *)im_fh;
+ file_handle->file_system = file_system;
+ WT_ERR(__wt_strdup(session, name, &file_handle->name));
+
+ /* Initialize private information. */
+ im_fh->ref = 1;
+ im_fh->off = 0;
+
+ hash = __wt_hash_city64(name, strlen(name));
+ bucket = hash % WT_HASH_ARRAY_SIZE;
+ im_fh->name_hash = hash;
+ WT_FILE_HANDLE_INSERT(im_fs, im_fh, bucket);
+
+ file_handle->close = __im_file_close;
+ file_handle->read = __im_file_read;
+ file_handle->size = __im_file_size;
+ file_handle->truncate = __im_file_truncate;
+ file_handle->write = __im_file_write;
+
+ *file_handlep = file_handle;
+
+ if (0) {
+err: __wt_free(session, im_fh);
+ }
+
+ __wt_spin_unlock(session, &im_fs->lock);
+ return (ret);
}
/*
- * __wt_os_inmemory --
- * Initialize an in-memory configuration.
+ * __im_terminate --
+ * Terminate an in-memory configuration.
*/
-int
-__wt_os_inmemory(WT_SESSION_IMPL *session)
+static int
+__im_terminate(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session)
{
- WT_CONNECTION_IMPL *conn;
WT_DECL_RET;
- WT_IM *im;
+ WT_FILE_HANDLE_INMEM *im_fh;
+ WT_FILE_SYSTEM_INMEM *im_fs;
+ WT_SESSION_IMPL *session;
- conn = S2C(session);
- im = NULL;
+ WT_UNUSED(file_system);
- /* Initialize the in-memory jump table. */
- conn->file_directory_list = __im_directory_list;
- conn->file_directory_sync = __im_directory_sync;
- conn->file_exist = __im_file_exist;
- conn->file_remove = __im_file_remove;
- conn->file_rename = __im_file_rename;
- conn->file_size = __im_file_size;
- conn->handle_open = __im_handle_open;
-
- /* Allocate an in-memory structure. */
- WT_RET(__wt_calloc_one(session, &im));
- WT_ERR(__wt_spin_init(session, &im->lock, "in-memory I/O"));
- conn->inmemory = im;
+ session = (WT_SESSION_IMPL *)wt_session;
+ im_fs = (WT_FILE_SYSTEM_INMEM *)file_system;
- return (0);
+ while ((im_fh = TAILQ_FIRST(&im_fs->fhqh)) != NULL)
+ WT_TRET(__im_handle_remove(session, file_system, im_fh));
+
+ __wt_spin_destroy(session, &im_fs->lock);
+ __wt_free(session, im_fs);
-err: __wt_free(session, im);
return (ret);
}
/*
- * __wt_os_inmemory_cleanup --
- * Discard an in-memory configuration.
+ * __wt_os_inmemory --
+ * Initialize an in-memory configuration.
*/
int
-__wt_os_inmemory_cleanup(WT_SESSION_IMPL *session)
+__wt_os_inmemory(WT_SESSION_IMPL *session)
{
WT_DECL_RET;
- WT_IM *im;
+ WT_FILE_SYSTEM *file_system;
+ WT_FILE_SYSTEM_INMEM *im_fs;
+ u_int i;
- if ((im = S2C(session)->inmemory) == NULL)
- return (0);
- S2C(session)->inmemory = NULL;
+ WT_RET(__wt_calloc_one(session, &im_fs));
+
+ /* Initialize private information. */
+ TAILQ_INIT(&im_fs->fhqh);
+ for (i = 0; i < WT_HASH_ARRAY_SIZE; i++)
+ TAILQ_INIT(&im_fs->fhhash[i]);
- __wt_spin_destroy(session, &im->lock);
- __wt_free(session, im);
+ WT_ERR(__wt_spin_init(session, &im_fs->lock, "in-memory I/O"));
+
+ /* Initialize the in-memory jump table. */
+ file_system = (WT_FILE_SYSTEM *)im_fs;
+ file_system->directory_list = __im_fs_directory_list;
+ file_system->directory_list_free = __im_fs_directory_list_free;
+ file_system->exist = __im_fs_exist;
+ file_system->open_file = __im_file_open;
+ file_system->remove = __im_fs_remove;
+ file_system->rename = __im_fs_rename;
+ file_system->size = __im_fs_size;
+ file_system->terminate = __im_terminate;
+
+ /* Switch the file system into place. */
+ S2C(session)->file_system = (WT_FILE_SYSTEM *)im_fs;
+
+ return (0);
+err: __wt_free(session, im_fs);
return (ret);
}