Import TBBT (NFS trace replay).
[bluesky.git] / TBBT / trace_init / rfs.pl
1 #!/usr/bin/perl -w\r
2 \r
3 use Getopt::Std;\r
4 $Usage =<< "EOF";\r
5 \r
6 Usage: $0 [options]\r
7 \r
8 This program runs after nfsscan.pl. It outputs the file system hierarchy (RFSFS) as well as\r
9 the file system hierarchy map (stored in three files: fh-path-map, noattrdirdiscard, noattrdir-root).\r
10 \r
11 This perl program do post processing based on this file\r
12 \r
13 Command line options:\r
14 \r
15 -h      Print Usage message and exit.\r
16 \r
17 -S  The file in file system hierarchy are all of size 0. \r
18     Without -S, the files are written to it full length.\r
19 \r
20 \r
21 EOF\r
22 \r
23 $writebuf = "R" x 8193;\r
24 $writeBlockSize = 8192;\r
25 \r
26 main ();\r
27 \r
28 sub rfsCreateSymlink()\r
29 {\r
30         my ($path, $pathcnt, $sizeHexStr) = @_;\r
31         $sizeHexStr = "0x".$sizeHexStr;\r
32 \r
33         my $dir = $path;\r
34         my $name = '';\r
35         my $cmdbuf;\r
36 \r
37         $dir =~ /(^.*)\/(.*)/;\r
38         $dir = $1;\r
39         $name = $2;\r
40         if (!$dir) {$dir = ".";}\r
41         die "name is empty\n" if (!$name);\r
42         #print "path($path) dir($dir) name($name)\n";\r
43 \r
44         if (! -e $dir) {\r
45                 $cmdbuf = "mkdir -p $dir";\r
46                 system $cmdbuf;\r
47                 print "RFS: Warning: the directory should be created already: $path\n";\r
48         } else {\r
49                 die "warning: directory name exist but not a directory: $path\n" if (!(-d $dir));\r
50         }\r
51 \r
52         my $size = hex($sizeHexStr);\r
53         #print "size($sizeHexStr) lp($lp) rem($remSize)\n";\r
54 \r
55         my $pathnamebuf = $sizeHexStr;\r
56         symlink ($pathnamebuf, $path);\r
57         #if (! symlink ($pathnamebuf, $path) ) {\r
58         #       print STDERR "JIAWU: WARNING: failed to create symlink: $path -> $pathnamebuf\n";\r
59         #}\r
60 }\r
61 \r
62 \r
63 sub  rfsCreateFile()\r
64 {\r
65         my ($path, $pathcnt, $sizeHexStr) = @_;\r
66         $sizeHexStr = "0x".$sizeHexStr;\r
67 \r
68         my $dir = $path;\r
69         my $name = '';\r
70         my $cmdbuf;\r
71 \r
72         $dir =~ /(^.*)\/(.*)/;\r
73         $dir = $1;\r
74         $name = $2;\r
75         if (!$dir) {$dir = ".";}\r
76         die "name is empty\n" if (!$name);\r
77         #print "path($path) dir($dir) name($name)\n";\r
78 \r
79         if (! -e $dir) {\r
80                 $cmdbuf = "mkdir -p $dir";\r
81                 system $cmdbuf;\r
82                 print "RFS: Warning: the directory should be created already: $path\n";\r
83         } else {\r
84                 die "warning: directory name exist but not a directory: $path\n" if (!(-d $dir));\r
85         }\r
86 \r
87         my $size = hex($sizeHexStr);\r
88         my $remSize = $size % $writeBlockSize;\r
89         my $lp = ($size - $remSize) / $writeBlockSize;\r
90         #print "size($sizeHexStr) lp($lp) rem($remSize)\n";\r
91 \r
92         open RFSTMPWRITE, ">$path" || die "RFS: can not open file for write";\r
93 \r
94         # the eight lines below should not be commented out \r
95                 if (!defined $opt_S) {\r
96         my $i = 0;\r
97         for ($i = 0; $i < $lp; $i++) {\r
98                 syswrite(RFSTMPWRITE, $writebuf, $writeBlockSize);\r
99         }\r
100         if ($remSize) {\r
101                 syswrite(RFSTMPWRITE, $writebuf, $remSize);\r
102                 #print "write ($remSize) byte\n";\r
103         }\r
104         close RFSTMPWRITE;\r
105                 }\r
106 }\r
107 \r
108 # Useful commands:\r
109 # sort -n -k a,b -c -u \r
110\r
111 # *** WARNING *** The locale specified by the  environment  affects  sort\r
112 #      order.  Set LC_ALL=C or LC_ALL=POSIX to get the traditional sort order that uses native\r
113 #      byte values.\r
114 \r
115 sub parseArgs {\r
116         my $Options = "S";\r
117         if (! getopts($Options)) {\r
118                 print STDERR "$0: Incorrect usage.\n";\r
119         print STDERR $Usage;\r
120                 exit (1);\r
121         }\r
122 }\r
123 \r
124 sub main {\r
125 \r
126         parseArgs ();\r
127 \r
128         my $cmdbuf;\r
129 \r
130         # format of lines in test.fil:\r
131         # "F(1) $type(2) $state(3) $fh(4) $path(5) $pathcnt(6) $attrOrig(7-14) $attr()\r
132         # attrOrig: ($size(7) $mode(8) $op(9) $atime(10) $mtime(11) $ctime(12) $nlink(13) $ts(14))\r
133         # attrLast: ($size(15) $mode(16) $op(17) $atime(18) $mtime(19) $ctime(20) $nlink(21) $ts(22))\r
134 \r
135         # skip comment lines\r
136         # if (path_count ($6) == 0 or original_op($9) == "create" or "mkdir" or "symlink") skip the file \r
137 \r
138         $cmdbuf = 'gawk \' !/^[#]/ { if ($6 != "0") print $0 }\'  test.fil > all.fil';\r
139         print "$cmdbuf\n";\r
140         system $cmdbuf;\r
141         \r
142         # sort the test.fil according to path name\r
143         $cmdbuf = 'export LC_ALL=C; sort -k 5,5 all.fil > all.fil.order; echo $LC_ALL';\r
144         print "$cmdbuf\n";\r
145         system $cmdbuf;\r
146 \r
147         # keep the interested field only\r
148         # 2(D/F) 4(FH) 5(path) 6(count) 15(size_last) 21(nlink_last) 14(ts_s) 22(ts_e)\r
149         $cmdbuf = 'gawk \' { print $14, $22, $4, $5, $15, $21}\'  all.fil.order > fh-path-map-all';\r
150         print "$cmdbuf\n";\r
151         system $cmdbuf;\r
152         \r
153         # skip comment lines\r
154         # if (path_count ($6) == 0 or original_op($9) == "create" or "mkdir" or "symlink") skip the file \r
155 \r
156         $cmdbuf = 'gawk \' !/^[#]/ { if ($6 != "0" && $9 != "create" && $9 != "mkdir" && $9 != "symlink") print $0 }\'  test.fil > active.fil';\r
157         print "$cmdbuf\n";\r
158         system $cmdbuf;\r
159         \r
160         # sort the active.fil according to path name\r
161         $cmdbuf = 'export LC_ALL=C; sort -k 5,5 active.fil > active.fil.order; echo $LC_ALL';\r
162         print "$cmdbuf\n";\r
163         system $cmdbuf;\r
164 \r
165         # keep the interested field only\r
166         # 2(D/F) 4(FH) 5(path) 6(count) 7(size) 8(mode) 13(nlink)\r
167         $cmdbuf = 'gawk \' { print $2, $4, $5, $6, $7, $8 }\'  active.fil.order > active';\r
168         print "$cmdbuf\n";\r
169         system $cmdbuf;\r
170         $cmdbuf = 'gawk \' { print $4, $5, $7, $13}\'  active.fil.order > fh-path-map';\r
171         print "$cmdbuf\n";\r
172         system $cmdbuf;\r
173 \r
174         # format output files\r
175         $cmdbuf = 'export LC_ALL=C; mv noattrdirdiscard noattrdirdiscard-tmp; sort -u -k 1,1 noattrdirdiscard-tmp > noattrdirdiscard; echo $LC_ALL; rm -f noattrdirdiscard-tmp';\r
176         print "$cmdbuf\n";\r
177         system $cmdbuf;\r
178 \r
179         $cmdbuf = 'export LC_ALL=C; mv noattrdir-root noattrdir-root-tmp; sort -u -k 1,1 noattrdir-root-tmp > noattrdir-root; echo $LC_ALL; rm -f noattrdir-root-tmp';\r
180         print "$cmdbuf\n";\r
181         system $cmdbuf;\r
182 \r
183         #$cmdbuf = 'mv noattrdirdiscard noattrdirdiscard-tmp; cat  noattrdirdiscard-tmp missdiscardfh >noattrdirdiscard; rm -f noattrdirdiscard-tmp missdiscardfh';\r
184         $cmdbuf = 'mv noattrdirdiscard noattrdirdiscard-tmp; cat  noattrdirdiscard-tmp missdiscardfh >noattrdirdiscard; rm -f noattrdirdiscard-tmp';\r
185         print "$cmdbuf\n";\r
186         system $cmdbuf;\r
187 \r
188         $cmdbuf = "cut -d ' ' -f '1 2' fh-path-map > fh-path-map-tmp";\r
189         print "$cmdbuf\n";\r
190         system $cmdbuf;\r
191 \r
192         $cmdbuf = 'cat noattrdirdiscard noattrdir-root fh-path-map-tmp > fh-path-map-play; rm -rf fh-path-map-tmp';\r
193         print "$cmdbuf\n";\r
194         system $cmdbuf;\r
195         \r
196         #exit(0);\r
197         \r
198         # so far, you got the following information\r
199         # in active: all files/dirs active \r
200         # in noattrdir-root: a set of fhs pointing to RFSNN0\r
201         # in rfsinfo: a set of dir fhs refer to RFSNNxxx(>0)\r
202         #                a set of file fhs should be discard due to short of information\r
203 \r
204         # create the active fs\r
205         # 1. BASEDIR/RFSNN0\r
206         # 2. BASEDIR/active\r
207         $cmdbuf = "mkdir -p RFSFS/RFSNN0";\r
208         system $cmdbuf;\r
209         open RFS_ACTIVE, "active" || die "open active failed\n";\r
210         while (<RFS_ACTIVE>) {\r
211                 chop;\r
212                 my ($type, $fh, $path, $pathcnt, $sizeHexStr, $mode) = split (' ', $_, 7);\r
213                 if ($type==2) {\r
214                         $cmdbuf = "mkdir -p RFSFS$path";\r
215                         system $cmdbuf;\r
216                 }elsif ($type==1){\r
217                         &rfsCreateFile("RFSFS$path", $pathcnt, $sizeHexStr);\r
218                 }elsif ($type==5){\r
219                         #print STDERR "SYMLINK: $type fh: $fh path: $path\n";\r
220                         &rfsCreateSymlink("RFSFS$path", $pathcnt, $sizeHexStr);\r
221                 }else {\r
222                         print STDERR "special file: $type fh: $fh path: $path\n";\r
223                 }\r
224 \r
225                 my $line_num=0;\r
226                 $line_num++;\r
227                 if ( ($line_num %100)==0 ) {\r
228                         print STDERR "$line_num\n";\r
229                 }\r
230                 \r
231         }\r
232 \r
233         # create map table: key (fh), value (path/fn)\r
234 \r
235         # check whether there is fh that is not mapped to any path/fn in the trace\r
236 \r
237         # simulate a replay of trace\r
238 \r
239         return;\r
240         \r
241 }\r
242 \r
243 1;\r