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