SIONlib  1.7.4
Scalable I/O library for parallel access to task-local files
siondefrag.c
1 /****************************************************************************
2 ** SIONLIB http://www.fz-juelich.de/jsc/sionlib **
3 *****************************************************************************
4 ** Copyright (c) 2008-2019 **
5 ** Forschungszentrum Juelich, Juelich Supercomputing Centre **
6 ** **
7 ** See the file COPYRIGHT in the package base directory for details **
8 ****************************************************************************/
9 
10 #define _XOPEN_SOURCE 700
11 
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <ctype.h>
16 
17 #include "sion.h"
18 #include "sion_error_handler.h"
19 #include "sion_internal.h"
20 #include "sion_fd.h"
21 #include "sion_filedesc.h"
22 
23 #define FILENAME_LENGTH 1024
24 #define FILE_MODE_LENGTH 1024
25 #define MAXNULLCNT 1000
26 
27 #define MB *1024*1024
28 
29 static void usage(char *name);
30 
31 
32 int main(int argc, char **argv)
33 {
34  char infilename[FILENAME_LENGTH];
35  char outfilename[FILENAME_LENGTH];
36  char file_mode[FILE_MODE_LENGTH];
37  char endianness[FILE_MODE_LENGTH];
38  char keyvalue[FILE_MODE_LENGTH];
39 
40  int i, rank, blknum;
41  int nullcount;
42  sion_int64 max_chunksize = 0;
43  char *localbuffer = NULL;
44  long localbuffer_size=-1;
45  sion_int64 left, bread, bsumread, bwrote, bsumwrote;
46  sion_int64 *chunksizes = NULL;
47  int *globalranks = NULL;
48 
49  /* options */
50  int verbose = 0;
51  /* sion_int64 opt_localsize = -1; */
52  sion_int32 opt_fsblocksize = -1;
53  sion_int32 opt_nfiles = 1;
54 
55  /* for file infomation */
56  int ntasks, nfiles, onfiles;
57  sion_int32 fsblksize;
58  int sid, outsid, size, blocks;
59  sion_int64 globalskip;
60  sion_int64 start_of_varheader;
61  sion_int64 *sion_chunksizes;
62  sion_int64 *sion_globalranks;
63  sion_int64 *sion_blockcount;
64  sion_int64 *sion_blocksizes;
65  sion_int64 *siondefrag_sum_bytes_per_task;
66  sion_int64 siondefrag_sum_bytes;
67  sion_int64 siondefrag_filesize;
68  sion_int64 siondefrag_sum_chunksizes;
69  _sion_filedesc *sion_filedesc;
70  uint64_t key;
71  size_t len;
72 
73 
74  /* parse command line */
75  i = 1;
76  if (argc < 3)
77  usage(argv[0]);
78 
79  while (i < argc) {
80  if (argv[i][0] == '-') {
81  switch (argv[i][1]) {
82  /*
83  case 's':
84  opt_localsize = atoi(argv[++i]);
85  break;
86  case 'S':
87  opt_localsize = atoi(argv[++i]) MB;
88  break;
89  */
90  case 'n':
91  opt_nfiles = atoi(argv[++i]);
92  break;
93  case 'q':
94  opt_fsblocksize = atoi(argv[++i]);
95  break;
96  case 'Q':
97  opt_fsblocksize = atoi(argv[++i]) MB;
98  break;
99  case 'v':
100  verbose++;
101  break;
102  case 'V':
103  fprintf(stderr, "SIONlib utility %s (Version %d.%dp%d, fileformat version %d)\n", argv[0],
104  SION_MAIN_VERSION,SION_SUB_VERSION,
105  SION_VERSION_PATCHLEVEL,SION_FILEFORMAT_VERSION);
106  exit(1);
107  case 'h':
108  usage(argv[0]);
109  break;
110  default:
111  usage(argv[0]);
112  }
113  }
114  i++;
115  }
116 
117  strcpy(infilename, argv[argc - 2]);
118  strcpy(outfilename, argv[argc - 1]);
119 
120  printf("siondefrag: infilename: %-30s\n", infilename);
121  printf("siondefrag: outfilename: %-30s\n", outfilename);
122 
123  chunksizes = NULL;
124  globalranks = NULL; /* will be allocated by sion_open */
125 
126  sid = sion_open(infilename, "rb,posix", &ntasks, &nfiles, &chunksizes, &fsblksize, &globalranks, NULL);
127 
128  /* get the sion file structure */
129  if ((_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
130  return(_sion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,"invalid sion_filedesc, aborting %d ...\n", sid));
131  }
132 
133 
134  printf("siondefrag: sid: %d\n", sid);
135  printf("siondefrag: filename: %-30s\n", infilename);
136  printf("siondefrag: nfiles: %d\n", nfiles);
137  printf("siondefrag: fsblksize: %lu bytes (%6.2f MB)\n", (unsigned long) fsblksize, fsblksize / 1024.0 / 1024.0);
138  printf("siondefrag: keyval: %d (%s)\n", (int) sion_filedesc->keyvalmode, sion_keyval_type_to_str(sion_filedesc->keyvalmode));
139  printf("siondefrag: current endianness: %s\n", (sion_get_endianness())? "big" : "little");
140  printf("siondefrag: file endianness: %s\n", (sion_get_file_endianness(sid)) ? "big" : "little");
141 
142  sion_get_locations(sid, &size, &blocks, &globalskip, &start_of_varheader, &sion_chunksizes, &sion_globalranks, &sion_blockcount,
143  &sion_blocksizes);
144 
145  printf("siondefrag: max number of blocks: %d\n", blocks);
146 
147  /* analysis */
148  siondefrag_sum_bytes_per_task = (sion_int64 *) malloc(ntasks * sizeof(sion_int64));
149  for (rank = 0; rank < size; rank++)
150  siondefrag_sum_bytes_per_task[rank] = 0;
151  for (rank = 0; rank < size; rank++) {
152  for (blknum = 0; blknum < sion_blockcount[rank]; blknum++) {
153  siondefrag_sum_bytes_per_task[rank] += sion_blocksizes[size * blknum + rank];
154  }
155  }
156  siondefrag_sum_chunksizes = 0;
157  siondefrag_sum_bytes = 0;
158  for (rank = 0; rank < size; rank++) {
159  siondefrag_sum_bytes += siondefrag_sum_bytes_per_task[rank];
160  siondefrag_sum_chunksizes+= sion_chunksizes[rank];
161  }
162  printf("siondefrag: datasize in file (aggr.): %lld bytes (%6.2f MB)\n", siondefrag_sum_bytes, siondefrag_sum_bytes / 1024.0 / 1024.0);
163  siondefrag_filesize = start_of_varheader + (blocks + 1) * rank * sizeof(sion_int64);
164  printf("siondefrag: start_of_varheader: %lld bytes (%6.2f MB)\n", start_of_varheader, start_of_varheader / 1024.0 / 1024.0);
165  printf("siondefrag: size of chunks: %lld bytes (%6.2f MB)\n", siondefrag_sum_chunksizes, siondefrag_sum_chunksizes / 1024.0 / 1024.0);
166  if (siondefrag_filesize > 0) {
167  printf("siondefrag: file usage: %8.6f%%\n", (double) siondefrag_sum_bytes / (double) siondefrag_sum_chunksizes * 100.0);
168  }
169 
170  /* scan for block with max. number of bytes */
171  for (rank = 0; rank < size; rank++) {
172  if (sion_chunksizes[rank] > max_chunksize)
173  max_chunksize = sion_chunksizes[rank];
174  for (blknum = 0; blknum < sion_blockcount[rank]; blknum++) {
175  if (sion_blocksizes[size * blknum + rank] > max_chunksize)
176  max_chunksize = sion_blocksizes[size * blknum + rank];
177  }
178  }
179 
180  for (rank = 0; rank < size; rank++)
181  chunksizes[rank] = (sion_int64) siondefrag_sum_bytes_per_task[rank];
182 
183  if (opt_fsblocksize != -1)
184  fsblksize = opt_fsblocksize;
185 
186  onfiles = opt_nfiles;
187 
188 
189  /* preserve endianness */
190  if (sion_get_file_endianness(sid)) {
191  sprintf(endianness, "endianness=big");
192  } else {
193  sprintf(endianness, "endianness=little");
194  }
195  if(sion_filedesc->keyvalmode==SION_KEYVAL_NONE) {
196  sprintf(keyvalue, "keyval=none");
197  } else if(sion_filedesc->keyvalmode==SION_KEYVAL_INLINE) {
198  sprintf(keyvalue, "keyval=inline");
199  } else {
200  fprintf(stderr, "unknown keyvalue mode ..., aborting\n");
201  free(siondefrag_sum_bytes_per_task);
202  return (1);
203  }
204 
205 
206 
207  if(sion_filedesc->keyvalmode==SION_KEYVAL_NONE) {
208  /* standard copy with read/write */
209 
210  printf("siondefrag: max chunksize: %lld\n", max_chunksize);
211  localbuffer = (char *) malloc(max_chunksize * sizeof(char));
212  if (localbuffer == NULL) {
213  free(siondefrag_sum_bytes_per_task);
214  fprintf(stderr, "cannot allocate localbuffer of size %lld , aborting ...\n", max_chunksize * sizeof(char));
215  return (1);
216  }
217 
218 
219  sprintf(file_mode, "wb,posix,%s",endianness);
220  outsid = sion_open(outfilename, file_mode, &ntasks, &onfiles, &chunksizes, &fsblksize, &globalranks, NULL);
221 
222  printf("siondefrag: outsid: %d\n", outsid);
223  printf("siondefrag: fsblksize outfile: %lu\n", (unsigned long) fsblksize);
224 
225  for (rank = 0; rank < size; rank++) {
226 
227  /* set position in outfile to current rank */
228  if (verbose)
229  printf("siondefrag: ->rank: %d\n", rank);
230  if (!verbose)
231  if (rank % 16 == 0) {
232  printf("[%d]", rank);
233  fflush(stdout);
234  }
236 
237  if (verbose)
238  printf("siondefrag: copy now %lld blocks on rank=%d \n", sion_blockcount[rank], rank);
239  for (blknum = 0; blknum < sion_blockcount[rank]; blknum++) {
240 
241  /* seek position of block */
242  sion_seek(sid, rank, blknum, 0);
243 
244  /* read data from block */
245  left = sion_blocksizes[size * blknum + rank];
246  if (verbose)
247  printf("siondefrag: copy now block #%d with %lld bytes \n", blknum, left);
248  bsumread = 0;
249  nullcount = 0;
250  while (left > 0) {
251  bread = sion_fread(localbuffer + bsumread, 1, left, sid);
252  if (bread == 0)
253  nullcount++;
254  else
255  nullcount = 0;
256  left -= bread;
257  bsumread += bread;
258  /* printf("siondefrag: %lld read left=%lld \n", bread, left); */
259  if (nullcount > MAXNULLCNT) {
260  fprintf(stderr, "timeout on read data , aborting ...\n");
261  exit(0);
262  }
263  }
264 
265  /* write data to outfile */
266  left = sion_blocksizes[size * blknum + rank];
267  bsumwrote = 0;
268  while (left > 0) {
269  bwrote = sion_fwrite(localbuffer + bsumwrote, 1, left, outsid);
270  if (bwrote == 0)
271  nullcount++;
272  else
273  nullcount = 0;
274  left -= bwrote;
275  bsumwrote += bwrote;
276  /* printf("siondefrag: %ld wrote left=%ld position=%lld\n",bwrote,left,_sion_get_position(outfp)); */
277  if (nullcount > MAXNULLCNT) {
278  fprintf(stderr, "timeout on write data , aborting ...\n");
279  exit(0);
280  }
281  }
282  }
283 
284  }
285  if (!verbose) printf("\n");
286  sion_close(outsid);
287  free(localbuffer);
288 
289  } else {
290  /* key-value copy with read/write */
291 
292  sprintf(file_mode, "wb,posix,%s,%s",endianness,keyvalue);
293  outsid = sion_open(outfilename, file_mode, &ntasks, &onfiles, &chunksizes, &fsblksize, &globalranks, NULL);
294 
295  for (rank = 0; rank < size; rank++) {
296 
297  if (verbose)
298  printf("siondefrag: ->rank: %d\n", rank);
299  if (!verbose)
300  if (rank % 16 == 0) {
301  printf("[%d]", rank);
302  fflush(stdout);
303  }
304 
305  /* set position in outfile to current rank */
307 
308  /* seek position in infile */
310 
311  /* reset iterator over keys */
313 
314  /* loop over key-value blocks */
315  while(sion_fread_key_iterator_next(sid,&key,&len)==SION_SUCCESS) {
316 
317  /* allocate buffer space */
318  if((long) localbuffer_size< (long) len) {
319  if(localbuffer_size>0) {
320  free(localbuffer);
321  }
322  localbuffer = (char *) malloc(len * sizeof(char));
323  if (localbuffer == NULL) {
324  fprintf(stderr, "cannot allocate localbuffer of size %zu , aborting ...\n", len * sizeof(char));
325  free(siondefrag_sum_bytes_per_task);
326  return (1);
327  }
328  localbuffer_size=len;
329  }
330 
331  if (verbose)
332  printf("siondefrag: copy now key[%12ld] with %zu bytes \n", (long) key, len);
333 
334  /* read data of key */
335  bread = sion_fread_key(localbuffer, key, 1, len, sid);
336  /* bread=len; */
337  if (bread != len) {
338  fprintf(stderr, "cannot read data of key %ld with len %zu, aborting ...\n",(long) key, (size_t) len * sizeof(char));
339  free(siondefrag_sum_bytes_per_task);
340  return (1);
341  }
342 
343  /* write data of key */
344  bwrote = sion_fwrite_key(localbuffer, key, 1, len, outsid);
345  /* bread=len; */
346  if (bwrote != len) {
347  fprintf(stderr, "cannot write data of key %ld with len %zu, aborting ...\n",(long) key, (size_t) len * sizeof(char));
348  free(siondefrag_sum_bytes_per_task);
349  return (1);
350  }
351 
352  }
353 
354  }
355 
356 
357 
358  sion_close(outsid);
359  if (!verbose) printf("\n");
360  }
361 
362  free(siondefrag_sum_bytes_per_task);
363 
364  sion_close(sid);
365 
366 
367  return (0);
368 }
369 
370 void usage(char *name)
371 {
372  fprintf(stderr, "Usage: %s options <insionfn> <outfn>\n\n", name);
373 
374  fprintf(stderr, "Creates a new SIONlib file <outfn> from an existing <insionfn>. The\n");
375  fprintf(stderr, "resulting file has only one chunk. This can be used to make SIONlib\n");
376  fprintf(stderr, "files less sparse (e.g. by using -q 1 which effectively removes file\n");
377  fprintf(stderr, "system block alignment).\n\n");
378 
379  fprintf(stderr, "Options:\n");
380  fprintf(stderr, " [-Q <fsblksize>] filessystem blocksize for new sion file in MB\n");
381  fprintf(stderr, " (default from input file)\n");
382  fprintf(stderr, " [-q <fsblksize>] filessystem blocksize for new sion file in bytes\n");
383  fprintf(stderr, " [-v] verbose mode\n");
384  fprintf(stderr, " [-V] show version of SIONlib\n");
385  fprintf(stderr, " [-h] show this help\n");
386  exit(1);
387 }
Sion File Descriptor Structure.
Definition: sion_filedesc.h:79
int sion_get_endianness(void)
Return endianness.
Definition: sion_tools.c:32
int sion_get_file_endianness(int sid)
Returns edianness of data in file sid.
Definition: sion_common.c:253
int sion_fread_key_iterator_next(int sid, uint64_t *key, size_t *size)
Forward to next key.
#define SION_KEYVAL_INLINE
Definition: sion_const.h:80
#define SION_CURRENT_BLK
Definition: sion_const.h:66
int sion_close(int sid)
Close a sion file.
Definition: sion_serial.c:106
int _sion_vcdtype(int sid)
Definition: sion_fd.c:58
int sion_get_locations(int sid, int *ntasks, int *maxchunks, sion_int64 *globalskip, sion_int64 *start_of_varheader, sion_int64 **sion_chunksizes, sion_int64 **sion_globalranks, sion_int64 **sion_blockcount, sion_int64 **sion_blocksizes)
Returns pointers to internal fields.
Definition: sion_common.c:84
#define SION_KEYVAL_NONE
Definition: sion_const.h:79
size_t sion_fwrite(const void *data, size_t size, size_t nitems, int sid)
Write data to sion file.
Definition: sion_common.c:470
char * sion_keyval_type_to_str(int type)
Returns key value mode as string.
void * _sion_vcdtovcon(int sid)
Definition: sion_fd.c:53
int sion_seek(int sid, int rank, int currentblocknr, sion_int64 posinblk)
Function to set the file pointer to a new position.
Definition: sion_common.c:698
#define SION_CURRENT_POS
Definition: sion_const.h:69
int sion_fread_key_iterator_reset(int sid)
Resets key iterator.
#define SION_FILEDESCRIPTOR
Definition: sion_fd.h:17
size_t sion_fread(void *data, size_t size, size_t nitems, int sid)
Read data from sion file.
Definition: sion_common.c:609
size_t sion_fread_key(void *data, uint64_t key, size_t size, size_t nitems, int sid)
Read data for key.
size_t sion_fwrite_key(const void *data, uint64_t key, size_t size, size_t nitems, int sid)
Writes data for key.
int sion_open(char *fname, const char *file_mode, int *ntasks, int *nfiles, sion_int64 **chunksizes, sion_int32 *fsblksize, int **globalranks, FILE **fileptr)
Open a sion file in serial mode.
Definition: sion_serial.c:54