Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Blow away vcachefs code that doesn't apply to us, add C++ support so we

can make a C interface to GridFS
  • Loading branch information...
commit bdbfba57f97985b2054d0eb543ac6109441096eb 1 parent b0ee176
Paul Betts authored
Showing with 20 additions and 386 deletions.
  1. +1 −0  configure.ac
  2. +1 −2  src/Makefile.am
  3. +18 −367 src/mongodbfs.c
  4. +0 −17 src/mongodbfs.h
1  configure.ac
View
@@ -8,6 +8,7 @@ AM_PROG_LIBTOOL
AC_ISC_POSIX
AC_PROG_CC
+AC_PROG_CXX
AC_C_INLINE
AC_STDC_HEADERS
AC_PROG_INSTALL
3  src/Makefile.am
View
@@ -16,5 +16,4 @@ mongodbfs_LDADD = $(MONGODBFS_LIBS) -lgthread-2.0 -lpthread \
mongodbfs_SOURCES = \
mongodbfs.c \
stats.c \
- queue.c \
- cachemgr.c
+ queue.c
385 src/mongodbfs.c
View
@@ -34,6 +34,7 @@
#include <sys/statvfs.h>
#include <dirent.h>
#include <unistd.h>
+#include <signal.h>
#include <fuse.h>
#include <glib.h>
@@ -42,7 +43,6 @@
#include "mongodbfs.h"
#include "stats.h"
#include "queue.h"
-#include "cachemgr.h"
/* Globals */
GIOChannel* stats_file = NULL;
@@ -75,10 +75,6 @@ static struct mongodbfs_fdentry* fdentry_ref(struct mongodbfs_fdentry* obj)
static void fdentry_unref(struct mongodbfs_fdentry* obj)
{
if(g_atomic_int_dec_and_test(&obj->refcnt)) {
- if(obj->source_fd > 0)
- close(obj->source_fd);
- if(obj->filecache_fd > 0)
- close(obj->filecache_fd);
g_free(obj->relative_path);
g_free(obj);
}
@@ -96,202 +92,6 @@ static struct mongodbfs_fdentry* fdentry_from_fd(uint fd)
return (ret ? fdentry_ref(ret) : NULL);
}
-static char* build_cache_path(const char* source_path)
-{
- const char* env = getenv("MONGODBFS_CACHEPATH");
- char* cache_root;
- if (env) {
- cache_root = g_strdup(env);
- } else {
- cache_root = g_build_filename(getenv("HOME"), ".mongodbfs", NULL);
- }
-
- // Calculate the MD5 of the source path
- gchar* sum = NULL;
- gchar* ret = NULL;
- sum = g_compute_checksum_for_string(G_CHECKSUM_MD5, source_path, -1);
- ret = g_build_filename(cache_root, sum, NULL);
- g_free(sum);
-
- g_free(cache_root);
- return ret;
-}
-
-
-/*
- * File-based cache functions
- */
-
-static int try_open_from_cache(const char* cache_root, const char* relative_path, int flags)
-{
- gchar* path = g_build_filename(cache_root, relative_path, NULL);
- int ret = open(path, flags, 0);
- g_free(path);
-
- return ret;
-}
-
-static int copy_file_and_return_destfd(const char* source_root, const char* dest_root, const char* relative_path, gint* quitflag_atomic)
-{
- gchar* src_path = g_build_filename(source_root, relative_path, NULL);
- gchar* dest_path = g_build_filename(dest_root, relative_path, NULL);
- int src_fd = 0, dest_fd = 0;
-
- g_debug("Copying '%s' to '%s'", src_path, dest_path);
- src_fd = open(src_path, O_RDONLY);
- dest_fd = open(dest_path, O_RDWR | O_CREAT | O_EXCL, S_IRWXU | S_IRGRP | S_IROTH);
- if (src_fd <= 0 || dest_fd <= 0)
- goto out;
-
- stats_write_record(stats_file, "copyfile", 0, 0, relative_path);
-
- /* We've got files, let's go to town */
- char buf[4096];
- int has_read, has_written;
- do {
- has_read = read(src_fd, buf, 4096);
-
- if (g_atomic_int_get(quitflag_atomic)) {
- has_read = -1;
- has_written = -1;
- break;
- }
-
- has_written = 0;
- if (has_read > 0)
- has_written = write(dest_fd, buf, has_read);
- } while (has_read > 0 && has_written == has_read );
-
- /* Something has gone wrong */
- if (has_written != has_read || has_read < 0) {
- unlink(dest_path);
- close(dest_fd);
- dest_fd = -1;
- goto out;
- }
-
- g_debug("Copy succeeded");
- lseek(dest_fd, 0, SEEK_SET);
-
-out:
- g_debug("Exiting, dest_fd = %d", dest_fd);
- if (src_fd > 0)
- close(src_fd);
- g_free(src_path);
- g_free(dest_path);
-
- return dest_fd;
-}
-
-/* Stupid struct to pass a tuple through to this fn */
-struct cache_entry {
- int fd;
- char* relative_path;
-};
-
-static void add_cache_fd_to_item(gpointer key, gpointer value, gpointer cache_entry)
-{
- /* NOTE: Since we've grabbed the fd table lock before this function, we don't need
- * to grab a reference to the fd entry */
- struct mongodbfs_fdentry* fde = value;
- struct cache_entry* ce = cache_entry;
- if (strcmp(fde->relative_path, ce->relative_path))
- return;
-
- int fd = dup(ce->fd);
- lseek(fd, 0, SEEK_SET);
-
- /* Maybe some thread beat us to it? */
- if (fde->source_fd > 0) {
- int tmp = fde->source_fd;
- fde->source_fd = 0;
- close(tmp);
- }
-
- fde->source_offset = fd;
- fde->source_fd = fd;
-}
-
-static gpointer file_cache_copy_thread(gpointer data)
-{
- struct mongodbfs_mount* mount_obj = data;
-
- g_debug("Starting cache copy thread...");
- while(g_atomic_int_get(&mount_obj->quitflag_atomic) == 0) {
- int err, destfd;
- struct stat st;
- struct cache_entry ce;
- GTimeVal five_secs_from_now;
- char* relative_path;
-
- g_get_current_time(&five_secs_from_now);
- g_time_val_add(&five_secs_from_now, 5 * 1000 * 1000);
- relative_path = g_async_queue_timed_pop(mount_obj->file_copy_queue, &five_secs_from_now);
-
- /* We didn't have anything to do - let's clean up the cache */
- if (!relative_path) {
- cache_manager_reclaim_space(mount_obj->cache_manager, mount_obj->max_cache_size);
- continue;
- }
-
- /* Create the parent directory if we have to */
- char* dirname = g_path_get_dirname(relative_path);
- char* parent_path = g_build_filename(mount_obj->cache_path, dirname, NULL);
- g_debug("Starting copy, picked up '%s'", relative_path);
- err = lstat(parent_path, &st);
- if (err == -1 && errno == ENOENT) {
- g_debug("Creating '%s'", parent_path);
- if (g_mkdir_with_parents(parent_path, 5+7*8+7*8*8) != 0)
- goto done;
- }
- if(err < 0) /* Couldn't create dir */
- goto done;
-
- destfd = copy_file_and_return_destfd(mount_obj->source_path, mount_obj->cache_path,
- relative_path, &mount_obj->quitflag_atomic);
-
- if (destfd < 0)
- goto done;
-
- ce.fd = destfd; ce.relative_path = relative_path;
-
- /* Grab the file table lock, and set the source file handle for every file */
- g_static_rw_lock_writer_lock(&mount_obj->fd_table_rwlock);
- g_hash_table_foreach(mount_obj->fd_table, add_cache_fd_to_item, &ce);
- g_static_rw_lock_writer_unlock(&mount_obj->fd_table_rwlock);
-
- /* Notify the cache manager */
- char* dest_path = g_build_filename(mount_obj->cache_path, relative_path, NULL);
- cache_manager_notify_added(mount_obj->cache_manager, dest_path);
- g_free(dest_path);
-
- /* Let go of our original fd */
- close(destfd);
-
-done:
- g_free(dirname);
- g_free(parent_path);
- g_free(relative_path);
- }
- g_debug("Ending cache copy thread...");
-
- return NULL;
-}
-
-gboolean can_delete_cached_file(const char* path, gpointer context)
-{
- /* Blowing away files who we have an open handle to is probably bad */
- struct mongodbfs_mount* mount_obj = context;
- gboolean ret;
-
- g_static_rw_lock_reader_lock(&mount_obj->fd_table_rwlock);
- /* FIXME: Relative path? */
- ret = (g_hash_table_lookup(mount_obj->fd_table_byname, path) != NULL);
- g_static_rw_lock_reader_unlock(&mount_obj->fd_table_rwlock);
-
- return ret;
-}
-
static void insert_fdtable_entry(struct mongodbfs_mount* mount_obj, struct mongodbfs_fdentry* fde)
{
g_hash_table_insert(mount_obj->fd_table, &fde->fd, fde);
@@ -309,7 +109,7 @@ static void insert_fdtable_entry(struct mongodbfs_mount* mount_obj, struct mongo
static gpointer force_terminate_on_ioblock(gpointer dontcare)
{
sleep(15);
- kill(0, SIGKILL);
+ //kill(0, SIGKILL);
return 0;
}
@@ -334,14 +134,6 @@ static void trash_fdtable_item(gpointer key, gpointer val, gpointer dontcare)
static void* mongodbfs_init(struct fuse_conn_info *conn)
{
struct mongodbfs_mount* mount_object = g_new0(struct mongodbfs_mount, 1);
- mount_object->source_path = g_strdup(getenv("MONGODBFS_TARGET"));
- mount_object->cache_path = build_cache_path(mount_object->source_path);
-
- /* TODO: This is actually a config param */
- mount_object->max_cache_size = 20 * 1024 * 1024;
-
- if (getenv("MONGODBFS_PASSTHROUGH"))
- mount_object->pass_through = 1;
g_thread_init(NULL);
@@ -353,15 +145,8 @@ static void* mongodbfs_init(struct fuse_conn_info *conn)
g_static_rw_lock_init(&mount_object->fd_table_rwlock);
mount_object->next_fd = 4;
- mount_object->cache_manager = cache_manager_new(mount_object->cache_path, can_delete_cached_file, mount_object);
mount_object->work_queue = workitem_queue_new();
- /* Set up the file cache thread */
- mount_object->file_copy_queue = g_async_queue_new();
- mount_object->file_copy_thread = g_thread_create(file_cache_copy_thread, mount_object, TRUE/*joinable*/, NULL);
-
- stats_write_record(stats_file, "init_target", 0, 0, mount_object->cache_path);
-
return mount_object;
}
@@ -375,23 +160,7 @@ static void mongodbfs_destroy(void *mount_object_ptr)
* that we can do about it, except for force kill everyone involved. */
g_thread_create(force_terminate_on_ioblock, NULL, FALSE, NULL);
- /* Signal the file cache thread to terminate and wait for it
- * XXX: if the thread hangs, we're boned - no way to timeout this */
- g_atomic_int_set(&mount_object->quitflag_atomic, 1);
- g_thread_join(mount_object->file_copy_thread);
-
- /* Free the async queue */
- char* item;
- g_async_queue_lock(mount_object->file_copy_queue);
- while ( (item = g_async_queue_try_pop_unlocked(mount_object->file_copy_queue)) ) {
- if (item)
- g_free(item);
- }
- g_async_queue_unlock(mount_object->file_copy_queue);
- g_async_queue_unref(mount_object->file_copy_queue);
-
workitem_queue_free(mount_object->work_queue);
- cache_manager_free(mount_object->cache_manager);
/* XXX: We need to make sure no one is using this before we trash it */
g_hash_table_foreach(mount_object->fd_table, trash_fdtable_item, NULL);
@@ -400,8 +169,6 @@ static void mongodbfs_destroy(void *mount_object_ptr)
g_hash_table_destroy(mount_object->fd_table_byname);
mount_object->fd_table = NULL;
mount_object->fd_table_byname = NULL;
- g_free(mount_object->cache_path);
- g_free(mount_object->source_path);
g_free(mount_object);
stats_close_logging(stats_file);
@@ -418,27 +185,8 @@ static int is_quitting(struct mongodbfs_mount* mount_obj)
static int mongodbfs_getattr(const char *path, struct stat *stbuf)
{
- int ret = 0;
- struct mongodbfs_mount* mount_obj = get_current_mountinfo();
-
- if(path == NULL || strlen(path) == 0) {
- return -ENOENT;
- }
-
- /* On shutdown, fail new requests */
- if(is_quitting(mount_obj))
- return -EIO;
-
- stats_write_record(stats_file, "getattr", 0, 0, path);
- if(strcmp(path, "/") == 0) {
- return (stat(mount_obj->source_path, stbuf) ? -errno : 0);
- }
-
- gchar* full_path = g_build_filename(mount_obj->source_path, &path[1], NULL);
- ret = stat((char *)full_path, stbuf);
- g_free(full_path);
-
- return (ret ? -errno : 0);
+ // XXX: Implement me
+ return -EIO;
}
static int mongodbfs_open(const char *path, struct fuse_file_info *fi)
@@ -454,46 +202,22 @@ static int mongodbfs_open(const char *path, struct fuse_file_info *fi)
if(is_quitting(mount_obj))
return -EIO;
- gchar* full_path = g_build_filename(mount_obj->source_path, &path[1], NULL);
-
- int source_fd = open(full_path, fi->flags, 0);
- if(source_fd <= 0)
- return -errno;
-
/* Open succeeded - time to create a fdentry */
fde = fdentry_new();
fde->relative_path = g_strdup(path);
- fde->source_fd = source_fd;
- fde->source_offset = 0;
g_static_rw_lock_writer_lock(&mount_obj->fd_table_rwlock);
fi->fh = fde->fd = mount_obj->next_fd;
- mount_obj->next_fd++;
+ mount_obj->next_fd++; // XXX: Atomic, you dumb fuck!
insert_fdtable_entry(mount_obj, fde);
g_static_rw_lock_writer_unlock(&mount_obj->fd_table_rwlock);
- if (mount_obj->pass_through)
- goto out;
-
- /* Try to open the file cached version; if it's not there, add it to the fetch list */
- if( (fde->filecache_fd = try_open_from_cache(mount_obj->cache_path, path, fi->flags)) == -1 && errno == ENOENT) {
- g_async_queue_push(mount_obj->file_copy_queue, g_strdup(path));
- }
-
- /* Touch the file so it doesn't get reclaimed by the cache manager */
- if (fde->filecache_fd) {
- gchar* full_cache_path = g_build_filename(mount_obj->cache_path, path, NULL);
- cache_manager_touch_file(mount_obj->cache_manager, full_cache_path);
- g_free(full_cache_path);
- }
-
-out:
-
/* FUSE handles this differently */
stats_write_record(stats_file, "open", 0, 0, path);
return 0;
}
+#if 0
static int read_from_fd(int fd, off_t* cur_offset, char* buf, size_t size, off_t offset)
{
int ret = 0;
@@ -512,6 +236,7 @@ static int read_from_fd(int fd, off_t* cur_offset, char* buf, size_t size, off_t
out:
return ret;
}
+#endif
static int mongodbfs_read(const char *path, char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
@@ -526,18 +251,10 @@ static int mongodbfs_read(const char *path, char *buf, size_t size, off_t offset
if(is_quitting(mount_obj))
return -EIO;
- /* Let's see if we can do this read from the file cache */
- if (!mount_obj->pass_through &&
- (ret = read_from_fd(fde->filecache_fd, &fde->filecache_offset, buf, size, offset)) >= 0) {
- stats_write_record(stats_file, "cached_read", size, offset, path);
- goto out;
- }
-
- stats_write_record(stats_file, "uncached_read", size, offset, path);
- ret = read_from_fd(fde->source_fd, &fde->source_offset, buf, size, offset);
+ // XXX: Implement Me!
+ return -EIO;
-out:
- fdentry_unref(fde);
+ fdentry_unref(fde); // XXX: Is this right?
return (ret < 0 ? -errno : ret);
}
@@ -549,7 +266,8 @@ static int mongodbfs_statfs(const char *path, struct statvfs *stat)
if(is_quitting(mount_obj))
return -EIO;
- return statvfs(mount_obj->source_path, stat);
+ // XXX: Implement me!
+ return -EIO;
}
static int mongodbfs_release(const char *path, struct fuse_file_info *info)
@@ -586,6 +304,7 @@ static int mongodbfs_release(const char *path, struct fuse_file_info *info)
if(!fde)
return -ENOENT;
+ // XXX: Is this correct?
fdentry_unref(fde);
return 0;
@@ -602,31 +321,17 @@ static int mongodbfs_access(const char *path, int amode)
/* On shutdown, fail new requests */
if(is_quitting(mount_obj))
return -EIO;
-
- if(!mount_obj->pass_through && strcmp(path, "/") == 0) {
- stats_write_record(stats_file, "cached_access", amode, 0, path);
- return access(mount_obj->source_path, amode);
- }
-
- stats_write_record(stats_file, "uncached_access", amode, 0, path);
- gchar* full_path = g_build_filename(mount_obj->source_path, &path[1], NULL);
- ret = access((char *)full_path, amode);
- g_free(full_path);
+
+ // XXX: Implement me
+ return -EIO;
return (ret < 0 ? errno : ret);
-
}
static int mongodbfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi)
{
- int ret;
- gchar* full_path = NULL;
- const gchar* next_path_try;
struct mongodbfs_mount* mount_obj = get_current_mountinfo();
- DIR* dir = NULL;
- struct dirent* dentry;
- char path_buf[512];
if(path == NULL || strlen(path) == 0)
return -ENOENT;
@@ -635,54 +340,11 @@ static int mongodbfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler
if(is_quitting(mount_obj))
return -EIO;
- /* Try the source path first; if it's gone, retry with the cache */
- next_path_try = mount_obj->source_path;
- while (next_path_try) {
- if(strcmp(path, "/") == 0) {
- full_path = g_strdup(next_path_try);
- } else {
- full_path = g_build_filename(next_path_try, &path[1], NULL);
- }
-
- /* Open the directory and read through it */
- if ((dir = opendir(full_path)) != NULL)
- break;
-
- next_path_try = (next_path_try == mount_obj->source_path && !mount_obj->pass_through ?
- mount_obj->cache_path : NULL);
- g_free(full_path);
- }
-
- /* No dice - bail */
- if (dir == NULL) {
- opendir(full_path);
- g_free(full_path);
- return -errno;
- }
+ // XXX: Implement me
+ return -EIO;
stats_write_record(stats_file, "readdir", offset, 0, path);
- /* mkdir -p the cache directory */
- if(strcmp(path, "/") != 0 && !mount_obj->pass_through) {
- char* cache_path = g_build_filename(mount_obj->cache_path, &path[1], NULL);
- g_mkdir_with_parents(cache_path, 5+7*8+7*8*8);
- g_free(cache_path);
- }
-
- while((dentry = readdir(dir))) {
- struct stat stbuf;
- int stat_ret;
-
- /* Stat the file */
- snprintf(path_buf, 512, "%s/%s", full_path, dentry->d_name);
- stat_ret = stat(path_buf, &stbuf);
-
- if ((ret = filler(buf, dentry->d_name, (stat_ret>=0 ? &stbuf : NULL), 0)))
- goto out;
- }
-
-out:
- closedir(dir);
return 0;
}
@@ -714,16 +376,5 @@ static struct fuse_operations mongodbfs_oper = {
int main(int argc, char *argv[])
{
- /* Check for our environment variables
- * FIXME: There's got to be a less dumb way to do this */
- if (!getenv("MONGODBFS_TARGET")) {
- printf(" *** Please set the MONGODBFS_TARGET environment variable to the path that "
- "should be mirrored! ***\n");
- return -1;
- }
-
- /* Initialize libevent */
- //ev_base = event_init();
-
return fuse_main(argc, argv, &mongodbfs_oper, NULL);
}
17 src/mongodbfs.h
View
@@ -33,12 +33,6 @@
/* This object is the per-mount data we carry around with us throughout the
* life of the app until we release it */
struct mongodbfs_mount {
-
- /* Configuration */
- char* source_path;
- char* cache_path;
- gulong max_cache_size;
- int pass_through;
/* File descriptor table */
GHashTable* fd_table;
@@ -46,11 +40,6 @@ struct mongodbfs_mount {
uint next_fd;
GStaticRWLock fd_table_rwlock;
- /* File-based caching */
- GAsyncQueue* file_copy_queue;
- GThread* file_copy_thread;
- struct CacheManager* cache_manager;
-
gint quitflag_atomic;
struct WorkitemQueue* work_queue;
};
@@ -60,12 +49,6 @@ struct mongodbfs_fdentry {
char* relative_path;
uint fd;
-
- uint64_t source_fd;
- off_t source_offset;
-
- uint64_t filecache_fd;
- off_t filecache_offset;
};
#endif
Please sign in to comment.
Something went wrong with that request. Please try again.