6d4878bb58db7d3e66376dab32cc6545ab42efd2
[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 <string.h>
18 #include <stdlib.h>
19 #include <sys/types.h>          /* for mtio.h */
20 #include <afs/cmd.h>
21 #include <afs/procmgmt.h>
22 #include <afs/usd.h>
23
24 /* structure for writing data to tape */
25 typedef struct tapeDataBuffer {
26     struct tapeDataBuffer *tdb_next;
27     char *tdb_buffer;
28 } tapeDataBufferT;
29 typedef tapeDataBufferT *tapeDataBufferP;
30
31 /* globals */
32 char *tapeDevice = 0;           /* device pathname */
33 afs_int32 eotEnabled = 1;
34
35 /* prototypes */
36 int fileMark(usd_handle_t hTape);
37 int fileMarkSize(char *tapeDevice);
38 static int tt_fileMarkSize(struct cmd_syndesc *as, void *arock);
39 afs_int32 rewindTape(usd_handle_t hTape);
40 int dataBlock(usd_handle_t, afs_int32);
41
42 #define ERROR(evalue) do {                                      \
43             code = evalue;                                      \
44             goto error_exit;                                    \
45         } while (0)
46
47 #define MAXV    100
48
49 #ifndef AFS_NT40_ENV
50 #include "AFS_component_version_number.c"
51 #endif
52
53 void quitFms(int);
54
55 int
56 main(int argc, char **argv)
57 {
58     struct sigaction intaction, oldaction;
59     struct cmd_syndesc *cptr;
60
61     memset(&intaction, 0, sizeof(intaction));
62     intaction.sa_handler = quitFms;
63
64     sigaction(SIGINT, &intaction, &oldaction);
65
66     cptr =
67         cmd_CreateSyntax(NULL, tt_fileMarkSize, NULL,
68                          "write a tape full of file marks");
69     cmd_AddParm(cptr, "-tape", CMD_SINGLE, CMD_REQUIRED, "tape special file");
70
71     cmd_Dispatch(argc, argv);
72     return 0;
73 }
74
75 static int
76 tt_fileMarkSize(struct cmd_syndesc *as, void *arock)
77 {
78     char *tapeDevice;
79
80     tapeDevice = as->parms[0].items->data;
81
82     fileMarkSize(tapeDevice);
83
84     return 0;
85 }
86
87
88 int
89 fileMarkSize(char *tapeDevice)
90 {
91     afs_uint32 nFileMarks, nBlocks, nbfTape;
92     double tpSize, fmSize;
93     afs_uint32 bufferSize = 16384;
94     usd_handle_t hTape;
95     FILE *logFile;
96     int count = 0;
97     afs_uint32 countr;
98     afs_int32 code = 0;
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 int
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;
260     afs_uint32 xferd;
261
262     /* dbBuffersize is only valid when dB_buffer is non-zero */
263
264     if ((dB_buffer != 0)
265         && (dB_buffersize != reqSize)
266         ) {
267         free(dB_buffer);
268         dB_buffer = 0;
269     }
270
271     if (dB_buffer == 0) {
272         dB_buffer = (char *)malloc(reqSize);
273         if (dB_buffer == 0)
274             ERROR(-1);
275         dB_buffersize = reqSize;
276         memset(dB_buffer, 0, dB_buffersize);
277     }
278
279     ptr = (int *)dB_buffer;
280     *ptr = dB_count++;
281
282     code = USD_WRITE(hTape, dB_buffer, dB_buffersize, &xferd);
283     if (code || xferd != dB_buffersize)
284         ERROR(-1);
285
286   error_exit:
287     return (code);
288 }