ShingledFS 2.0
SMR-AwareFUSE-basedFileSystem

cleaning_thread.c

00001 
00002 
00003 
00004 #include <stdio.h>
00005 #include <sys/types.h>
00006 #include <sys/stat.h>
00007 #include <fcntl.h>
00008 #include <unistd.h>
00009 #include <signal.h>
00010 #include <string.h>
00011 #include <assert.h>
00012 
00013 #include "band_log.h"
00014 
00015 #define _XOPEN_SOURCE 500
00016 #include <unistd.h>
00017 #include <semaphore.h>
00018 #include <pthread.h>
00019 #include <stdlib.h>
00020 
00021 #include "band_bitmap.h"
00022 #include "cleaning_thread.h"
00023 #include "common.h"
00024 #include "inode.h"
00025 #include "emulator.h"
00026 
00027 
00028 static sem_t cleaner_sem;
00029 
00030 
00031 static void sig_handler(int signal);
00032 
00033 
00034 
00035 /*
00036  * @brief : Spawns a cleaning thread and intializes the cleaning parameters.
00037  *
00038  * @param : None.
00039  *
00040  * @return 0 : on Success.
00041  *         -1 : on Error.
00042  *
00043  */
00044 
00045 int cleaner_init(void)
00046 {
00047     int err;
00048     pthread_t tid;
00049 
00050     if ((err = pthread_create(&tid, NULL, band_cleaner, NULL)) != 0) {
00051         log(LOG_CLN_ERRORS, "Error creating thread: %s\n", strerror(err));
00052         return -1;
00053     }
00054 
00055 
00056     // Install the signal handler
00057     signal(SIGUSR1, sig_handler);
00058 
00059     return 0;
00060 }
00061 
00062 
00063 
00064 /*
00065  * @brief : Cleaning thread created by the cleaner_init function. It waits on
00066  *          a semaphore to be signalled by the signal handler to start 
00067  *          cleaning. Currently ascynchronus cleaning is supported. It will
00068  *          clean all bands one by one and then will again wait on the semaphore
00069  *          once all the bands are cleaned. It also intializes the log
00070  *          functions for the cleaning thread.
00071  *
00072  * @param sfs : Pointer to fuse context data.
00073  *
00074  * @return : None.
00075  *
00076  */
00077 
00078 void * band_cleaner()
00079 {     
00080     //Initialize the log file creation.
00081 #ifdef GENERATE_LOGS
00082     char filename[50];
00083     int len;
00084     time_t curtime = time(NULL);
00085 
00086 
00087     /* Initialize the logging interface */
00088     len = strftime(filename, 50, "/tmp/smr%Y%m%d%H%M%S_cleaner.log",
00089             localtime(&curtime));
00090     if (!len) {
00091         fprintf(stderr, "Error generating log file name: %s\n", filename);
00092         assert(0);
00093     }
00094     log_open(filename);
00095 #endif
00096 
00097 
00098 
00099     init_semcleaner();
00100 
00101 
00102     while(1) {
00103         wait_cleaner();
00104 
00105         //Fucntion will clean all the bands on the disk.
00106         band_cleanall();
00107 
00108     }
00109 }
00110 
00111 
00112 /*
00113  * @brief : Fucntion will clean all the band on the disk. Will return once all
00114  *          the bands are cleaned. When this fucntion is running no other
00115  *          activity should be running on the file system.
00116  *
00117  * @param sfs : Pointer to fuse context.
00118  *
00119  * @return : None.
00120  *
00121  */
00122 
00123 void band_cleanall()
00124 {
00125     int i;
00126 
00127     while (1) {
00128         i = band_cleaning();
00129         if (i == -1) {
00130             break;
00131         }
00132     }
00133 }
00134 
00135 
00136 /*
00137  * @breif : Cleans one band at a time.
00138  *          Selects one band for cleaning and one band to clean to.
00139  *          Once the band are selected according to the policies then they
00140  *          are cleaned. The updates of the data and inode takes place in 
00141  *          a particular order to avaoid inconsistencies during failure.
00142  *
00143  * @param 
00144  *
00145  * @return 0 : on Success.
00146  *         -1 : no band left to clean.
00147  *
00148  */
00149 
00150 int band_cleaning()
00151 {
00152     int band_frag;
00153     int band_clean;
00154     struct store_entry *live;  
00155     int livedata;
00156     int length;
00157     int frag_storefd;
00158     int frag_deletefd;
00159     int write_pointer = 0;
00160 
00161 
00162     //TODO: Acquire locks before writing to the band. In the functions select
00163     //the locks should be acaquired. Thus one the band is selected, no one uses
00164     //it for writing.
00165 
00166     band_frag = select_fragband();
00167     if (band_frag == 0) {
00168         return -1;
00169     }
00170 
00171     //Get the fd's for store log and append log.
00172     frag_storefd = init_storelog(band_frag);
00173     if (frag_storefd == -1) {
00174         exit(EXIT_FAILURE);
00175     }
00176 
00177     frag_deletefd = init_deletelog(band_frag);
00178     if (frag_deletefd == -1) {
00179         exit(EXIT_FAILURE);
00180     }
00181 
00182     live = get_livelog(band_frag, frag_storefd, frag_deletefd, &length,
00183                        &livedata);
00184 
00185     close(frag_storefd);
00186     close(frag_deletefd);
00187 
00188     band_clean = select_cleanband(livedata);
00189 
00190     if (band_clean == 0) {
00191         exit(EXIT_FAILURE);
00192     }
00193 
00194     migrate_data(band_frag, band_clean, live, length);
00195 
00196     clear_storelog(band_frag);
00197     clear_deletelog(band_frag);
00198 
00199     //TODO:Update the locks of both the bands.
00200 
00201     if (edi_managebands(SFSDATA.fd_edi, SVC_SETPTR, &band_frag, &write_pointer,
00202                                                             sizeof(rba_t))) {
00203         exit(EXIT_FAILURE);
00204     } 
00205 
00206     free(live);
00207     return 0;
00208 
00209 }
00210 
00211 
00212 /*
00213  * @brief : The function migrates data from one band to another band.
00214  *
00215  * @param band_frag : Band id of the band to be cleaned.
00216  * @param band_clean : Band id of the band to clean to.
00217  * @param live : Array of store entries i.e. live data's metadata for the band.
00218  * @param length : Length of the array live.
00219  *
00220  * @return : None.
00221  *
00222  */
00223 
00224 void migrate_data(int band_frag, int band_clean,
00225                   struct store_entry *live, int length)
00226 {
00227     int i;
00228     int write_pointer;
00229     inode_t temp_inode;
00230     int index;
00231     int clean_storefd;
00232     int err;
00233 
00234     if (edi_managebands(SFSDATA.fd_edi, SVC_GETPTR, &band_clean, &write_pointer,
00235                                                             sizeof(rba_t))) {
00236         exit(EXIT_FAILURE);
00237     }
00238 
00239     clean_storefd = init_storelog(band_clean);
00240     if (clean_storefd == -1) {
00241         exit(EXIT_FAILURE);
00242     }
00243 
00244     for(i = 0; i < length; i++) {
00245         
00246         err = get_inode(live[i].inode_num, &temp_inode);
00247         if (err == -1) {
00248             exit(EXIT_FAILURE);
00249         }
00250 
00251         copy_data(band_frag, band_clean, live[i].offset, live[i].size,
00252                   write_pointer);
00253         
00254         //TODO: Update the age correctly.
00255         index = append_storelog(clean_storefd, write_pointer, live[i].size,
00256                                 live[i].inode_num, 0);
00257 
00258         temp_inode.entrynumber = index;
00259         temp_inode.band_id = band_clean;
00260         temp_inode.band_offset = write_pointer;
00261         
00262         err = put_inode(live[i].inode_num, &temp_inode);
00263         if (err == -1) {
00264             exit(EXIT_FAILURE);
00265         }
00266 
00267         write_pointer = write_pointer + live[i].size;
00268 
00269     }
00270 
00271     close(clean_storefd);
00272 }
00273 
00274 
00275 /*
00276  * @brief : Called by the cleaner thread to wait for the signal/
00277  *
00278  * @param : None.
00279  *
00280  * @return : None.
00281  *
00282  */
00283 
00284 void wait_cleaner(void)
00285 {
00286     sem_wait(&cleaner_sem);
00287 }
00288 
00289 
00290 /*
00291  * @brief : Called by the signal handler to woka up the cleaning thread. 
00292  *
00293  * @param : None.
00294  *
00295  * @return : None.
00296  *
00297  */
00298 
00299 void signal_cleaner(void)
00300 {
00301     sem_post(&cleaner_sem);
00302 }
00303 
00304 
00305 /*
00306  * @brief : Initialize the cleaner semaphore.
00307  *
00308  * @param : None.
00309  *
00310  * @return : None.
00311  *
00312  */
00313 
00314 void init_semcleaner(void)
00315 {   
00316     int error;
00317     error = sem_init(&cleaner_sem, 0, 0);
00318     if (error != 0) {
00319         log(LOG_CLN_ERRORS, "Error initializing semaphore for the cleaner. \n");
00320     }
00321 }
00322 
00323 
00324 /*
00325  * @brief : Copy data from one band to another band with the given band offset
00326  *          and size.
00327  *
00328  * @param band_src : Source band number.
00329  * @param band_dst : Destination band number.
00330  * @param offset_src : Sorce band rba.
00331  * @param len_src : Length of copy.
00332  * @param offset_dst : Destination band rba.
00333  *
00334  * @return None.
00335  *
00336  */
00337 
00338 void copy_data(int band_src, int band_dst, int offset_src, int len_src, 
00339                int offset_dst)
00340 {
00341     char *buf;
00342 
00343     buf = (char *) malloc (len_src * SFSDATA.edi_blksize);
00344     if (buf == NULL) {
00345         exit(EXIT_FAILURE);
00346     }
00347 
00348     if (edi_read(SFSDATA.fd_edi, band_src, offset_src, buf, len_src)) {
00349        exit(EXIT_FAILURE);
00350     }
00351 
00352     if (edi_write(SFSDATA.fd_edi, band_dst, offset_dst, buf, len_src)) {
00353         exit(EXIT_FAILURE);
00354     }
00355 
00356 }
00357 
00358 
00359 
00360 static void sig_handler(int signal) {
00361     /* Check the signal received */
00362     if (signal == SIGUSR1)
00363         signal_cleaner();
00364 }