5700dde88a595fc079db4f557e784ee461031753
[openafs.git] / src / bu_utils / fms.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13
14 #undef  IN
15 #include <stdio.h>
16 #include <errno.h>
17 #include <sys/types.h>          /* for mtio.h */
18 #include <afs/cmd.h>
19 #include <afs/procmgmt.h>
20 #include <afs/usd.h>
21
22 /* structure for writing data to tape */
23 typedef struct tapeDataBuffer {
24     struct tapeDataBuffer *tdb_next;
25     char *tdb_buffer;
26 } tapeDataBufferT;
27 typedef tapeDataBufferT *tapeDataBufferP;
28
29 /* globals */
30 char *tapeDevice = 0;           /* device pathname */
31 afs_int32 eotEnabled = 1;
32
33 /* prototypes */
34 int fileMark(usd_handle_t hTape);
35 int fileMarkSize(char *tapeDevice);
36 static int tt_fileMarkSize(struct cmd_syndesc *as, void *arock);
37
38 #define ERROR(evalue)                                           \
39         {                                                       \
40             code = evalue;                                      \
41             goto error_exit;                                    \
42         }
43
44 #define MAXV    100
45
46 #ifndef AFS_NT40_ENV
47 #include "AFS_component_version_number.c"
48 #endif
49
50 void quitFms(int);
51
52 main(argc, argv)
53      int argc;
54      char **argv;
55 {
56     struct sigaction intaction, oldaction;
57     struct cmd_syndesc *cptr;
58
59     memset((char *)&intaction, 0, sizeof(intaction));
60     intaction.sa_handler = (int (*)())quitFms;
61
62     sigaction(SIGINT, &intaction, &oldaction);
63
64     cptr =
65         cmd_CreateSyntax(NULL, tt_fileMarkSize, NULL,
66                          "write a tape full of file marks");
67     cmd_AddParm(cptr, "-tape", CMD_SINGLE, CMD_REQUIRED, "tape special file");
68
69     cmd_Dispatch(argc, argv);
70     return 0;
71 }
72
73 static int
74 tt_fileMarkSize(struct cmd_syndesc *as, void *arock)
75 {
76     char *tapeDevice;
77
78     tapeDevice = as->parms[0].items->data;
79
80     fileMarkSize(tapeDevice);
81
82     return 0;
83 }
84
85
86 fileMarkSize(tapeDevice)
87      char *tapeDevice;
88 {
89     afs_uint32 nFileMarks, nBlocks, nbfTape;
90     double tpSize, fmSize;
91     afs_uint32 bufferSize = 16384;
92     usd_handle_t hTape;
93     FILE *logFile;
94     int count = 0;
95     afs_uint32 countr;
96     afs_int32 code = 0;
97
98     afs_int32 rewindTape();
99
100     code =
101         usd_Open(tapeDevice, (USD_OPEN_RDWR | USD_OPEN_WLOCK), 0777, &hTape);
102     if (code) {
103         printf("Can't open tape device %s\n", tapeDevice);
104         fflush(stdout);
105         exit(1);
106     }
107
108     logFile = fopen("fms.log", "w+");
109     if (logFile == NULL) {
110         printf("Can't open log file\n");
111         fflush(stdout);
112         exit(1);
113     }
114     fprintf(logFile, "fms test started\n");
115     fflush(logFile);
116
117     code = rewindTape(hTape);
118     if (code) {
119         fprintf(logFile, "Can't rewind tape\n");
120         fflush(logFile);
121         ERROR(code);
122     }
123
124     /* measure capacity of tape */
125     nbfTape = 0;
126     countr = 0;
127     while (1) {
128         code = dataBlock(hTape, bufferSize);
129         nbfTape++;
130         count++;
131         countr++;
132         if (code)
133             break;
134
135         if (count >= 5) {
136             count = 0;
137             printf("\rwrote block: %d", nbfTape);
138         }
139
140     }
141
142     fprintf(logFile, "wrote %d blocks\n", nbfTape);
143     fflush(logFile);
144     printf("\rwrote %d blocks\n", nbfTape);
145     printf("Finished data capacity test - rewinding\n");
146     /* reset the tape device */
147     code = USD_CLOSE(hTape);
148     if (code) {
149         fprintf(logFile, "Can't close tape device at end of pass 1\n");
150         fflush(logFile);
151         printf("Can't close tape device %s\n", tapeDevice);
152         goto error_exit;
153     }
154     code =
155         usd_Open(tapeDevice, (USD_OPEN_RDWR | USD_OPEN_WLOCK), 0777, &hTape);
156     if (code) {
157         fprintf(logFile, "Can't open tape device for pass 2\n");
158         fflush(logFile);
159         printf("Can't open tape device %s\n", tapeDevice);
160         goto error_exit;
161     }
162
163     code = rewindTape(hTape);
164     if (code) {
165         fprintf(logFile, "Can't rewind tape\n");
166         fflush(logFile);
167         ERROR(code);
168     }
169
170     /* now measure file mark size */
171     nFileMarks = 0;
172     nBlocks = 0;
173     count = 0;
174     countr = 0;
175     while (1) {
176         code = dataBlock(hTape, bufferSize);
177         nBlocks++;
178         if (code)
179             break;
180         code = fileMark(hTape);
181         nFileMarks++;
182         if (code)
183             break;
184         count++;
185         countr++;
186
187         if (count >= 2) {
188             count = 0;
189             printf("\rwrote %d blocks, %d filemarks", nBlocks, nFileMarks);
190         }
191
192     }
193     printf("\nFinished filemark test\n");
194     tpSize = (double)nbfTape *(double)bufferSize;
195     fmSize =
196         (((double)nbfTape -
197           (double)nBlocks) * (double)bufferSize) / (double)nFileMarks;
198     printf("Tape capacity is %.0f bytes\n", tpSize);
199     printf("File marks are %.0f bytes\n", fmSize);
200     fprintf(logFile, "Tape capacity is %.0f bytes\n", tpSize);
201     fprintf(logFile, "File marks are %.0f bytes\n", fmSize);
202     fflush(logFile);
203     fclose(logFile);
204   error_exit:
205     USD_CLOSE(hTape);
206     return (code);
207 }
208
209 void
210 quitFms(int sig)
211 {
212     exit(0);
213 }
214
215
216 /* --------------------------
217  * device handling routines
218  * --------------------------
219  */
220
221 /* rewindTape() - rewinds tape to beginning */
222 afs_int32
223 rewindTape(usd_handle_t hTape)
224 {
225     usd_tapeop_t tapeop;
226     int rcode;
227
228     tapeop.tp_op = USDTAPE_REW;
229     tapeop.tp_count = 1;
230     rcode = USD_IOCTL(hTape, USD_IOCTL_TAPEOPERATION, (void *)&tapeop);
231     return rcode;
232 }
233
234 /* write an EOF marker */
235 int
236 fileMark(usd_handle_t hTape)
237 {
238     usd_tapeop_t tapeop;
239     int rcode;
240
241     tapeop.tp_op = USDTAPE_WEOF;
242     tapeop.tp_count = 1;
243     rcode = USD_IOCTL(hTape, USD_IOCTL_TAPEOPERATION, (void *)&tapeop);
244     return rcode;
245 }
246
247 /* dataBlock
248  *      write a block of data on tape
249  * entry:
250  *      blocksize - size of block in bytes
251  */
252
253 dataBlock(usd_handle_t hTape, afs_int32 reqSize)
254 {
255     static char *dB_buffer = 0;
256     static afs_int32 dB_buffersize = 0;
257     static int dB_count = 0;
258     int *ptr;
259     afs_int32 code = 0, xferd;
260
261     /* dbBuffersize is only valid when dB_buffer is non-zero */
262
263     if ((dB_buffer != 0)
264         && (dB_buffersize != reqSize)
265         ) {
266         free(dB_buffer);
267         dB_buffer = 0;
268     }
269
270     if (dB_buffer == 0) {
271         dB_buffer = (char *)malloc(reqSize);
272         if (dB_buffer == 0)
273             ERROR(-1);
274         dB_buffersize = reqSize;
275         memset(dB_buffer, 0, dB_buffersize);
276     }
277
278     ptr = (int *)dB_buffer;
279     *ptr = dB_count++;
280
281     code = USD_WRITE(hTape, dB_buffer, dB_buffersize, &xferd);
282     if (code || xferd != dB_buffersize)
283         ERROR(-1);
284
285   error_exit:
286     return (code);
287 }