|
| 1 | +/* here's a simple utility to read the logfs .logfs and .meta files. These |
| 2 | + * structures are all internal to logfs and defined in ad_logfs/logfs.c, so if |
| 3 | + * they are modified there, one will have to manually update the structures |
| 4 | + * here. |
| 5 | + * |
| 6 | + * if while reading the file you get an assertion (see the 'UNKNOWN RECORD TYPE |
| 7 | + * IN LOG ' comment below), that might be because the log file was generatd |
| 8 | + * with (or without) magic guards */ |
| 9 | + |
| 10 | +#include <sys/types.h> |
| 11 | +#include <sys/stat.h> |
| 12 | +#include <fcntl.h> |
| 13 | + |
| 14 | +#include <unistd.h> |
| 15 | + |
| 16 | +#include <stdlib.h> |
| 17 | + |
| 18 | +#include <stdio.h> |
| 19 | + |
| 20 | +#include <assert.h> |
| 21 | +typedef struct |
| 22 | +{ |
| 23 | + char magic[64]; /* file magic */ |
| 24 | + int flags; |
| 25 | + int logfilecount; /* max. number of lock files possibly created for |
| 26 | + this file (acros reopens) (== number of CPUs |
| 27 | + used in open/create) */ |
| 28 | + int epoch; /* next epoch number (used in reopen) */ |
| 29 | + char logfilebase[255]; /* base filename for logfiles */ |
| 30 | +} logfs_logfsfile_header; |
| 31 | + |
| 32 | +/* from logfs_file.c */ |
| 33 | +/* ======================================================================= */ |
| 34 | +/* ============= LOGFS_FILE RECORDTYPE =================================== */ |
| 35 | +/* ======================================================================= */ |
| 36 | + |
| 37 | +/* |
| 38 | + * The displacement and datatype follow the record header |
| 39 | + */ |
| 40 | +#define LOGFS_FILE_RECORD_VIEW 1 |
| 41 | + |
| 42 | +/* |
| 43 | + * After this header kind: |
| 44 | + * - seek position (in etypes) |
| 45 | + * - datasize (in bytes) |
| 46 | + * |
| 47 | + * The datasize (in bytes) followed by the |
| 48 | + * actual data |
| 49 | + */ |
| 50 | +#define LOGFS_FILE_RECORD_DATA 2 |
| 51 | + |
| 52 | +/* |
| 53 | + * Followed by the epoch number |
| 54 | + */ |
| 55 | +#define LOGFS_FILE_RECORD_SYNC 3 |
| 56 | + |
| 57 | +/* |
| 58 | + * followed by filesize (MPI_Offset) |
| 59 | + */ |
| 60 | +#define LOGFS_FILE_RECORD_SETSIZE 4 |
| 61 | + |
| 62 | +/* used for debugging; If enabled, magicstart and magicstop will |
| 63 | + * be written before and after the recordheader */ |
| 64 | +//#define LOGFS_FILE_RECORDMAGIC |
| 65 | + |
| 66 | +#define LOGFS_FILE_RECORDMAGIC_START "[magicstart] " |
| 67 | +#define LOGFS_FILE_RECORDMAGIC_STOP "[magicstop ] " |
| 68 | + |
| 69 | + |
| 70 | +/* Record struct for in the logfs metalog */ |
| 71 | +typedef struct |
| 72 | +{ |
| 73 | +#ifdef LOGFS_FILE_RECORDMAGIC |
| 74 | + char magic_start[16]; |
| 75 | +#endif |
| 76 | + int recordtype; |
| 77 | + double timestamp; |
| 78 | +#ifdef LOGFS_FILE_RECORDMAGIC |
| 79 | + char magic_stop[16]; |
| 80 | +#endif |
| 81 | +} logfs_file_recordstruct; |
| 82 | + |
| 83 | + |
| 84 | +/* Header that goes at the beginning of both metadata and datafiles */ |
| 85 | +typedef struct |
| 86 | +{ |
| 87 | + char magic[64]; |
| 88 | + /* don't store epoch here; otherwise we need an alreduce when we lazily |
| 89 | + * open the logfile to inform other CPUs of the highest epoch number */ |
| 90 | + /*int epoch; */ /* epoch number of last epoch in file */ |
| 91 | +} logfs_file_headerstruct; |
| 92 | + |
| 93 | + |
| 94 | + |
| 95 | +char * logfs_flags_to_string(int flags) |
| 96 | +{ |
| 97 | + if (flags == 2) return "REPLAY"; |
| 98 | + if (flags == 3) return "ACTIVE"; |
| 99 | + return NULL; |
| 100 | +} |
| 101 | +void dump_logfs(char *filename) |
| 102 | +{ |
| 103 | + int fd, ret; |
| 104 | + logfs_logfsfile_header h; |
| 105 | + |
| 106 | + fd = open(filename, O_RDONLY); |
| 107 | + ret = read(fd, &h, sizeof(h)); |
| 108 | + printf("magic: %s flags %s count %d epoch %d base |%s|\n", |
| 109 | + h.magic, logfs_flags_to_string(h.flags), |
| 110 | + h.logfilecount, h.epoch, h.logfilebase); |
| 111 | + |
| 112 | +} |
| 113 | + |
| 114 | +void extract_typemap(char *prefix, int fd, FILE *output) |
| 115 | +{ |
| 116 | + int64_t count; |
| 117 | + int64_t *indices; |
| 118 | + int64_t *blocklens; |
| 119 | + int ret, i; |
| 120 | + ret = read(fd, &count, sizeof(count)); |
| 121 | + indices = malloc(count*sizeof(*indices)); |
| 122 | + blocklens = malloc(count*sizeof(*blocklens)); |
| 123 | + ret = read(fd, indices, count*sizeof(*indices)); |
| 124 | + ret = read(fd, blocklens, count*sizeof(*blocklens)); |
| 125 | + fprintf(output, "%s ", prefix); |
| 126 | + for (i=0; i<count; i++) { |
| 127 | + fprintf(output, "(%ld %ld) ", indices[i], blocklens[i]); |
| 128 | + } |
| 129 | + free(indices); |
| 130 | + free(blocklens); |
| 131 | +} |
| 132 | + |
| 133 | +void dump_logfs_view(int fd_in, FILE *output) |
| 134 | +{ |
| 135 | + int ret; |
| 136 | + int64_t displacement; |
| 137 | + ret = read(fd_in, &displacement, sizeof(displacement)); |
| 138 | + fprintf(output, "\ndisplacement: %ld ", displacement); |
| 139 | + extract_typemap("etype:", fd_in, output); |
| 140 | + extract_typemap("ftype:", fd_in, output); |
| 141 | +} |
| 142 | + |
| 143 | +void dump_logfs_meta_data(int fd_in, FILE *output) |
| 144 | +{ |
| 145 | + int ret, size; |
| 146 | + int64_t fileofs, datalogofs; |
| 147 | + ret = read(fd_in, &size, sizeof(size)); |
| 148 | + ret = read(fd_in, &fileofs, sizeof(fileofs)); |
| 149 | + ret = read(fd_in, &datalogofs, sizeof(datalogofs)); |
| 150 | + fprintf(output, "\nsize: %d fileofs: %ld datalogofs: %ld\n", |
| 151 | + size, fileofs, datalogofs); |
| 152 | +} |
| 153 | + |
| 154 | +void dump_logfs_meta(char *filename, FILE * output) |
| 155 | +{ |
| 156 | + int fd, ret, epoch; |
| 157 | + logfs_file_recordstruct record; |
| 158 | + logfs_file_headerstruct h; |
| 159 | + fd = open(filename, O_RDONLY); |
| 160 | + /* read header, but mostly to just skip over it */ |
| 161 | + ret = read(fd, &h, sizeof(h)); |
| 162 | + |
| 163 | + |
| 164 | + while(1) { |
| 165 | + ret = read(fd, &record, sizeof(record)); |
| 166 | + if (ret <= 0) break; |
| 167 | + |
| 168 | + switch (record.recordtype) { |
| 169 | + case LOGFS_FILE_RECORD_VIEW: |
| 170 | + dump_logfs_view(fd, output); |
| 171 | + break; |
| 172 | + |
| 173 | + case LOGFS_FILE_RECORD_DATA: |
| 174 | + dump_logfs_meta_data(fd, output); |
| 175 | + break; |
| 176 | + case LOGFS_FILE_RECORD_SYNC: |
| 177 | + ret = read(fd, &epoch, sizeof(epoch)); |
| 178 | + fprintf(output, "\nsync-epoch: %d ", epoch); |
| 179 | + break; |
| 180 | + |
| 181 | + default: |
| 182 | + printf("found record type %d\n", record.recordtype); |
| 183 | + assert (0 /* UNKNOWN RECORD TYPE IN LOG */); |
| 184 | + } |
| 185 | + } |
| 186 | + |
| 187 | +} |
| 188 | +void dump_logfs_data(char *filename) |
| 189 | +{ |
| 190 | +} |
| 191 | + |
| 192 | +int main(int argc, char **argv) |
| 193 | +{ |
| 194 | + int c; |
| 195 | + while ((c = getopt(argc, argv, "l:m:d:")) != -1) { |
| 196 | + switch (c) { |
| 197 | + case 'l': |
| 198 | + dump_logfs(optarg); |
| 199 | + break; |
| 200 | + case 'm': |
| 201 | + dump_logfs_meta(optarg, stdout); |
| 202 | + break; |
| 203 | + case 'd': |
| 204 | + dump_logfs_data(optarg); |
| 205 | + break; |
| 206 | + default: |
| 207 | + printf("unknown argument\n"); |
| 208 | + } |
| 209 | + } |
| 210 | +} |
0 commit comments