Add proper per-file copyright notices/licenses and top-level license.
[bluesky.git] / TBBT / trace_play / rfs_c_age.c.trace_base
1 #include <sys/vfs.h>
2 #include <sys/stat.h>
3 #include <fcntl.h>
4 #include <errno.h>
5 #include <stdio.h>
6 #include "rfs_assert.h"
7 #include "profile.h"
8 #define MKDIR 1
9 #define RMDIR 2
10 #define CREATE 3
11 #define REMOVE 4
12 #define WRITE 5
13 #define TRUNCATE 6
14
15 #define MAX_FILES 100000
16 #define MAX_DIRS  100000
17 #define FILE_FH_HTABLE_SIZE MAX_FILES
18 #define MAX_NAMELEN 256
19 #define MAX_PLAY_PATH_SIZE 256
20 #define MAX_COMMAND_LEN (MAX_PLAY_PATH_SIZE+16)
21 #define NFS_MAXDATA 32768
22 #define TRACE_FH_SIZE 64
23
24 #define FH_T_FLAG_FREE 0
25 #define FH_T_FLAG_IN_USE 1
26 #define IS_FILE 0
27 #define IS_DIR 1
28 #define NOT_EXIST 0
29 #define EXIST 1
30
31 typedef struct {
32     char flag;
33     //char trace_fh [TRACE_FH_SIZE+1];
34     char path[MAX_PLAY_PATH_SIZE];
35 } fh_t;
36
37 typedef struct {
38         char name[32];
39         fh_t * fh;
40         //struct generic_entry * htable;
41         int fh_size;
42         int fh_max;
43         int index;
44         //int htable_size;
45 } fh_info_t;
46
47 fh_info_t file_fh, dir_fh;
48 profile_t read_line_profile, fgets_profile;
49 char trace_file[MAX_NAMELEN];
50 FILE * profile_fp = NULL;
51 char testdir[MAX_NAMELEN];
52
53 int age_create_num = 0;
54 int age_mkdir_num = 0;
55 int assure_create_num = 0;
56 int assure_mkdir_num = 0;
57 int age_write_num = 0;
58 int nonage_write_num = 0;
59 int overlap_write_num = 0;
60
61 int init_profile_variables()
62 {
63         init_profile ("read_line profile", &read_line_profile);
64         init_profile ("fgets profile", &fgets_profile);
65 }
66
67 int init_fh_info (char * name, fh_info_t * fh_infop, int fh_size, int htable_size)
68 {
69         RFS_ASSERT (strlen(name) < sizeof(fh_infop->name));
70         strcpy (fh_infop->name, name);
71         fh_infop->fh_max = 0;
72         fh_infop->index = 0;
73         fh_infop->fh_size = fh_size;
74         //fh_infop->htable_size = htable_size;
75         fh_infop->fh = (fh_t *)malloc (sizeof(fh_t)*fh_size);
76         RFS_ASSERT (fh_infop->fh);
77         //fh_infop->htable = malloc (sizeof(struct*generic_entry)*htable_size);
78         //RFS_ASSERT (fh_infop->htable);
79         printf("initialize %s size %d bytes\n", 
80                 //name, sizeof(fh_t)*fh_size + sizeof(struct*generic_entry)*htable_size);
81                 name, sizeof(fh_t)*fh_size);
82 }
83
84 int init()
85 {
86         init_fh_info ("file_fh", &file_fh, MAX_FILES, MAX_FILES);
87         init_fh_info ("dir_fh", &dir_fh, MAX_DIRS, MAX_DIRS);
88 }
89
90 int add_fh_t (fh_info_t * fh_table, char * path, int exist_flag)
91 {
92         int i;
93
94         for (i=0; i<fh_table->fh_size; i++,fh_table->index++) {
95                 if (fh_table->index==fh_table->fh_size)
96                         fh_table->index = 0;
97                 if (fh_table->fh[fh_table->index].flag == FH_T_FLAG_FREE) {
98                         fh_table->fh[fh_table->index].flag = FH_T_FLAG_IN_USE;
99                         //RFS_ASSERT(strlen(path)<MAX_PLAY_PATH_SIZE);
100                         strcpy (fh_table->fh[fh_table->index].path, path);
101                         if (fh_table->index > fh_table->fh_max)
102                                 fh_table->fh_max = fh_table->index;
103                         return 0;
104                 }
105         }
106         //print_fh_map(fh_table);
107         RFS_ASSERT (0);
108 }
109
110 int create_mkdir_op (int flag)
111 {
112         static int fhno = 0;
113         char name[MAX_NAMELEN];
114         char command[MAX_COMMAND_LEN];
115         int i;
116         int fd;
117         int count = 0;
118         fh_info_t * fh_infop;
119
120         while (count++ < 100) {
121                 i = random()%dir_fh.fh_max;
122                 if (dir_fh.fh[i].flag==FH_T_FLAG_IN_USE) {
123                         assure_exist(dir_fh.fh[i].path);
124                         strcpy (name, dir_fh.fh[i].path);
125                         if (flag == IS_FILE) {
126                                 sprintf (name+strlen(name), "AGEfile%d", fhno++);
127                                 fd = creat (name, S_IRWXU);
128                                 age_create_num++;
129                                 //printf ("create fd %d\n", fd);
130                                 close(fd);
131                                 fh_infop = &file_fh;
132                         } else {
133                                 sprintf (name+strlen(name), "AGEdir%d", fhno++);
134                                 fd = mkdir (name, S_IRWXU);
135                                 age_mkdir_num++;
136                                 fh_infop = &dir_fh;
137                         }
138                         if (fd == -1) {
139                                 perror("");
140                                 if (errno == ENOENT) {
141                                         dir_fh.fh[i].flag = FH_T_FLAG_FREE;
142                                         continue;
143                                 } else
144                                         RFS_ASSERT (0);
145                         }
146                         add_fh_t (fh_infop, name, EXIST);
147                         RFS_ASSERT (fd >=0);
148                         return 0;
149                 }
150         };
151         return -1;
152 }
153
154 int remove_op ()
155 {
156         int i;
157         int count = 0;
158         int ret;
159
160         while (count++<100) {
161                 i = random()%file_fh.fh_max;
162                 if (file_fh.fh[i].flag == FH_T_FLAG_IN_USE) {
163 /*
164                         if (!strstr(file_fh.fh[i].path, "AGE"))
165                                 continue;
166 */
167                         assure_exist(file_fh.fh[i].path);
168                         ret = remove (file_fh.fh[i].path);
169                         RFS_ASSERT (ret ==0);
170                         file_fh.fh[i].flag = FH_T_FLAG_FREE;
171                         return 0;
172                 }
173         }
174         return -1;
175 }
176
177 int rmdir_op()
178 {
179         int i;
180         int count=0;
181         char command[MAX_COMMAND_LEN];
182         int ret;
183
184         while (count++<100) {
185                 i = random()%dir_fh.fh_max;
186                 if ( (dir_fh.fh[i].flag == FH_T_FLAG_IN_USE) ) {
187 /*
188                         if (!strstr(file_fh.fh[i].path, "AGE"))
189                                 continue;
190 */
191                         assure_exist(file_fh.fh[i].path);
192                         ret = rmdir (dir_fh.fh[i].path);
193                         if (ret == 0) {
194                                 dir_fh.fh[i].flag = FH_T_FLAG_FREE;
195                                 return 0;
196                         }
197                         RFS_ASSERT ((ret == -1) && (errno == ENOTEMPTY));
198                         //strcpy (command, "rm -r %s", dir_fh.fh[i].path);
199                         //system (command);
200                 }
201         }
202         return -1;
203 }
204
205 int loop_write (int fd, char * buf, int buflen)
206 {
207     int ret;
208     int pos = 0;
209
210     while (1) {
211         ret = write (fd, buf+pos, buflen-pos);
212
213         if (ret == -1) {
214             perror ("loop write");
215             exit (-1);
216         }
217         if (ret == buflen-pos)
218             break;
219         pos += ret;
220     }
221     return 0;
222 }
223
224 int assure_exist(char * path)
225 {
226         char name[MAX_NAMELEN];
227         int ret;
228         char *p, *q;
229         int non_exist_flag = 0;
230         int count=0;
231         struct stat st;
232
233         ret = stat (path, &st);
234         if (ret == 0)
235                 return 0;
236         RFS_ASSERT (errno == ENOENT);
237         
238         RFS_ASSERT (!strstr (path, "AGE"));
239         p = path;
240         q = name;
241         while (count++<100) {
242                 for (; *p!=0 && *p!='/'; p++, q++ ) 
243                         *q = *p;
244                 *q = 0;
245                 ret = stat (name, &st);
246                 if (ret == -1) {
247                         RFS_ASSERT (errno == ENOENT)
248                         if ((*p)==0) {
249                                 ret = creat (name, S_IRWXU);
250                                 assure_create_num ++;
251                                 RFS_ASSERT (ret >=0);
252                                 close(ret);
253                         } else {
254                                 ret = mkdir (name, S_IRWXU);
255                                 assure_mkdir_num ++;
256                                 RFS_ASSERT (ret >=0);
257                         }
258                 }
259                 if ((*p)=='/') {
260                         *q = '/';
261                         p++; q++;
262                 } else {
263                         RFS_ASSERT ((*p)==0)
264                         return 0;
265                 }
266         }
267         RFS_ASSERT (0);
268 }
269
270 int write_op (int off, int size)
271 {
272         static char buf[NFS_MAXDATA];
273         int i;
274         int count=0;
275         int fd;
276         int ret;
277         struct stat st;
278
279         RFS_ASSERT (size <= NFS_MAXDATA);
280         while (count++<100) {
281                 i = random()%file_fh.fh_max;
282                 if ( (file_fh.fh[i].flag == FH_T_FLAG_IN_USE) ) {
283                         assure_exist(file_fh.fh[i].path);
284                         fd = open(file_fh.fh[i].path, O_WRONLY);
285                         if (fd == -1)
286                                 perror("");
287                         //else 
288                                 //printf ("write fd %d\n", fd);
289                         RFS_ASSERT (fd!=-1);
290                         fstat (fd, &st);
291                         if (st.st_size < (off+size)) {
292                                 int written_bytes = 0;
293                                 while (written_bytes+NFS_MAXDATA < off+size-st.st_size) {
294                                         loop_write (fd, buf, NFS_MAXDATA);
295                                         written_bytes += NFS_MAXDATA;
296                                 }
297                                 loop_write (fd, buf, off+size-st.st_size-written_bytes);
298                                 if (strstr(file_fh.fh[i].path, "AGE")) {
299                                         age_write_num+=(written_bytes+NFS_MAXDATA-1)/NFS_MAXDATA;
300                                 } else 
301                                         nonage_write_num+=(written_bytes+NFS_MAXDATA-1)/NFS_MAXDATA;
302                         } else
303                                 overlap_write_num++;
304 /*
305                         if (strstr(file_fh.fh[i].path, "AGE")) {
306                                 age_write_num++;
307                         } else 
308                                 nonage_write_num++;
309                         loop_write (fd, buf, size);
310 */
311                         close(fd);
312                         return 0;
313                 };
314         }
315         return -1;
316 }
317
318 int truncate_op(int size)
319 {
320         int i;
321         int count=0;
322         int ret;
323
324         while (count++<100) {
325                 i = random()%file_fh.fh_max;
326                 if ( (file_fh.fh[i].flag == FH_T_FLAG_IN_USE) ) {
327 /*
328                         if (!strstr(file_fh.fh[i].path, "AGE"))
329                                 continue;
330 */
331                         assure_exist (file_fh.fh[i].path);
332                         ret = truncate(file_fh.fh[i].path, size);
333                         if (ret ==0) 
334                                 return 0;
335                         RFS_ASSERT (errno == ENOENT);
336                         file_fh.fh[i].flag = FH_T_FLAG_FREE;
337                         continue;       
338                 }
339         };
340         return -1;
341 }
342
343 int print_fh_map(fh_info_t * fhp)
344 {
345         int i;
346         int num = 0;
347         for (i=0; i<fhp->fh_max; i++) {
348                 if (fhp->fh[i].flag == FH_T_FLAG_IN_USE) {
349                         num ++;
350                         printf("%s[%d] %s\n", fhp->name, i, fhp->fh[i].path);
351                 }
352         }
353         fprintf(stderr, "fh_max %d total %d entries \n", fhp->fh_max, num);
354 }
355
356 void read_fh_map(char * fh_map_file)
357 {
358         FILE * fp;
359         int i = 0;
360         char buf[1024];
361         char trace_fh[TRACE_FH_SIZE];
362         char intbuf[9];
363         char * trace_path;
364         char * p;
365         int map_flag;
366         int lineno = 0;
367         int fh_map_debug =0;
368         char name[MAX_NAMELEN];
369
370         fp = fopen(fh_map_file, "r");
371         if (!fp) {
372                 printf ("can not opern %s\n", fh_map_file);
373                 perror("open");
374                 exit (0);
375         }
376         RFS_ASSERT (fp!=NULL);
377         
378         intbuf[8]=0;
379
380         memset(buf, 0, sizeof(buf));
381         while (fgets(buf, 1024, fp)) {
382                 RFS_ASSERT (fh_map_debug==0);
383                 lineno ++;
384                 if (lineno % 10000==0)
385                         printf("%d fh_map entry read\n", lineno);
386
387                 RFS_ASSERT (buf[strlen(buf)-1]=='\n');
388                 buf[strlen(buf)-1]=0;
389
390                 trace_path = buf + TRACE_FH_SIZE +1;
391
392                 strcpy (name, testdir);
393                 strcat (name, trace_path);
394                 if ((*(buf+strlen(buf)-1))=='/') {
395                         *(buf+strlen(buf)-1)=0;
396                         add_fh_t (&dir_fh, name, NOT_EXIST);
397                 } else {
398                         add_fh_t (&file_fh, name, NOT_EXIST);
399                 }
400         }
401                         
402         fclose(fp);
403         if (fh_map_debug) {
404                 print_fh_map (&file_fh);
405                 print_fh_map (&dir_fh);
406         }
407 }
408
409 int print_usage()
410 {
411         printf("age trace_file fh_path_map testdir\n");
412 }
413
414 inline char * read_line (int disk_index)
415 {
416         static FILE * fp=NULL;
417         static int start=0;
418         static int start_disk_index=0;
419         int i;
420         static int finish_flag = 0;
421
422 #define READ_LINE_BUF_SIZE 1000
423 #define READ_LINE_LENGTH 32
424
425         static char line_buf[READ_LINE_BUF_SIZE][READ_LINE_LENGTH];
426         start_profile (&read_line_profile);
427
428         if (fp==NULL) {
429                 if (strcmp(trace_file, "stdin")) {
430                         fp = fopen(trace_file, "r");
431                         if (!fp) {
432                                 printf("can not open files %s\n", fp);
433                                 perror("open");
434                         }
435                 } else {
436                         fp = stdin;
437                 }
438                 RFS_ASSERT (fp!=NULL);
439                 for (i=0; i<READ_LINE_BUF_SIZE; i++) {
440                         start_profile(&fgets_profile);
441                         if (!fgets(line_buf[i], READ_LINE_LENGTH, fp)) {
442                                 RFS_ASSERT (0);
443                         }
444                         end_profile(&fgets_profile);
445                         //printf ("read_line, line_buf[%d]:%s", i, line_buf[i]);
446                 }
447         }
448         
449         RFS_ASSERT (disk_index <= start_disk_index+READ_LINE_BUF_SIZE)
450         if (disk_index==(start_disk_index+READ_LINE_BUF_SIZE)) {
451                 if (finish_flag) {
452                         return NULL;
453                 }
454                 start_profile(&fgets_profile);
455                 if (!fgets(line_buf[start], READ_LINE_LENGTH, fp)) {
456                         end_profile(&fgets_profile);
457                         fclose(fp);
458                         finish_flag = 1;
459                         return NULL;
460                 }
461                 end_profile(&fgets_profile);
462                 //printf ("read_line, line_buf[%d]:%s", start, line_buf[start]);
463                 start = (start+1) % READ_LINE_BUF_SIZE;
464                 start_disk_index ++;
465         }
466         RFS_ASSERT (disk_index < start_disk_index+READ_LINE_BUF_SIZE)
467         i = (start+disk_index-start_disk_index)%READ_LINE_BUF_SIZE;
468
469         end_profile (&read_line_profile);
470         return (line_buf[i]);
471 }
472
473 int f()
474 {};
475
476 int print_result()
477 {
478         struct statfs stfs;
479         int ret;
480         ret = statfs (testdir, &stfs);
481         RFS_ASSERT (ret == 0);
482         fprintf(stderr, "number of files %d size of file system %d\n", stfs.f_files, stfs.f_bfree);
483         fprintf(stderr, "assure_create_num %d assure_mkdir_num %d, age_create_num %d age_mkdir_num %d age_write_num %d nonage_write_num %d overlap_write_num %d\n",
484                         assure_create_num, assure_mkdir_num, age_create_num, age_mkdir_num, age_write_num, nonage_write_num, overlap_write_num);
485         printf("assure_create_num %d assure_mkdir_num %d, age_create_num %d age_mkdir_num %d age_write_num %d nonage_write_num %d overlap_write_num %d\n",
486                         assure_create_num, assure_mkdir_num, age_create_num, age_mkdir_num, age_write_num, nonage_write_num, overlap_write_num);
487 }
488
489 int main(int argc, char ** argv)
490 {
491         char * buf;
492         static int disk_index=0;
493         int j, nfs3proc, size, off, count;
494         char procname[16];
495         struct stat st;
496         int ret;
497
498         if (argc!=4) {
499                 print_usage();
500                 exit(0);
501         }
502
503         init();
504         strcpy (trace_file, argv[1]);
505         strcpy (testdir, argv[3]);
506         ret = stat (testdir, &st);
507         RFS_ASSERT (ret == 0);
508         read_fh_map(argv[2]);
509         init_profile_variables();
510
511         while ((buf=read_line(++disk_index))!=NULL) {
512
513                 memset (procname, 0, sizeof(procname));
514                 //printf ("line[%d] %s", disk_index, buf);
515                 sscanf (&buf[0], "%s", procname);
516                 j = 0;
517                 while ((*(buf+j)!=' ') && (*(buf+j)!='\n'))
518                         j++;
519                 j++;
520                 if (!strcmp(procname, "write"))
521                         sscanf (&buf[j], "off %x count %x", &off, &count);
522
523                 if (!strcmp(procname, "setattr")) 
524                         sscanf (&buf[j], "size %x", &size);
525
526                 if (!strcmp(procname, "write"))
527                         ret = write_op(off, count);
528                 else if (!strcmp(procname, "create")) 
529                         ret = create_mkdir_op(IS_FILE); 
530                 else if (!strcmp(procname, "mkdir")) 
531                         ret = create_mkdir_op(IS_DIR);
532                 else if (!strcmp(procname, "remove")) 
533                         ret = remove_op(); 
534                 else if (!strcmp(procname, "rmdir")) 
535                         ret = rmdir_op();
536                 else if (!strcmp(procname, "setattr")) 
537                         ret = truncate_op(size);
538                 else {
539                         printf("disk_index %d procname %s\n", disk_index, procname);
540                         RFS_ASSERT (0);
541                 }
542                 if (ret!=0) {
543                         printf("execute disk_line[%d] %s error\n", disk_index, buf);
544                 }
545                 if ((disk_index%100)==0) {
546                         fprintf (stderr, "%d disk trace parsed \n", disk_index);
547                         print_result();
548                 }
549         }
550         print_result();
551 }