ShingledFS 2.0
SMR-AwareFUSE-basedFileSystem

band_log.c

00001 
00002 
00003 #define _XOPEN_SOURCE 500
00004 #include <unistd.h>
00005 #include <stdio.h>
00006 #include <sys/types.h>
00007 #include <sys/stat.h>
00008 #include <fcntl.h>
00009 #include <limits.h>
00010 
00011 
00012 #include "helper.h"
00013 #include "common.h"
00014 #include "errno.h"
00015 #include "string.h"
00016 
00017 #include <stdlib.h>
00018 
00019 
00020 #include "band_log.h"
00021 
00022 
00023 
00024 #define FILE_BANDLOG_APPEND_PREFIX              "/.smr_append_log_"
00025 #define FILE_BANDLOG_DELETE_PREFIX              "/.smr_delete_log_"
00026 
00027 
00028 /*
00029  * @brief : Initialize the store log for the given band number.
00030  *
00031  * @param band_num : Band number.
00032  *
00033  * @return fd : File descriptor.
00034  *         -ve number : on Error.
00035  *
00036  */
00037 
00038 int init_storelog(int band_num)
00039 {
00040     int fd;
00041     char band_name[PATH_MAX];
00042     char path[PATH_MAX];
00043 
00044     sprintf(band_name, "%s%d", FILE_BANDLOG_APPEND_PREFIX, band_num);
00045     translate_path(band_name, SFSDATA.path_unshingled, path);
00046 
00047     fd = open(path, O_RDWR | O_APPEND | O_CREAT | O_EXCL, 0644);
00048 
00049     if (fd < 0) {
00050         //append log file already exist.
00051         fd = open(path, O_RDWR | O_APPEND);
00052         if (fd < 0) {
00053             dbg("Error opening store log: %s \n", strerror(errno));
00054             return -1;
00055         }
00056         return fd;
00057     }
00058 
00059     return fd;
00060 }
00061 
00062 
00063 /*
00064  * @brief : Initialize the delete log for a band.
00065  *
00066  * @param band_num : Band number.
00067  *
00068  * @return fd : File descriptor.
00069  *         -ve number : on Error.
00070  *
00071  */
00072 
00073 int init_deletelog(int band_num)
00074 {
00075     int fd;
00076     char band_name[PATH_MAX];
00077     char path[PATH_MAX];
00078 
00079     sprintf(band_name, "%s%d", FILE_BANDLOG_DELETE_PREFIX, band_num);
00080     translate_path(band_name, SFSDATA.path_unshingled, path);
00081 
00082     fd = open(path, O_RDWR | O_APPEND | O_CREAT | O_EXCL, 0644);
00083 
00084     if (fd < 0) {
00085         //delete log file already exist.
00086         fd = open(path, O_RDWR | O_APPEND);  
00087         if (fd < 0) {
00088             dbg("Error opening delete log  \n");
00089             return -1;
00090         }
00091         return fd;
00092     }
00093 
00094     return fd;
00095 }
00096 
00097 
00098 /*
00099  * @brief : Deletes the store log for given band.
00100  *
00101  * @param band_num : Band number.
00102  *
00103  * @return : None.
00104  *
00105  */
00106 
00107 void clear_storelog(int band_num)
00108 {
00109     char band_name[PATH_MAX];
00110     char path[PATH_MAX];
00111 
00112     sprintf(band_name, "%s%d", FILE_BANDLOG_APPEND_PREFIX, band_num);
00113     translate_path(band_name, SFSDATA.path_unshingled, path);
00114  
00115     unlink(path);
00116 }
00117 
00118 
00119 /*
00120  * @brief : Deletes the delete log for given band. Is called when a band is
00121  *          cleaned.
00122  *
00123  * @param band_num : Band number.
00124  * @param path_unshingled : Path to the unshingled drive.
00125  *
00126  * @return : None.
00127  *
00128  */
00129 
00130 void clear_deletelog(int band_num)
00131 {
00132     char band_name[PATH_MAX];
00133     char path[PATH_MAX];
00134 
00135     sprintf(band_name, "%s%d", FILE_BANDLOG_DELETE_PREFIX, band_num);
00136     translate_path(band_name, SFSDATA.path_unshingled, path);
00137 
00138     unlink(path);
00139 }
00140 
00141 
00142 /*
00143  * @brief : Appends an entry to the store log.
00144  *
00145  * @param fd : File descriptor.
00146  * @param offset : Offset in the band where the file is stored.
00147  * @param size : Size of the file.
00148  * @param inode_num : inode number of the file.
00149  *
00150  * @return : Index of the appended entry.
00151  *
00152  */
00153 
00154 int  append_storelog(int fd, int offset, int size, int inode_num, long int age)
00155 {
00156     struct store_entry entry;
00157     struct stat filestat;
00158     int entrynumber;
00159 
00160     entry.offset = offset;
00161     entry.size = size;
00162     entry.inode_num = inode_num;
00163     entry.age = age;
00164 
00165     if (write(fd, &entry, sizeof(struct store_entry)) < 0) {
00166         dbg("Error writing to the append log in append_storelog \n");
00167         exit(1);
00168     }
00169 
00170     //Calculate the index of the insertion using the file size.
00171     fstat(fd, &filestat);
00172     entrynumber = filestat.st_size / (sizeof(struct store_entry));
00173 
00174     return entrynumber;
00175 }
00176 
00177 
00178 /*
00179  * @brief : Appends an entry to the delete log.
00180  *
00181  * @param fd : File descriptor.
00182  * @param offset : Offset in the band where the file was stored.
00183  * @param size : Size of the file.
00184  * @param entrynumber : Index in the append log.
00185  *
00186  * @return : None.
00187  */
00188 
00189 void append_deletelog(int fd, int offset, int size, int entrynumber)
00190 {
00191     struct delete_entry entry;;
00192 
00193     entry.offset = offset;
00194     entry.size = size;
00195     entry.entrynumber = entrynumber;
00196 
00197     if (write(fd, &entry, sizeof(struct delete_entry)) < 0) {
00198         dbg("Error writing delete log in append_deletelog\n");
00199         exit(1);
00200     }
00201 }
00202 
00203 
00204 /*
00205  * @brief : List the entries of the band where the data is live on the band.
00206  *
00207  * @param band_num : Band number.
00208  * @param store_fd : File Descriptor for append log.
00209  * @param delete_fd : File Descriptor for delete log.
00210  * @param length : Pointer to store the number of entries returned.
00211  * @param livedatasize : Number of live block in the band.
00212  *
00213  * @return : List of struct containing append log entries not present in delete
00214  *           log. The list of structure is malloced here and needs tobe freed 
00215  *           by the user afterwards.
00216  *
00217  */
00218 
00219 struct store_entry*  get_livelog(int band_num, int store_fd, int delete_fd,
00220                                  int *length, int *livedatablocks)
00221 {
00222     struct store_entry *live;
00223     struct delete_entry del;
00224     struct store_entry entry;
00225     int *deleted;
00226     int numentries;
00227     int delentries;
00228     int i;
00229     int livecount = 0;
00230     int liveblock = 0;
00231 
00232     struct stat filestat;
00233 
00234     fstat(store_fd, &filestat);
00235     numentries = filestat.st_size / sizeof(struct store_entry);
00236 
00237     fstat(delete_fd, &filestat);
00238     delentries = filestat.st_size / sizeof(struct delete_entry);
00239 
00240     deleted = (int *) calloc (numentries, sizeof(int));
00241     if (deleted == NULL) {
00242         dbg("Memory allocation failed in get_livelog\n");
00243         exit(1);
00244     }
00245 
00246     //Read the delete log and mark the entires which are deleted in a array.
00247     for (i = 0; i < delentries; i++) {
00248         pread(delete_fd, &del, sizeof(struct delete_entry), 
00249               i * sizeof(struct delete_entry));
00250 
00251         if (del.entrynumber > numentries) {
00252             dbg("wrong value of delete entry \n");
00253             exit(1);
00254         }
00255 
00256         deleted[del.entrynumber - 1] = 1;
00257     }
00258 
00259     live = (struct store_entry *) calloc((numentries - delentries),
00260                                                                           sizeof(struct store_entry));
00261     if (live == NULL) {
00262         dbg("Malloc failed \n");
00263         exit(1);
00264     }
00265 
00266     //Now using the array, read only those entries which are not present in the
00267     //delete log.
00268     for (i = 0; i < numentries; i++) {
00269         if (deleted[i] == 0) {
00270             if (pread(store_fd, &entry, sizeof(struct store_entry),
00271                   i * sizeof(struct store_entry)) < 0) {
00272                 dbg("Error reading the store log in get_livelog \n");
00273             }
00274 
00275             live[livecount] = entry;
00276             liveblock = liveblock + entry.size;
00277             livecount++;
00278         }
00279     }
00280 
00281     *length = livecount;
00282     *livedatablocks = liveblock;
00283     free(deleted);
00284     return live;
00285 
00286 }
00287 
00288 
00289 /*
00290  * @brief : Returns the size of the band currently used.
00291  *
00292  * @param band_num : Band number.
00293  *
00294  * @return size : Size of the band used.
00295  *            -1 : on Error.
00296  *
00297  */
00298 
00299 int band_occupancy(int band_num)
00300 {
00301     int fd;
00302     char band_name[PATH_MAX];
00303     char path[PATH_MAX];
00304     struct store_entry lastentry;
00305     int error;
00306 
00307     sprintf(band_name, "%s%d", FILE_BANDLOG_APPEND_PREFIX, band_num);
00308     translate_path(band_name, SFSDATA.path_unshingled, path);
00309 
00310     fd = open(path, O_RDWR);
00311     if (fd < 0) {
00312         dbg("Error opening store log file in band_occupancy \n");
00313         return -1;
00314     }
00315 
00316     lseek(fd, -1 * (sizeof(struct store_entry)), SEEK_END);
00317     error = read(fd, &lastentry, sizeof(struct store_entry));
00318 
00319     close(fd);
00320     if (error < 0) {
00321         dbg("Error reading the store log in band_occupancy \n");
00322         return -1;
00323     }
00324 
00325     if (error == 0) {
00326         return 0;
00327     }
00328 
00329     return lastentry.offset + lastentry.size;
00330 }
00331 
00332 
00333 /*
00334  * @brief : Returns the age of the band currently used.
00335  *
00336  * @param band_num : Band number.
00337  *
00338  * @return age : Age of the band.
00339  *            -1 : on Error.
00340  *
00341  */
00342 
00343 int band_age(int band_num)
00344 {
00345     int fd;
00346     char band_name[PATH_MAX];
00347     char path[PATH_MAX];
00348     struct store_entry firstentry;
00349     int error;
00350 
00351     //TODO: Currently returns the age of the first file.
00352     //Needs to parse the entire log to get the age of the band.
00353 
00354     sprintf(band_name, "%s%d", FILE_BANDLOG_APPEND_PREFIX, band_num);
00355     translate_path(band_name, SFSDATA.path_unshingled, path);
00356 
00357     fd = open(path, O_RDWR);
00358     if (fd < 0) {
00359         dbg("Error opening store log in band_age \n");
00360         return -1;
00361     }
00362 
00363     error = read(fd, &firstentry, sizeof(struct store_entry));
00364 
00365     close(fd);
00366     if (error < 0) {
00367         dbg("Error reading append log in band_age \n");
00368         return -1;
00369     }
00370 
00371     if (error == 0) {
00372         return 0;
00373     }
00374 
00375     return firstentry.age;
00376 }
00377 
00378 
00379 /*
00380  * @brief : Return the number of entries in the delete log.
00381  *          Function currently used in cleaning for the base line
00382  *          cleaning thread.
00383  * 
00384  * @param band_num : Band number.
00385  *
00386  * @return num_entries : Number of entries in delete log.
00387  *
00388  */
00389 
00390 int band_delentries(int band_num)
00391 {
00392     char band_name[PATH_MAX];
00393     char path[PATH_MAX];
00394     struct stat filestat;
00395     int error;
00396     int num_entries;
00397 
00398     sprintf(band_name, "%s%d", FILE_BANDLOG_DELETE_PREFIX, band_num);
00399     translate_path(band_name, SFSDATA.path_unshingled, path);
00400 
00401     error = stat(path, &filestat);
00402     if (error == -1) {
00403         if (errno == ENOENT) {
00404             //delete log does not exist for file
00405             return 0;
00406         }
00407         return 0;
00408     }
00409 
00410     num_entries = filestat.st_size / sizeof (struct delete_entry);
00411     return num_entries;
00412 }