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