X-Git-Url: http://git.vrable.net/?a=blobdiff_plain;f=bluesky%2Fcleaner.c;h=3f6b685f06e1eaefe5ae5b26917c5bb6280e2181;hb=HEAD;hp=ec2b5dd99eff09a8b2de80ec9730f50a8223529f;hpb=77511ae98a27a2db081b6e8b5374c4bf955b655f;p=bluesky.git diff --git a/bluesky/cleaner.c b/bluesky/cleaner.c index ec2b5dd..3f6b685 100644 --- a/bluesky/cleaner.c +++ b/bluesky/cleaner.c @@ -3,7 +3,29 @@ * Copyright (C) 2010 The Regents of the University of California * Written by Michael Vrable * - * TODO: Licensing + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #include @@ -115,7 +137,8 @@ static BlueSkyCleanerItem *bluesky_cleaner_find_checkpoint(BlueSkyFS *fs) if (last_segment == NULL) return NULL; - g_print("Last cloud log segment: %s\n", last_segment); + g_print("Last cloud log segment: %s (processed up to %d)\n", + last_segment, fs->log_state->latest_cleaner_seq_seen); int seq = atoi(last_segment + 13); g_free(last_segment); @@ -142,8 +165,11 @@ static BlueSkyCleanerItem *bluesky_cleaner_find_checkpoint(BlueSkyFS *fs) length = item->length; } - if (length == 0) + if (length == 0) { + bluesky_cachefile_unref(cachefile); + g_mutex_unlock(cachefile->lock); return NULL; + } g_print("Found a cleaner checkpoint record.\n"); @@ -152,6 +178,8 @@ static BlueSkyCleanerItem *bluesky_cleaner_find_checkpoint(BlueSkyFS *fs) g_mutex_unlock(cachefile->lock); BlueSkyCleanerItem *checkpoint = bluesky_cleaner_deserialize(data); + checkpoint->location.directory = BLUESKY_CLOUD_DIR_CLEANER; + checkpoint->location.sequence = seq; bluesky_string_unref(data); return checkpoint; @@ -197,6 +225,29 @@ gboolean needs_merging(BlueSkyFS *fs, BlueSkyCloudPointer location) return TRUE; } +/* For an inode which has been modified by the cleaner and must be flushed out + * to cloud storage, mark it as appropriately dirty. We will bypass writingt + * the inode to the journal if possible--but if there have ben other + * uncommitted changes besides what the cleaner did then we will force a + * journal write as well since the cloud shouldn't contain newer data than the + * journal. Inode must be locked. */ +static void cleaner_flush_inode(BlueSkyInode *inode) +{ + // if (inode->change_commit != inode->change_count) { + if (TRUE) { + /* bluesky_inode_start_sync schedules a flush to the cloud so we're all + * done. */ + bluesky_inode_start_sync(inode); + return; + } + + g_assert(inode->unlogged_list == NULL); + + bluesky_list_unlink(&inode->fs->dirty_list, inode->dirty_list); + inode->dirty_list = bluesky_list_prepend(&inode->fs->dirty_list, inode); + inode->change_cloud = inode->change_count; +} + static void merge_inode(BlueSkyFS *fs, BlueSkyCleanerItem *cleaner_inode) { /* There are two versions we are concerned with: cleaner_ is for the data @@ -216,8 +267,8 @@ static void merge_inode(BlueSkyFS *fs, BlueSkyCleanerItem *cleaner_inode) BlueSkyCloudLog *proxy_item = entry->item; g_mutex_lock(proxy_item->lock); - BlueSkyCloudPointer proxy_location = entry->item->location; - BlueSkyCloudID proxy_id = entry->item->id; + //BlueSkyCloudPointer proxy_location = entry->item->location; + //BlueSkyCloudID proxy_id = entry->item->id; g_mutex_unlock(proxy_item->lock); g_mutex_unlock(fs->lock); @@ -251,6 +302,7 @@ static void merge_inode(BlueSkyFS *fs, BlueSkyCleanerItem *cleaner_inode) b->ref->location = cb->location; } } + cleaner_flush_inode(proxy_inode); g_mutex_unlock(proxy_inode->lock); /* Mark the inode as modified so it will get written back to the cloud. We @@ -273,6 +325,12 @@ void bluesky_cleaner_merge(BlueSkyFS *fs) return; } + if (checkpoint->type != LOGTYPE_CHECKPOINT) { + g_warning("Last cleaner object not a checkpoint; cleaning probably in progress."); + bluesky_cleaner_item_free(checkpoint); + return; + } + /* Iterate over each of the inode map sections in the checkpoint */ for (int i = 0; i < checkpoint->links->len; i++) { BlueSkyCleanerLink *link = &g_array_index(checkpoint->links, @@ -302,5 +360,25 @@ void bluesky_cleaner_merge(BlueSkyFS *fs) bluesky_cleaner_item_free(imap); } + fs->log_state->latest_cleaner_seq_seen = checkpoint->location.sequence; bluesky_cleaner_item_free(checkpoint); } + +/* Run the cleaner as a background task. */ +static gpointer cleaner_thread(BlueSkyFS *fs) +{ + while (TRUE) { + struct timespec delay; + delay.tv_sec = 30; + delay.tv_nsec = 0; + nanosleep(&delay, NULL); + bluesky_cleaner_merge(fs); + } + + return NULL; +} + +void bluesky_cleaner_thread_launch(BlueSkyFS *fs) +{ + g_thread_create((GThreadFunc)cleaner_thread, fs, FALSE, NULL); +}