ShingledFS 2.0
SMR-AwareFUSE-basedFileSystem

edistats.c

00001 
00010 #include <errno.h>
00011 #include <stdio.h>
00012 #include <string.h>
00013 #include <stdlib.h>
00014 #include <unistd.h>
00015 #include <limits.h>
00016 
00017 #include "debug.h"
00018 #include "common.h"
00019 #include "helper.h"
00020 #include "emulator.h"
00021 #include "band_bitmap.h"
00022 #include "band_log.h"
00023 
00024 
00025 
00026 /* ======================= */
00027 /* -- Macro Definitions -- */
00028 /* ======================= */
00029 
00030 #define ARG_COUNT_MIN                   4
00031 
00032 #define ARG_PATH_EDI                    1
00033 #define ARG_PATH_USHNG                  2
00034 #define ARG_PATH_OUTPUT                 3
00035 
00036 
00037 
00038 /* ====================== */
00039 /* -- Type Definitions -- */
00040 /* ====================== */
00041 
00042 
00043 
00044 /* ============================= */
00045 /* -- Global/Static Variables -- */
00046 /* ============================= */
00047 
00048 FILE            *file_stats;
00049 
00050 
00051 
00052 /* ========================= */
00053 /* -- Function Prototypes -- */
00054 /* ========================= */
00055 
00056 static void initialize();
00057 static void process_band(band_t band);
00058 
00059 
00060 
00061 /* ============================== */
00062 /* -- Function Implementations -- */
00063 /* ============================== */
00064 
00068 static void usage(const char *program_name)
00069 {
00070     fprintf(stderr,
00071                 "USAGE: %s <EDI path> <Unshingled path> <Output path>\n",
00072                 program_name);
00073     abort();
00074 }
00075 
00076 
00077 
00090 static void process_args(int *argc, char *argv[]) {
00091         int i, arg_error = 0;
00092 
00093 
00094         /* Ensure that the arguments are available */
00095         if (*argc < ARG_COUNT_MIN)
00096                 usage(argv[0]);
00097 
00098 
00099         /* Strip out any terminating /'s in the path to the directories */
00100         i = strlen(argv[ARG_PATH_USHNG]) - 1;
00101         if (argv[ARG_PATH_USHNG][i] == '/')
00102                 argv[ARG_PATH_USHNG][i] = '\0';
00103 
00104 
00105         /* Validate the path to the Emulated Disk Image */
00106         if (!is_valid_file(argv[ARG_PATH_EDI])) {
00107                 arg_error = 1;
00108                 fprintf(stderr, "%s is not a valid file!\n", argv[ARG_PATH_EDI]);
00109         }
00110 
00111         /* Validate the path to the Unshingled partition */
00112         if (!is_valid_dir(argv[ARG_PATH_USHNG])) {
00113                 arg_error = 1;
00114                 fprintf(stderr, "%s is not a valid directory!\n", argv[ARG_PATH_USHNG]);
00115         }
00116 
00117 
00118         /* Check if there are any errors */
00119         if (arg_error)
00120                 usage(argv[0]);
00121 
00122 
00123         /* Store the arguments */
00124         strcpy(SFSDATA.path_edi, argv[ARG_PATH_EDI]);
00125         strcpy(SFSDATA.path_unshingled, argv[ARG_PATH_USHNG]);
00126         strcpy(SFSDATA.path_tmpfs, argv[ARG_PATH_OUTPUT]);
00127         dbg("EDI path: %s\n", SFSDATA.path_edi);
00128         dbg("Unshingled path: %s\n", SFSDATA.path_unshingled);
00129         dbg("Output path: %s\n", SFSDATA.path_tmpfs);
00130 }
00131 
00132 
00133 
00140 static void initialize() {
00141         /* Load the Emulated Disk Image */
00142         if (edi_init()) {
00143                 fprintf(stderr, "Error initializing Emulator interface!\n");
00144                 exit(EXIT_FAILURE);
00145         }
00146 
00147         if ((SFSDATA.fd_edi = edi_open(SFSDATA.path_edi)) < 0) {
00148                 fprintf(stderr, "edi_open(%s): %s!\n", SFSDATA.path_edi, strerror(errno));
00149                 exit(EXIT_FAILURE);
00150         }
00151 
00152         /* Open the output file */
00153         if ((file_stats = fopen(SFSDATA.path_tmpfs, "w+")) == NULL) {
00154                 fprintf(stderr, "fopen(%s): %s\n", SFSDATA.path_tmpfs, strerror(errno));
00155                 exit(EXIT_FAILURE);
00156         }
00157 
00158 
00159         /* Read the EDI Parameters */
00160         read_edi_parameters(SFSDATA.fd_edi, &SFSDATA.edi_blksize,
00161                         &SFSDATA.edi_bandcount, &SFSDATA.edi_bandsize);
00162 
00163         /* Initialize the Band Bitmap */
00164         if (init_band_bitmap() < 0) {
00165                 fprintf(stderr, "Error opening band bitmap!\n");
00166                 exit(EXIT_FAILURE);
00167         }
00168 }
00169 
00170 
00171 
00179 static void process_band(band_t band) {
00180         char error[PATH_MAX];
00181         int i, band_used, fd_append, fd_delete, num_append, num_delete;
00182         rba_t band_ptr = 0, band_live = 0, band_dead = 0;
00183         struct stat statbuf;
00184         int *deleted;
00185     struct delete_entry rec_delete;
00186     struct store_entry rec_append;
00187 
00188 
00189         /* Read the write pointer for the band */
00190         if (edi_managebands(SFSDATA.fd_edi, SVC_GETPTR, &band, &band_ptr, 0)) {
00191                 sprintf(error, "edi_managebands() failed!");
00192                 goto error;
00193         }
00194 
00195         /* Check if the band is free or occupied */
00196         if ((band_used = test_bandusage(band)) < 0) {
00197                 sprintf(error, "test_bandusage() failed!");
00198                 goto error;
00199         }
00200         dbg("Band State: %s\n", band_used ? "Used" : "Free");
00201 
00202 
00203     /* Open the Append Log and the Delete Log for the band */
00204     if ((fd_append = init_storelog(band)) < 0) {
00205         sprintf(error, "Error opening Append Log!");
00206                 goto error;
00207     }
00208 
00209     if ((fd_delete = init_deletelog(band)) < 0) {
00210         sprintf(error, "Error opening Delete Log!");
00211                 goto error;
00212     }
00213 
00214 
00215     /* Generate statistics for the band if it is used */
00216         if (band_used) {
00217             /* Read the no. of append and delete log entries */
00218             fstat(fd_append, &statbuf);
00219             num_append = statbuf.st_size / sizeof(struct store_entry);
00220             dbg("Append Log Entries:%d\n",num_append);
00221 
00222             fstat(fd_delete, &statbuf);
00223             num_delete = statbuf.st_size / sizeof(struct delete_entry);
00224             dbg("Delete Log Entries:%d\n",num_delete);
00225 
00226 
00227             /* Identify deleted append log entries from the delete log */
00228             deleted = calloc(num_append, sizeof(int));
00229             for (i=0; i<num_delete; i++) {
00230                 dbg("Processing Delete Entry %d\n", i);
00231                 pread(fd_delete, &rec_delete, sizeof(struct delete_entry),
00232                                 i * sizeof(struct delete_entry));
00233 
00234                 if (rec_delete.entrynumber > num_append) {
00235                     sprintf(error, "Delete Log entry %d refers to %d of %d Append"
00236                                 "Log entries!", i, rec_delete.entrynumber, num_append);
00237                     goto error;
00238                 }
00239 
00240                 deleted[rec_delete.entrynumber - 1] = 1;
00241                 band_dead += rec_delete.size;
00242             }
00243 
00244 
00245             /* Identify the live data in the band */
00246             for (i=0; i<num_append; i++) {
00247                 if (deleted[i])
00248                         continue;
00249 
00250                 dbg("Processing Append Entry %d\n", i);
00251                 pread(fd_append, &rec_append, sizeof(struct store_entry),
00252                                 i * sizeof(struct store_entry));
00253 
00254                 band_live += rec_append.size;
00255             }
00256         }
00257 
00258 
00259         /* Close the open files */
00260         close(fd_append);
00261         close(fd_delete);
00262 
00263 
00264         /* Write the band statistics to the output file */
00265         fprintf(file_stats, "Band %3d\t%s\t%8d\t%8d\t%8d\t%8d\n",
00266                         band, (band_used ? "Used" : "Free"), SFSDATA.edi_bandsize,
00267                         band_ptr, band_live, band_dead);
00268 
00269         return;
00270 
00271 error:
00272         fprintf(file_stats, "Band %3d: %s\n", band, error);
00273 }
00274 
00275 
00276 
00277 /* =================== */
00278 /* -- Main Function -- */
00279 /* =================== */
00280 
00281 int main(int argc, char *argv[]) {
00282         int i;
00283         time_t curtime = time(NULL);
00284 
00285 
00286     /* Process the arguments */
00287     process_args(&argc, argv);
00288 
00289     /* Initialize the program */
00290     initialize();
00291 
00292 
00293     /* Output the basic EDI parameters */
00294     fprintf(file_stats, "EDI Image: %s\n", SFSDATA.path_edi);
00295     fprintf(file_stats, "Unshingled Partition: %s\n", SFSDATA.path_unshingled);
00296     fprintf(file_stats, "Report Time: %s\n", ctime(&curtime));
00297     fprintf(file_stats, "Sector Size: %d bytes\n", SFSDATA.edi_blksize);
00298     fprintf(file_stats, "Bands: %d bytes\n", SFSDATA.edi_bandcount);
00299     fprintf(file_stats, "Band Size: %d blocks (%d bytes)\n",
00300                 SFSDATA.edi_bandsize, SFSDATA.edi_bandsize * SFSDATA.edi_blksize);
00301 
00302 
00303     /* Iterate over the bands in the EDI */
00304         fprintf(file_stats, "Band No.\tState\tBand Size\tCursor Position\t"
00305                         "Live Blocks\tDead Blocks\n");
00306     for (i=1; i<SFSDATA.edi_bandcount; i++) {
00307         dbg("Processing band %d\n", i);
00308         process_band(i);
00309     }
00310 
00311 
00312     /* Close the output file */
00313     fclose(file_stats);
00314     return (EXIT_SUCCESS);
00315 }