SIONlib  1.7.1
Scalable I/O library for parallel access to task-local files
sion_generic_buddy.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  *
11  * \brief Internal Functions(parallel)
12  */
13 
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <unistd.h>
18 
19 #include "sion.h"
20 #include "sion_debug.h"
21 #include "sion_error_handler.h"
22 #include "sion_file.h"
23 #include "sion_filedesc.h"
24 #include "sion_fd.h"
25 #include "sion_metadata.h"
26 #include "sion_internal.h"
27 #include "sion_printts.h"
28 #include "sion_flags.h"
29 
30 #include "sion_buffer.h"
31 
32 #include "sion_filedesc.h"
33 #include "sion_keyvalue.h"
34 
35 #include "sion_generic_internal.h"
37 #include "sion_generic_buddy.h"
38 
39 
61 #define DFUNCTION "_sion_paropen_generic_buddy"
62 int _sion_paropen_generic_buddy(
63  int sid,
64  const char *fname,
65  _sion_flags_store *flags_store,
66  char *prefix,
67  int *numFiles,
68  int *filenumber,
69  sion_int64 *chunksize,
70  sion_int32 *fsblksize,
71  int rank,
72  int ntasks,
73  int *globalrank,
74  FILE **fileptr,
75  _sion_generic_gendata *sion_gendata )
76 {
77  int rc = SION_SUCCESS;
78  int b, capability, pass, buddylevel;
79  sion_int32 file_globalrank;
80  sion_int64 file_chunksize;
81  char *buddy_fn, *nfname=NULL;
82  _sion_filedesc *sion_filedesc;
83  _sion_generic_buddy *buddies, *buddyptr;
84  _sion_generic_apidesc *sion_apidesc;
85 
86  buddylevel = atoi(_sion_flags_get(flags_store,"buddy")->val);
87  if (buddylevel==0) buddylevel=1; /* default */
88 
89  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "allocate memory for %d buddy levels\n", buddylevel));
90 
91  buddies = (_sion_generic_buddy *) malloc(buddylevel * sizeof(_sion_generic_buddy));
92  if (buddies == NULL) {
93  return(_sion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,"cannot allocate buddies structure of size %lu (_sion_generic_buddy), aborting ...\n",
94  (unsigned long) sizeof(_sion_generic_buddy)));
95  }
96  buddies->numgroups=0;
97 
98  buddy_fn = calloc(SION_FILENAME_LENGTH+10,1);
99  if (buddy_fn == NULL) {
100  free(buddies);
101  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_paropen_generic_buddy: cannot allocate temporary memory of size %lu (buddy_fn), aborting ...\n",
102  (unsigned long) SION_FILENAME_LENGTH+10));
103  }
104 
105  /* get pointer to internal datastructures */
106  sion_apidesc=sion_gendata->apidesc;
107 
108  if (flags_store->mask&_SION_FMODE_WRITE) {
109 
110  /* STEP1: WRITE open normal file */
111  nfname=(sion_apidesc->get_multi_filename_cb?sion_apidesc->get_multi_filename_cb:_sion_get_multi_filename)
112  (fname,sion_gendata->filenumber);
113  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "call parallel open of %d files (current name %s)\n",
114  sion_gendata->numfiles, nfname));
115  rc=_sion_paropen_generic_one_file(sid, nfname, flags_store, prefix,
116  &sion_gendata->numfiles, &sion_gendata->filenumber,
117  chunksize, fsblksize,
118  sion_gendata->lrank, sion_gendata->lsize, globalrank,
119  _SION_INTERNAL_FLAG_BUDDY_NORMAL, fileptr, sion_gendata, NULL);
120  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "leave parallel open of %d files in #tasks=%d sid=%d globalrank=%d\n", sion_gendata->numfiles,
121  sion_gendata->lsize, sid, sion_gendata->grank));
122  free(nfname);
123 
124  /* test sid and get internal data structure */
125  if ((rc<0) || (sid<0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
126  free(buddies);
127  free(buddy_fn);
128  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_paropen_generic_buddy: invalid sion_filedesc %d", sid));
129  }
130 
131  /* store additional data */
132  sion_filedesc->buddies=buddies;
133 
134  capability=sion_apidesc->get_capability_cb(sion_gendata->comm_data_global);
135 
136  /* open buddy files */
137  for(b=0;b<sion_filedesc->buddylevel;b++) {
138  buddyptr=&buddies[b];
139 
140  /* create communicators */
141  buddyptr->buddy_send.commgroup=NULL; buddyptr->buddy_coll.commgroup=NULL;
142  rc=_sion_buddy_map(sion_gendata,capability,b+1,&buddyptr->buddy_send,&buddyptr->buddy_coll);
143 
144  /* file name */
145  sprintf(buddy_fn,"%s_BUDDY_%02d", fname,b);
146 
147  /* open files */
148  for(pass=1;pass<=_SION_BW_SCHED_NUM_PASSES;pass++) {
149 
150  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDYO pass=%d [grank=%2d] op=%d\n",pass,*globalrank,
151  _sion_buddy_bwsched(buddyptr->buddy_send.groupnum, sion_gendata->numfiles, pass)));
152 
153 
154  switch (_sion_buddy_bwsched(buddyptr->buddy_send.groupnum, sion_gendata->numfiles, pass)) {
155  case _SION_BW_SCHED_ACTIONA:
156  /* parameter */
157  file_globalrank=-1*(*globalrank+1);
158  file_chunksize=0;
159  nfname=(sion_apidesc->get_multi_filename_cb?sion_apidesc->get_multi_filename_cb:_sion_get_multi_filename)
160  (buddy_fn,buddyptr->buddy_coll.filenum);
161  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDYO call open_one_file COLL [gendata: b=%d grank=%2d, group=%d of %d, lrank=%d of %d] fn=%s (%d)\n",
162  b,*globalrank, buddyptr->buddy_coll.groupnum,sion_gendata->numfiles,
163  buddyptr->buddy_coll.rank, buddyptr->buddy_coll.size,nfname,buddyptr->buddy_coll.filenum));
164  buddyptr->buddy_coll.sid = _sion_newvcd(NULL,SION_FILEDESCRIPTOR);
165  rc=_sion_paropen_generic_one_file(buddyptr->buddy_coll.sid, nfname, flags_store, prefix,
166  &sion_gendata->numfiles, &buddyptr->buddy_coll.filenum,
167  &file_chunksize, fsblksize,
168  buddyptr->buddy_coll.rank,buddyptr->buddy_coll.size, &file_globalrank,
169  _SION_INTERNAL_FLAG_BUDDY_COLL, NULL, sion_gendata,
170  buddyptr);
171  free(nfname);
172  break;
173  case _SION_BW_SCHED_ACTIONB:
174  /* parameter */
175  file_globalrank=*globalrank;
176  file_chunksize=*chunksize;
177  nfname=(sion_apidesc->get_multi_filename_cb?sion_apidesc->get_multi_filename_cb:_sion_get_multi_filename)
178  (buddy_fn,buddyptr->buddy_send.filenum);
179  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDYO call open_one_file SEND [gendata: b=%d grank=%2d, group=%d of %d, lrank=%d of %d] fn=%s \n",
180  b,*globalrank, buddyptr->buddy_send.groupnum,sion_gendata->numfiles,
181  buddyptr->buddy_send.rank, buddyptr->buddy_send.size,nfname));
182  buddyptr->buddy_send.sid = _sion_newvcd(NULL,SION_FILEDESCRIPTOR);
183  rc=_sion_paropen_generic_one_file(buddyptr->buddy_send.sid, nfname, flags_store, prefix,
184  &sion_gendata->numfiles, &buddyptr->buddy_send.filenum,
185  &file_chunksize, fsblksize,
186  buddyptr->buddy_send.rank,buddyptr->buddy_send.size, &file_globalrank,
187  _SION_INTERNAL_FLAG_BUDDY_SEND, NULL, sion_gendata,
188  buddyptr);
189  free(nfname);
190  break;
191  default:
192  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDYO no-op [grank=%2d]\n",*globalrank));
193  break;
194  } /* switch */
195  } /* for pass */
196  } /* for buddies */
197 
198  } else if (flags_store->mask&_SION_FMODE_READ) {
199  int filefound, lgroup=*filenumber, root=0, task, tmpsize, group, masterfile_found;
200  sion_int32 filenumber, numfiles, lrank, lsize, file, file_lgroup, myrole, steprank;
201  sion_int32 helpint32=0, numsteps=0, numgroups=0, numreaderinthisfile;
202  sion_int32 *sion_tmpintfield1 = NULL; /* allocated on rank 0 */
203  /* sion_int32 *sion_tmpintfield2 = NULL; */ /* allocated on lranl-0 that has access to master file */
204 
205  int *stepvectorlist[MAXREADSTEPS]; /* to be changed in an dynamic list */
206  int *stepvector, readercount=0, readyflag=0, datafound=0;
207  int stepcount_coll,stepcount_collreader,stepcount_reader,stepcount_reader_rank,stepcount_noreader,stepcount_noreader_rank, groupcounter;
208  int step,fit,newrank;
209  _sion_generic_buddy_info *buddy_info;
210  sion_int32 helpint7[7];
211 
212  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "enter buddy open in read mode\n"));
213 
214  if(sion_gendata->grank==0) {
215  tmpsize=1*sion_gendata->gsize;
216  sion_tmpintfield1 = (sion_int32 *) malloc(tmpsize * sizeof(sion_int32));
217  if (sion_tmpintfield1 == NULL) {
218  free(buddies);
219  free(buddy_fn);
220  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_paropen_generic_buddy: cannot allocate temporary memory of size %lu (sion_tmpintfield), aborting ...\n",
221  (unsigned long) tmpsize * sizeof(sion_int32)));
222  }
223  }
224 
225  /* Loop1: over all file sets (normal, buddy1, buddy2) until all have found their data chunk */
226  groupcounter=0;
227  for(b=-1; ( (b<buddylevel) && (!readyflag));b++) {
228 
229  /* determine filename and check for existence of master file on each lrank=0 */
230  if(b==-1) sprintf(buddy_fn,"%s", fname);
231  else sprintf(buddy_fn,"%s_BUDDY_%02d", fname,b);
232  nfname=(sion_apidesc->get_multi_filename_cb?sion_apidesc->get_multi_filename_cb:_sion_get_multi_filename)(buddy_fn,0);
233  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDY[%2d] start checking buddy level (file=%s)\n",b,nfname));
234 
235  filefound=0;
236  if(sion_gendata->lrank==0) {
237  if(_sion_file_stat_file(nfname)) {
238  filefound=1;
239  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "check for existence of file %s --> file found\n",nfname));
240  }
241  }
242 
243  /* distribute info about master file to all others (root=<tasknum> or -1 if file not found) */
244  helpint32=filefound;
245  sion_gendata->apidesc->gatherr_cb(&helpint32, sion_tmpintfield1, sion_gendata->comm_data_global, _SION_INT32, 1, 0);
246  if (sion_gendata->grank == 0) {
247  root=-1;
248  if (sion_tmpintfield1 == NULL) {
249  free(buddies);
250  free(buddy_fn);
251  return(_sion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_ABORT, DFUNCTION ": gatherr_cb returned sion_tmpintfield1 == NULL"));
252  }
253  for(task=0;task<sion_gendata->gsize;task++) {
254  if(sion_tmpintfield1[task]==1) root=task;
255  }
256  helpint32=root;
257  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "after scan master: root for this file is %d #tasks=%d\n",root,sion_gendata->gsize));
258  }
259  sion_gendata->apidesc->bcastr_cb(&helpint32, sion_gendata->comm_data_global, _SION_INT32, 1, 0); root=helpint32;
260  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "root for this file is %d\n",root));
261 
262  /* get mapping from file and distribute it */
263  if(root!=-1) {
264  _sion_generic_buddy_get_and_distribute_info_from_file(sion_gendata,nfname,root, &filenumber, &numfiles, &lrank, &lsize);
265  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDY[%d] after read mapping file=%d of %d, lrank=%d of %d\n",b,filenumber, numfiles, lrank, lsize));
266  masterfile_found=1;
267  } else {
268  filenumber=lrank=lsize=-1;
269  masterfile_found=0;
270  }
271  free(nfname);
272 
273  /* numfiles will be defined from from input parameter, other info will be defined on-the-fly */
274  numfiles=*numFiles;
275  DPRINTFP((32, DFUNCTION, sion_gendata->grank, "Info avail: b=%d numfiles=%d root=%d lgroup=%d\n",b,numfiles,root,lgroup));
276 
277  /* Loop2: for each physical file of this file set */
278  for(file=0;( (file<numfiles) && (!readyflag) );file++) {
279 
280  /* check physical file */
281  nfname=(sion_apidesc->get_multi_filename_cb?sion_apidesc->get_multi_filename_cb:_sion_get_multi_filename)(buddy_fn,file);
282  filefound=-1;
283  if(sion_gendata->lrank==0) {
284  if(_sion_file_stat_file(nfname)) {
285  filefound=lgroup;
286  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "check for existence of file %s --> file found\n",nfname));
287  }
288  }
289 
290  /* gather and distribute info (root and lgroup) about file to all others (root=<tasknum> or -1 if file not found) */
291  helpint32=filefound;
292  sion_gendata->apidesc->gatherr_cb(&helpint32, sion_tmpintfield1, sion_gendata->comm_data_global, _SION_INT32, 1, 0);
293  if (sion_gendata->grank == 0) {
294  root=-1;
295  for(task=0;task<sion_gendata->gsize;task++) {
296  if(sion_tmpintfield1[task]>-1) {
297  root=task;
298  file_lgroup=sion_tmpintfield1[task];
299  }
300  }
301  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "after scan one file: root for this file is %d file_lgroup=%d\n",root,file_lgroup));
302  }
303  if (sion_gendata->grank == 0) helpint32=root;
304  sion_gendata->apidesc->bcastr_cb(&helpint32, sion_gendata->comm_data_global, _SION_INT32, 1, 0); root=helpint32;
305  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "root for this file is %d\n",root));
306 
307  if(root>=0) {
308  /* file found */
309 
310  if(!masterfile_found) {
311  /* get avail info from file: lrank/lsize for local tasks */
312  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDY[%d] befre read globalranks file=%d of %d, lrank=%d of %d\n",
313  b, filenumber, numfiles, lrank, lsize));
314  _sion_generic_buddy_get_and_distribute_info_from_one_file(sion_gendata, nfname, root, &filenumber, &numfiles, &lrank, &lsize);
315  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDY[%d] after read globalranks file=%d of %d, lrank=%d of %d\n",
316  b, filenumber, numfiles, lrank, lsize));
317  }
318 
319  /* bcast lgroup */
320  if (sion_gendata->grank == 0) helpint32=file_lgroup;
321  sion_gendata->apidesc->bcastr_cb(&helpint32, sion_gendata->comm_data_global, _SION_INT32, 1, 0); file_lgroup=helpint32;
322  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "file_lgroup for this file is %d\n",file_lgroup));
323 
324  /* determine my role for this file */
325  myrole=SION_ROLE_NONE; /* not acting on that file */
326  if((filenumber==file) && (!datafound)) {
327  datafound=1; /* fantastic ... */
328  if(sion_gendata->grank==root) myrole=SION_ROLE_COLLECTOR_READER; /* collector and reader */
329  else myrole=SION_ROLE_READER; /* reader */
330  } else {
331  if(sion_gendata->grank==root) myrole=SION_ROLE_COLLECTOR; /* collector */
332  else if(file_lgroup==lgroup) myrole=SION_ROLE_NOREADER; /* task on the same lgroup but not collector */
333  }
334 
335  /* collect on rank 0 info about each task acting on this file */
336  helpint32=myrole;
337  sion_gendata->apidesc->gatherr_cb(&helpint32, sion_tmpintfield1, sion_gendata->comm_data_global, _SION_INT32, 1, 0);
338 
339  /* check if at least one tasks needs data */
340  if(sion_gendata->grank == 0) {
341  numreaderinthisfile=0;
342  if (sion_tmpintfield1 == NULL) {
343  return(_sion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_ABORT, DFUNCTION ": gatherr_cb returned sion_tmpintfield1 == NULL"));
344  }
345  for(task=0; ( (task<sion_gendata->gsize) ) ;task++)
346  if ( (sion_tmpintfield1[task]==SION_ROLE_COLLECTOR_READER) || (sion_tmpintfield1[task]==SION_ROLE_READER) ) numreaderinthisfile++;
347  }
348  sion_gendata->apidesc->bcastr_cb(&numreaderinthisfile, sion_gendata->comm_data_global, _SION_INT32, 1, 0);
349 
350  if (numreaderinthisfile>0) {
351 
352  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "myrole for file %s is %s\n",nfname,_sion_buddy_role_to_str(myrole)));
353 
354  /* check for step in which the group can be created */
355  if (sion_gendata->grank == 0) {
356  /* check in existing steps if group can created there */
357  fit=0;
358  for(step=0; ( (step<numsteps) && (fit==0) ) ;step++) {
359  stepvector=stepvectorlist[step];
360  fit=1;
361  for(task=0; ( (task<sion_gendata->gsize) && (fit==1) ) ;task++) {
362  if(sion_tmpintfield1[task]!=SION_ROLE_NONE) {
363  if(stepvector[task]!=SION_ROLE_NONE) fit=0;
364  }
365  }
366  }
367  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDY STEP assign: after scanning %d steps fit=%d\n",numsteps,fit));
368  if(fit==0) {
369  /* no space in available steps, create a new one */
370  stepvector = (int *) malloc(sion_gendata->gsize * sizeof(int));
371  if (stepvector == NULL) {
372  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_paropen_generic_buddy: cannot allocate temporary memory of size %lu (stepvector), aborting ...\n",
373  (unsigned long) sion_gendata->gsize * sizeof(int)));
374  }
375  for(task=0; (task<sion_gendata->gsize);task++) stepvector[task]=SION_ROLE_NONE;
376  numsteps++;step++;
377  stepvectorlist[numsteps-1]=stepvector;
378  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDY STEP assign: allocating new step %d\n",numsteps-1));
379  }
380  /* store roles in stepvector and analyse group */
381  stepcount_coll=stepcount_collreader=stepcount_reader=stepcount_noreader=0;
382  for(task=0; (task<sion_gendata->gsize);task++) {
383  if(sion_tmpintfield1[task]!=SION_ROLE_NONE) {
384  stepvector[task]=sion_tmpintfield1[task];
385  if (sion_tmpintfield1[task]==SION_ROLE_COLLECTOR) stepcount_coll++;
386  if (sion_tmpintfield1[task]==SION_ROLE_READER) {readercount++;stepcount_reader++;}
387  if (sion_tmpintfield1[task]==SION_ROLE_COLLECTOR_READER) {readercount++;stepcount_collreader++;}
388  if (sion_tmpintfield1[task]==SION_ROLE_NOREADER) stepcount_noreader++;
389  }
390  }
391  /* DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDY STEP assign: stepcount_coll=%d stepcount_collreader=%d stepcount_reader=%d stepcount_noreader=%d\n", */
392  /* stepcount_coll,stepcount_collreader, stepcount_reader, stepcount_noreader)); */
393  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDY STEP assign: group assigned to step %d (tasks with no data: %d)\n",numsteps-1,sion_gendata->gsize-readercount));
394  if(sion_gendata->gsize-readercount==0) readyflag=1;
395 
396  /* calculate ranks */
397  stepcount_noreader_rank = stepcount_coll;
398  stepcount_reader_rank = stepcount_noreader_rank+stepcount_noreader;
399  for(task=0; (task<sion_gendata->gsize);task++) {
400  /*DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDY STEP assign1: task %d stepcount_reader_rank=%d stepcount_noreader_rank=%d %s\n",
401  task, stepcount_reader_rank, stepcount_noreader_rank,_sion_buddy_role_to_str(sion_tmpintfield1[task])));*/
402  if(sion_tmpintfield1[task]==SION_ROLE_NONE) newrank=-1;
403  if(sion_tmpintfield1[task]==SION_ROLE_COLLECTOR) newrank=0;
404  if(sion_tmpintfield1[task]==SION_ROLE_COLLECTOR_READER) newrank=stepcount_reader_rank++;
405  if(sion_tmpintfield1[task]==SION_ROLE_NOREADER) newrank=stepcount_noreader_rank++;
406  if(sion_tmpintfield1[task]==SION_ROLE_READER) newrank=stepcount_reader_rank++;
407  sion_tmpintfield1[task]=newrank;
408  /* DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDY STEP assign2: rank %d to task %d stepcount_reader_rank=%d stepcount_noreader_rank=%d\n",
409  sion_tmpintfield1[task],task, stepcount_reader_rank, stepcount_noreader_rank));*/
410  }
411  } /* if(rank==0) --> stepvector handling */
412 
413  /* scatter rank info to tasks */
414  sion_gendata->apidesc->scatterr_cb(sion_tmpintfield1, &steprank, sion_gendata->comm_data_global, _SION_INT32, 1, 0);
415 
416 
417  /* bcast info ), ready flag, size, collsize, to_index */
418  if (sion_gendata->grank == 0) {
419 
420  helpint7[0]=step-1; /* step number */
421  helpint7[1]=readyflag; /* readyflag */
422  helpint7[2]=stepcount_coll+stepcount_collreader+stepcount_reader+stepcount_noreader; /* size */
423  helpint7[3]=stepcount_collreader+stepcount_reader; /* collsize */
424  helpint7[4]=stepcount_coll+stepcount_noreader; /* from_index */
425  helpint7[5]=stepcount_coll+stepcount_noreader+stepcount_collreader+stepcount_reader-1; /* to_index */
426  helpint7[6]=groupcounter++; /* unique Id of group */
427  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "define group #%d (step=%d, readyflag=%d, size=%d, collsize=%d, from=%d, to=%d) \n",
428  helpint7[6], helpint7[0], helpint7[1], helpint7[2], helpint7[3], helpint7[4], helpint7[5]));
429  }
430  sion_gendata->apidesc->bcastr_cb(helpint7, sion_gendata->comm_data_global, _SION_INT32, 7, 0);
431  readyflag=helpint7[1];
432 
433  /* create new data structure for storing info about group if task is acting in this group */
434  if(myrole!=SION_ROLE_NONE) {
435  buddy_info = (_sion_generic_buddy_info *) malloc(sizeof(_sion_generic_buddy_info));
436  if (buddy_info == NULL) {
437  free(buddies);
438  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_paropen_generic_buddy: cannot allocate temporary memory of size %lu (buddy_info), aborting ...\n",
439  (unsigned long) sizeof(_sion_generic_buddy_info)));
440  }
441  buddies->groups[buddies->numgroups]=buddy_info; buddies->numgroups++;
442  buddy_info->groupid=helpint7[6];
443  buddy_info->stepnum=helpint7[0];
444  buddy_info->rank=steprank;
445  buddy_info->size=helpint7[2];
446  buddy_info->commgroup=NULL; /* will be created later */
447  buddy_info->collsize=helpint7[3];
448  buddy_info->from_index=helpint7[4];
449  buddy_info->to_index=helpint7[5];
450  buddy_info->myrole=myrole;
451  buddy_info->bnum=b;
452  if( (myrole==SION_ROLE_READER) || (myrole==SION_ROLE_COLLECTOR_READER)) {
453  buddy_info->filelrank=lrank;
454  } else {
455  buddy_info->filelrank=-1;
456  }
457  buddy_info->filenum=file;
458  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "create group #%d (step=%d, rank=%d, size=%d, collsize=%d, from=%2d, to=%2d) (bnum=%2d file# %2d) with role %s \n",
459  buddy_info->groupid, buddy_info->stepnum, buddy_info->rank, buddy_info->size, buddy_info->collsize,
460  buddy_info->from_index, buddy_info->to_index, buddy_info->bnum, buddy_info->filenum, _sion_buddy_role_to_str(buddy_info->myrole)));
461 
462  } /* create group */
463  } /* (numreaderinthisfile>0) */
464  } /* if (file found on one of the lgroups) */
465  } /* end of loop over physical files of file set */
466  } /* end of loop over file sets (buddies) */
467 
468  if(!readyflag) {
469  /* some tasks could not find their data */
470  free(buddies);
471  free(buddy_fn);
472  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_paropen_generic_buddy: cannot open file, not all files available"));
473  }
474 
475  /* bcast max. number of steps */
476  sion_gendata->apidesc->bcastr_cb(&numsteps, sion_gendata->comm_data_global, _SION_INT32, 1, 0);
477  buddies->numsteps=numsteps;
478 
479  /* bcast max. number of groups */
480  if (sion_gendata->grank == 0) numgroups=groupcounter;
481  sion_gendata->apidesc->bcastr_cb(&numgroups, sion_gendata->comm_data_global, _SION_INT32, 1, 0);
482 
483  /* build commgroups */
484  for(step=0;step<numsteps;step++) {
485  /* search for group with this step */
486  group=-1;
487  for(b=0; ( (b<buddies->numgroups) && (group==-1) ); b++ ) {
488 
489  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "check group #%d of %d in stepnum=%d step=%d\n",b, buddies->numgroups, buddies->groups[b]->stepnum,step));
490  if (buddies->groups[b]->stepnum==step) group=b;
491  }
492 
493  if(group!=-1) {
494  /* create group for step */
495  buddy_info=buddies->groups[group];
496  rc=sion_gendata->apidesc->create_lcg_cb(&buddy_info->commgroup,sion_gendata->comm_data_global,
497  sion_gendata->grank,sion_gendata->gsize,
498  buddy_info->rank,buddy_info->size,
499  buddy_info->groupid,numgroups);
500  DPRINTFP((256, DFUNCTION, _SION_DEFAULT_RANK, "COMM_created active [grank=%2d of %2d, group=%2d of %2d, lrank=%2d of %2d]\n",
501  sion_gendata->grank,sion_gendata->gsize, buddy_info->groupid,numgroups, buddy_info->rank,buddy_info->size));
502  } else {
503  /* nothing to do in this step, create dummy comm */
504  void *dummycommgroup=NULL;
505  rc=sion_gendata->apidesc->create_lcg_cb(&dummycommgroup,sion_gendata->comm_data_global,
506  sion_gendata->grank,sion_gendata->gsize,
507  0,1,
508  -1,numgroups);
509  DPRINTFP((256, DFUNCTION, _SION_DEFAULT_RANK, "COMM_created dummy [grank=%2d of %2d, group=%2d of %2d, lrank=%2d of %2d]\n",
510  sion_gendata->grank,sion_gendata->gsize,
511  -1,numgroups,
512  0,1 ));
513  }
514 
515 
516  if(group!=-1) {
517  /* open file */
518  buddy_info=buddies->groups[group];
519  buddies->currentgroup=group;
520 
521  if(buddy_info->bnum==-1) sprintf(buddy_fn,"%s", fname);
522  else sprintf(buddy_fn,"%s_BUDDY_%02d", fname,buddy_info->bnum);
523  nfname=(sion_apidesc->get_multi_filename_cb?sion_apidesc->get_multi_filename_cb:_sion_get_multi_filename)(buddy_fn,buddy_info->filenum);
524 
525  DPRINTFP((256, DFUNCTION, _SION_DEFAULT_RANK, "open file for group #%d %s [step=%d grank=%2d of %2d, lrank=%2d of %2d filelrank=%2d]\n",
526  buddy_info->groupid,nfname,buddy_info->stepnum,
527  sion_gendata->grank,sion_gendata->gsize, buddy_info->rank,buddy_info->size,buddy_info->filelrank));
528 
529  /* test if tsk is a reader, a task is only in one step a reader */
530  if( (buddy_info->myrole == SION_ROLE_READER)
531  || (buddy_info->myrole == SION_ROLE_COLLECTOR_READER)) {
532  buddy_info->sid=sid; /* use already defined sid, this will be the master data structure */
533  rc=_sion_paropen_generic_one_file(buddy_info->sid, nfname, flags_store, prefix,
534  &sion_gendata->numfiles, &buddy_info->filenum,
535  chunksize, fsblksize,
536  buddy_info->rank, buddy_info->size, &sion_gendata->grank,
537  _SION_INTERNAL_FLAG_BUDDY_READ, NULL, sion_gendata,
538  buddies);
539 
540  /* store internal buddy data structure */
541  /* test sid and get internal data structure */
542  if ((rc<0) || (sid<0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
543  free(buddy_fn);
544  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_paropen_generic_buddy: invalid sion_filedesc %d", sid));
545  }
546 
547  /* store additional data */
548  sion_filedesc->buddies=buddies;
549 
550  } else {
551  sion_int64 dummy_chunksize;
552  sion_int32 dummy_fsblksize;
553  buddy_info->sid = _sion_newvcd(NULL,SION_FILEDESCRIPTOR); /* create a new sid */
554  rc=_sion_paropen_generic_one_file(buddy_info->sid, nfname, flags_store, prefix,
555  &sion_gendata->numfiles, &buddy_info->filenum,
556  &dummy_chunksize, &dummy_fsblksize,
557  buddy_info->rank, buddy_info->size, &sion_gendata->grank,
558  _SION_INTERNAL_FLAG_BUDDY_READ, NULL, sion_gendata,
559  buddies);
560 
561  }
562 
563  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDYO afteropen [grank=%2d step=%d] rc=%d\n",sion_gendata->grank,step,rc));
564  free(nfname);
565 
566  } else {
567  /* nothing to do in this step */
568  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDYO no-op [grank=%2d]\n",sion_gendata->grank));
569  }
570 
571  /* barrier between steps */
572  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDYO beforegbarrier [grank=%2d]\n",sion_gendata->grank));
573  sion_apidesc->barrier_cb(sion_gendata->comm_data_global);
574  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDYO aftergbarrier [grank=%2d]\n",sion_gendata->grank));
575 
576 
577  } /* for steps */
578 
579 
580  } else {
581  free(buddies);
582  free(buddy_fn);
583  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_paropen_generic_buddy: unknown file mode"));
584  }
585  /* 'buddies' is still used later and should not be freed here. */
586  /* free(buddies); */
587  free(buddy_fn);
588  sion_apidesc->barrier_cb(sion_gendata->comm_data_global);
589 
590 
591  return(rc);
592 }
593 #undef DFUNCTION
594 
595 
607 #define DFUNCTION "_sion_parclose_generic_buddy"
608 int _sion_parclose_generic_buddy(int sid,
609  int rank,
610  int ntasks,
611  int mapping_size,
612  sion_int32 *mapping,
613  _sion_generic_gendata *sion_gendata) {
614  int rc=SION_SUCCESS;
615  _sion_filedesc *sion_filedesc;
616  /* _sion_generic_apidesc *sion_apidesc; */
617  _sion_generic_buddy *buddies, *buddyptr;
618  int b_mapping_size=0,group,step;
619  sion_int32 *b_mapping=NULL;
620  _sion_generic_buddy_info *buddy_info;
621 
622  int b, pass;
623 
624  /* obtain pointers to internal data structures */
625  if ( (sid<0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
626  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_parclose_generic_buddy: invalid sion_filedesc %d", sid));
627  }
628  /* sion_apidesc=sion_gendata->apidesc; */
629  buddies=sion_filedesc->buddies;
630 
631 
632  if (sion_filedesc->mode == SION_FILEMODE_WRITE) {
633 
634  /* close buddy files */
635  for(b=0;b<sion_filedesc->buddylevel;b++) {
636  buddyptr=&buddies[b];
637 
638 
639  /* collect mapping */
640  _sion_generic_collect_mapping_buddy(buddyptr, sion_gendata, &b_mapping_size, &b_mapping);
641 
642 
643  /* close files */
644  for(pass=1;pass<=_SION_BW_SCHED_NUM_PASSES;pass++) {
645 
646  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDYC pass=%d [grank=%2d] op=%d\n",pass,sion_gendata->grank,
647  _sion_buddy_bwsched(buddyptr->buddy_send.groupnum, sion_gendata->numfiles, pass)));
648 
649  switch (_sion_buddy_bwsched(buddyptr->buddy_send.groupnum, sion_gendata->numfiles, pass)) {
650  case _SION_BW_SCHED_ACTIONA:
651  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDYc call parallel close COLL [gendata: grank=%2d, group=%d of %d, lrank=%d of %d]\n",
652  sion_gendata->grank, buddyptr->buddy_coll.groupnum,sion_gendata->numfiles,
653  buddyptr->buddy_coll.rank, buddyptr->buddy_coll.size));
654  _sion_parclose_generic(buddyptr->buddy_coll.sid, buddyptr->buddy_coll.rank, buddyptr->buddy_coll.size,
655  b_mapping_size, b_mapping, _SION_INTERNAL_FLAG_BUDDY_COLL, sion_gendata, buddyptr );
656  break;
657  case _SION_BW_SCHED_ACTIONB:
658  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDYc call parallel close SEND [gendata: grank=%2d, group=%d of %d, lrank=%d of %d]\n",
659  sion_gendata->grank, buddyptr->buddy_send.groupnum,sion_gendata->numfiles,
660  buddyptr->buddy_send.rank, buddyptr->buddy_send.size));
661  _sion_parclose_generic(buddyptr->buddy_send.sid, buddyptr->buddy_send.rank, buddyptr->buddy_send.size,
662  0, NULL, _SION_INTERNAL_FLAG_BUDDY_SEND, sion_gendata, buddyptr );
663  break;
664  default:
665  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDYC no-op [grank=%2d]\n",sion_gendata->grank));
666  break;
667  } /* switch */
668  } /* for pass */
669  } /* for buddies */
670 
671 
672  _SION_SAFE_FREE(b_mapping, NULL);
673  _SION_SAFE_FREE(buddies, NULL);
674 
675 
676  /* STEP: close normal files */
677  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "call parallel close of %d files, sid=%d\n",
678  sion_gendata->numfiles, sid));
679  rc = _sion_parclose_generic( sid, sion_filedesc->rank, sion_filedesc->ntasks, mapping_size, mapping, _SION_INTERNAL_FLAG_NORMAL,
680  sion_gendata, NULL );
681  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "leave parallel close of %d files in #tasks=%d globalrank=%d\n", sion_gendata->numfiles,
682  sion_gendata->lsize, sion_gendata->grank));
683 
684  } else if (sion_filedesc->mode == SION_FILEMODE_READ) {
685 
686  /* loop over all groups */
687  for(step=0;step<buddies->numsteps;step++) {
688  /* search for group with this step */
689  group=-1;
690  for(b=0; ( (b<buddies->numgroups) && (group==-1) ); b++ ) {
691 
692  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "check group #%d of %d %d==%d %x\n",b, buddies->numgroups, buddies->groups[b]->stepnum,step, buddies->groups[b]));
693  if (buddies->groups[b]->stepnum==step) group=b;
694  }
695  buddy_info=buddies->groups[group];
696 
697  if(group!=-1) {
698  /* call parclose for this group */
699  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "call parallel close of %d files, sid=%d\n",
700  sion_gendata->numfiles, sid));
701  buddies->currentgroup=group;
702  rc = _sion_parclose_generic( buddy_info->sid, buddy_info->rank,buddy_info->size, -1, NULL, _SION_INTERNAL_FLAG_BUDDY_READ,
703  sion_gendata, buddies );
704  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "leave parallel close of %d files in #tasks=%d globalrank=%d\n", sion_gendata->numfiles,
705  sion_gendata->lsize, sion_gendata->grank));
706  }
707  } /* step */
708 
709 
710  } else {
711  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_parclose_generic_buddy: unknown file mode"));
712  }
713 
714 
715  return(rc);
716 }
717 #undef DFUNCTION
718 
719 
728 #define DFUNCTION "_sion_coll_fwrite_buddy"
729 int _sion_coll_fwrite_buddy(const void *data,
730  size_t size,
731  size_t nitems,
732  int sid,
733  _sion_generic_gendata *sion_gendata ) {
734  int rc=SION_SUCCESS;
735  _sion_filedesc *sion_filedesc,*sion_filedesc_coll,*sion_filedesc_send;
736  _sion_generic_apidesc *sion_apidesc;
737  _sion_generic_buddy *buddies, *buddyptr;
738  sion_int64 spec[2], ownnewposition;
739  int b, pass, collector=0;
740 
741  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "enter parallel write buddy\n"));
742 
743  /* obtain pointers to internal data structures */
744  if ( (sid<0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
745  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_coll_fwrite_buddy: invalid sion_filedesc %d", sid));
746  }
747  sion_apidesc=sion_gendata->apidesc;
748  buddies=sion_filedesc->buddies;
749 
750  /* buddy files */
751  for(b=0;b<sion_filedesc->buddylevel;b++) {
752  buddyptr=&buddies[b];
753 
754  /* get pointer to data structures */
755  if ( (buddyptr->buddy_coll.sid<0) || (_sion_vcdtype(buddyptr->buddy_coll.sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc_coll = _sion_vcdtovcon(buddyptr->buddy_coll.sid))) {
756  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_coll_fwrite_buddy: invalid sion_filedesc %d", buddyptr->buddy_coll.sid));
757  }
758  if ( (buddyptr->buddy_send.sid<0) || (_sion_vcdtype(buddyptr->buddy_send.sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc_send = _sion_vcdtovcon(buddyptr->buddy_send.sid))) {
759  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_coll_fwrite_buddy: invalid sion_filedesc %d", buddyptr->buddy_send.sid));
760  }
761 
762 
763  /* open files */
764  for(pass=1;pass<=_SION_BW_SCHED_NUM_PASSES;pass++) {
765 
766  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDYw pass=%d [grank=%2d] op=%d\n",pass,sion_gendata->grank,
767  _sion_buddy_bwsched(buddyptr->buddy_send.groupnum, sion_gendata->numfiles, pass)));
768 
769  switch (_sion_buddy_bwsched(buddyptr->buddy_send.groupnum, sion_gendata->numfiles, pass)) {
770  case _SION_BW_SCHED_ACTIONA:
771  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDYw call parallel write COLL [gendata: grank=%2d, group=%d of %d, lrank=%d of %d] %d..%d\n",
772  sion_gendata->grank, buddyptr->buddy_coll.groupnum,sion_gendata->numfiles,
773  buddyptr->buddy_coll.rank, buddyptr->buddy_coll.size,buddyptr->buddy_coll.from_index,buddyptr->buddy_coll.to_index));
774  spec[0]=0;spec[1]=0;
775  if(sion_filedesc_coll->rank == collector) {
776  ownnewposition=sion_filedesc_coll->currentpos;
777  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDYw call parallel write COLL currentpos=%d\n",(int) sion_filedesc_coll->currentpos));
778  }
779  rc = sion_apidesc->gather_execute_cb(data,spec,2, sion_filedesc_coll->fsblksize,
780  buddyptr->buddy_coll.commgroup,collector,buddyptr->buddy_coll.from_index,buddyptr->buddy_coll.to_index,
781  buddyptr->buddy_coll.sid, _sion_generic_collective_process_write);
782  if(sion_filedesc_coll->rank == collector) {
783  _sion_file_flush(sion_filedesc_coll->fileptr);
784  _sion_file_set_position(sion_filedesc_coll->fileptr,ownnewposition);sion_filedesc_coll->currentpos=ownnewposition;
785  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDYw call parallel write COLL currentpos=%d\n",(int) sion_filedesc_coll->currentpos));
786  }
787  break;
788  case _SION_BW_SCHED_ACTIONB:
789  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDYw call parallel write SEND [gendata: grank=%2d, group=%d of %d, lrank=%d of %d] %d..%d\n",
790  sion_gendata->grank, buddyptr->buddy_send.groupnum,sion_gendata->numfiles,
791  buddyptr->buddy_send.rank, buddyptr->buddy_send.size,buddyptr->buddy_send.from_index,buddyptr->buddy_send.to_index));
792 
793  /* ensure free space for this block */
794  if(sion_ensure_free_space(buddyptr->buddy_send.sid,size*nitems) != SION_SUCCESS) {
795  _sion_errorprint(SION_SIZE_NOT_VALID,_SION_ERROR_RETURN,"could not ensure free space for this block, returning %d ...\n", sid);
796  spec[0]=spec[1]=-1; /* signaling error */
797  } else {
798  spec[0]=sion_filedesc_send->currentpos;
799  spec[1]=size*nitems;
800  }
801  rc = sion_apidesc->gather_execute_cb(data,spec,2, sion_filedesc_send->fsblksize,
802  buddyptr->buddy_send.commgroup,collector,buddyptr->buddy_send.from_index,buddyptr->buddy_send.to_index,
803  buddyptr->buddy_send.sid, _sion_generic_collective_process_write);
804  sion_filedesc_send->currentpos+=size*nitems;
805  break;
806  default:
807  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDYw no-op [grank=%2d]\n",sion_gendata->grank));
808  break;
809  } /* switch */
810  } /* for pass */
811  } /* for buddies */
812 
813 
814  /* sion_apidesc->barrier_cb(sion_gendata->comm_data_global); */
815 
816  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "leave parallel write buddy\n"));
817 
818 
819 
820  return(rc);
821 }
822 #undef DFUNCTION
823 
824 
833 #define DFUNCTION "_sion_coll_fread_buddy"
834 int _sion_coll_fread_buddy( void *data, size_t size, size_t nitems, int sid) {
835  _sion_filedesc *sion_filedesc,*b_sion_filedesc;
836  _sion_generic_gendata *sion_gendata;
837  _sion_generic_apidesc *sion_apidesc;
838  sion_int64 bread=-1, spec[2], ownnewposition, items_read = 0;
839  int rc_own=SION_STD_SUCCESS,rc_cb=SION_STD_SUCCESS;
840  int collector, firstsender, lastsender, step, b, group;
841  _sion_generic_buddy *buddies;
842  _sion_generic_buddy_info *buddy_info;
843 
844  /* obtain pointers to internal data structures */
845  if ( (sid<0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
846  return(_sion_errorprint(SION_SIZE_NOT_VALID,_SION_ERROR_RETURN,"_sion_coll_fread_buddy: invalid sion_filedesc %d", sid));
847  }
848  DPRINTFP((4, DFUNCTION, _SION_DEFAULT_RANK, "enter usecoll=%d collector=%d collsize=%d (%d tasks, %d files)\n",
849  sion_filedesc->usecoll, sion_filedesc->collector, sion_filedesc->collsize, sion_filedesc->ntasks,sion_filedesc->nfiles));
850 
851  sion_gendata=sion_filedesc->dataptr;
852  sion_apidesc=sion_gendata->apidesc;
853  buddies=sion_filedesc->buddies;
854 
855  /* needed for avoiding subsequent non-collective calls */
856  sion_filedesc->collcmdused=1;
857 
858  /* check collsize */
859  if (sion_filedesc->collsize<=0) {
860  return(_sion_errorprint(SION_SIZE_NOT_VALID,_SION_ERROR_RETURN,"_sion_coll_fread_buddy: collsize=%d <= 0, returning ...\n",
861  (int) sion_filedesc->collsize));
862  }
863 
864 
865  /* loop over all groups */
866  for(step=0;step<buddies->numsteps;step++) {
867  /* search for group with this step */
868  group=-1;
869  for(b=0; ( (b<buddies->numgroups) && (group==-1) ); b++ ) {
870 
871  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "check group #%d of %d %d==%d %x\n",b, buddies->numgroups, buddies->groups[b]->stepnum,step, buddies->groups[b]));
872  if (buddies->groups[b]->stepnum==step) group=b;
873  }
874 
875  if(group!=-1) {
876  /* activity needed for this group */
877 
878  buddy_info=buddies->groups[group];
879 
880  if ( (buddy_info->sid<0) || (_sion_vcdtype(buddy_info->sid) != SION_FILEDESCRIPTOR) || !(b_sion_filedesc = _sion_vcdtovcon(buddy_info->sid))) {
881  return(_sion_errorprint(SION_SIZE_NOT_VALID,_SION_ERROR_RETURN,"_sion_coll_fread_buddy: invalid sion_filedesc %d", buddy_info->sid));
882  }
883 
884  /* parameter of callback function */
885  collector=0;
886  firstsender=buddy_info->from_index;
887  lastsender=buddy_info->to_index;
888 
889 
890  /* check input parameter and position in file */
891  if( (buddy_info->myrole == SION_ROLE_READER)
892  || (buddy_info->myrole == SION_ROLE_COLLECTOR_READER)) {
893 
894  /* ensure to be at the beginning of the right block */
895  if(size*nitems>0) {
896  if(sion_feof(buddy_info->sid)) {
897  _sion_errorprint(SION_SIZE_NOT_VALID,_SION_ERROR_RETURN,"early eof found for this block, returning %d ...\n", buddy_info->sid);
898  spec[0]=spec[1]=-1; /* signaling that no data is requested */
899  } else {
900  /* specification of location in file */
901  spec[0]=sion_filedesc->currentpos;
902  spec[1]=size*nitems;
903  }
904  } else {
905  /* signaling that no data is requested */
906  spec[0]=spec[1]=-1;
907  }
908 
909 
910  }
911 
912 
913  /* read own part */
914  if( (buddy_info->myrole == SION_ROLE_COLLECTOR_READER) ) {
915  rc_own=_sion_generic_collective_process_read(data,spec,buddy_info->sid);
916  firstsender++; /* must not read again */
917  }
918  /* save own position before reading at other positions */
919  if( (buddy_info->myrole == SION_ROLE_COLLECTOR)
920  || (buddy_info->myrole == SION_ROLE_COLLECTOR_READER)) {
921  ownnewposition=sion_filedesc->currentpos;
922  }
923 
924 
925  /* read parts and scatter these to sender tasks via callback function */
926  if(!sion_apidesc->execute_scatter_cb ) {
927  return(_sion_errorprint(SION_SIZE_NOT_VALID,_SION_ERROR_RETURN,
928  "_sion_coll_fread_buddy: API %s not correctly initalized, collective I/O calls missing, aborting",sion_apidesc->name));
929  }
930  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "call execute_gather #%d (step=%d, rank=%d, size=%d, collsize=%d, from=%2d, to=%2d) (bnum=%2d file# %2d) with role %s \n",
931  buddy_info->groupid, buddy_info->stepnum, buddy_info->rank, buddy_info->size, buddy_info->collsize,
932  buddy_info->from_index, buddy_info->to_index, buddy_info->bnum, buddy_info->filenum, _sion_buddy_role_to_str(buddy_info->myrole)));
933 
934  rc_cb=sion_apidesc->execute_scatter_cb(data,spec,2, b_sion_filedesc->fsblksize,
935  buddy_info->commgroup,collector,firstsender,lastsender,buddy_info->sid,
936  _sion_generic_collective_process_read);
937 
938 
939 
940  /* set own position to end of own block read in this call */
941  if( (buddy_info->myrole == SION_ROLE_COLLECTOR)
942  || (buddy_info->myrole == SION_ROLE_COLLECTOR_READER)) {
943  _sion_file_flush(b_sion_filedesc->fileptr);
944  _sion_file_set_position(b_sion_filedesc->fileptr,ownnewposition);b_sion_filedesc->currentpos=ownnewposition;
945  }
946 
947  /* set file pointer in data structure and in file if it is exported and can be used without control of SIONlib */
948  if(buddy_info->myrole == SION_ROLE_READER) {
949  b_sion_filedesc->currentpos+=size*nitems;
950  if(b_sion_filedesc->fileptr_exported) {
951  _sion_file_set_position(b_sion_filedesc->fileptr,b_sion_filedesc->currentpos);
952  }
953  }
954 
955  if( (buddy_info->myrole == SION_ROLE_READER)
956  || (buddy_info->myrole == SION_ROLE_COLLECTOR_READER)) {
957  if( (rc_own == SION_STD_SUCCESS) && (rc_cb == SION_STD_SUCCESS) ) {
958  bread=size*nitems;
959  } else {
960  bread=0;
961  }
962  items_read = size ? bread / size : 0;
963  }
964 
965  } /* froup != -1 */
966 
967  /* barrier between steps */
968  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDYO beforegbarrier [grank=%2d]\n",sion_gendata->grank));
969  sion_apidesc->barrier_cb(sion_gendata->comm_data_global);
970  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "BUDDYO aftergbarrier [grank=%2d]\n",sion_gendata->grank));
971 
972  } /* for step */
973 
974  DPRINTFP((4, DFUNCTION, _SION_DEFAULT_RANK, "leave usecoll=%d collector=%d collsize=%d (%d tasks, %d files) rc=%d\n",
975  sion_filedesc->usecoll, sion_filedesc->collector, sion_filedesc->collsize, sion_filedesc->ntasks,sion_filedesc->nfiles,items_read));
976 
977  return items_read;
978 
979 }
980 #undef DFUNCTION
981 
982 #define DFUNCTION "_sion_buddy_map"
983 int _sion_buddy_map(
984  _sion_generic_gendata *sion_gendata,
985  int capability,
986  int buddy_idx,
987  _sion_generic_buddy_info *buddy_send,
988  _sion_generic_buddy_info *buddy_coll ) {
989  int rc=SION_SUCCESS;
990  int tmpsize,t,g, g_map, p, p_map, n, n_map, orig, distance,distance_1step,pass;
991  int *size_per_group = NULL, *group_map_orig_to_new, *group_map_new_to_orig, mynewgroupnr;
992  sion_int32 helpint2[2];
993  sion_int32 *tasktogroup = NULL;
994  sion_int32 *tmpintfield1 = NULL;
995  int comm_send_rank, comm_send_size, comm_send_grpnum;
996  int comm_coll_rank, comm_coll_size, comm_coll_grpnum;
997  void *dummycommgroup=NULL;
998 
999  DPRINTFP((256, DFUNCTION, _SION_DEFAULT_RANK, "buddy_idx=%d capability=%d [gendata: grank=%d of %d, group=%d of %d, lrank=%d of %d]\n",
1000  buddy_idx, capability,
1001  sion_gendata->grank, sion_gendata->gsize,
1002  sion_gendata->filenumber, sion_gendata->numfiles,
1003  sion_gendata->lrank, sion_gendata->lsize));
1004 
1005  distance=buddy_idx; /* higher level buddy CP: groups will be remapped to d=1 buddy CP */
1006  distance_1step=1;
1007 
1008  /* allocate some fields */
1009  if(sion_gendata->grank==0) {
1010 
1011  tmpsize=1*sion_gendata->gsize;
1012  tasktogroup = (sion_int32 *) malloc(tmpsize * sizeof(sion_int32));
1013  if (tasktogroup == NULL) {
1014  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_buddy_map: cannot allocate temporary memory of size %lu (tasktogroup), aborting ...\n",
1015  (unsigned long) tmpsize * sizeof(sion_int32)));
1016  }
1017 
1018  tmpsize=2*sion_gendata->gsize;
1019  tmpintfield1 = (sion_int32 *) malloc(tmpsize * sizeof(sion_int32));
1020  if (tmpintfield1 == NULL) {
1021  free(tasktogroup);
1022  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_buddy_map: cannot allocate temporary memory of size %lu (tmpintfield1), aborting ...\n",
1023  (unsigned long) tmpsize * sizeof(sion_int32)));
1024  }
1025 
1026  size_per_group = (int *) malloc(sion_gendata->numfiles * sizeof(int));
1027  if (size_per_group == NULL) {
1028  free(tasktogroup);
1029  free(tmpintfield1);
1030  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_buddy_map: cannot allocate temporary memory of size %lu (size_per_group), aborting ...\n",
1031  (unsigned long) sion_gendata->numfiles * sizeof(int)));
1032  }
1033 
1034  }
1035 
1036  /* on all tasks */
1037  group_map_orig_to_new = (int *) malloc(sion_gendata->numfiles * sizeof(int));
1038  if (group_map_orig_to_new == NULL) {
1039  free(tasktogroup);
1040  _SION_SAFE_FREE(size_per_group, NULL);
1041  free(tmpintfield1);
1042  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_buddy_map: cannot allocate temporary memory of size %lu (group_map_orig_to_new), aborting ...\n",
1043  (unsigned long) sion_gendata->numfiles * sizeof(int)));
1044  }
1045 
1046  group_map_new_to_orig = (int *) malloc(sion_gendata->numfiles * sizeof(int));
1047  if (group_map_new_to_orig == NULL) {
1048  _SION_SAFE_FREE(size_per_group, NULL);
1049  free(group_map_orig_to_new);
1050  free(tasktogroup);
1051  free(tmpintfield1);
1052  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_buddy_map: cannot allocate temporary memory of size %lu (group_map_new_to_orig), aborting ...\n",
1053  (unsigned long) sion_gendata->numfiles * sizeof(int)));
1054  }
1055 
1056  /* Step1: gather group number */
1057  helpint2[0]=sion_gendata->filenumber;
1058  sion_gendata->apidesc->gatherr_cb(helpint2, tasktogroup, sion_gendata->comm_data_global, _SION_INT32,1,0);
1059 
1060 
1061  /* Step2: gather local size */
1062  helpint2[0]=sion_gendata->lsize;
1063  helpint2[1]=capability;
1064  sion_gendata->apidesc->gatherr_cb(helpint2, tmpintfield1, sion_gendata->comm_data_global, _SION_INT32,2,0);
1065  if(sion_gendata->grank==0) {
1066  for(t=0;t<sion_gendata->gsize;t++) {
1067  DPRINTFP((256, DFUNCTION, _SION_DEFAULT_RANK, "task-map --> t=%2d grpnr=%2d lsize=%2d capability=%d\n",
1068  t,tasktogroup[t],tmpintfield1[2*t+0],tmpintfield1[2*t+1]));
1069  }
1070  /* --> tasktogroup[t] = groupnr, tmpintfield1[t][0] = lsize tmpintfield1[t][1] = capability */
1071  }
1072 
1073  /* Step2: build vector with size info per group and group map */
1074  if(sion_gendata->grank==0) {
1075  for(t=0;t<sion_gendata->gsize;t++) {
1076  size_per_group[tasktogroup[t]] = tmpintfield1[2*t+0];
1077  }
1078  }
1079 
1080  for(g=0;g<sion_gendata->numfiles;g++) {
1081  orig=(g*distance) % sion_gendata->numfiles;
1082  group_map_orig_to_new[orig]=g;
1083  group_map_new_to_orig[g]=orig;
1084  }
1085 
1086  for(g=0;g<sion_gendata->numfiles;g++) {
1087  DPRINTFP((256, DFUNCTION, _SION_DEFAULT_RANK, "grp-map --> g=%2d->%2d\n",g,group_map_orig_to_new[g]));
1088  }
1089 
1090 
1091  /* Step3: compute send group */
1092  if(sion_gendata->grank==0) {
1093  for(t=0;t<sion_gendata->gsize;t++) {
1094  g=tasktogroup[t];
1095  g_map=group_map_orig_to_new[g];
1096  p_map=(g_map-distance_1step + sion_gendata->numfiles) % sion_gendata->numfiles;
1097  p=group_map_new_to_orig[p_map];
1098  tmpintfield1[2*t+0] = g_map;
1099  tmpintfield1[2*t+1] = size_per_group[p];
1100  DPRINTFP((256, DFUNCTION, _SION_DEFAULT_RANK, "comm-send --> t=%2d grpnr=%2d grpmap=%2d prevgr=%2d prevgrmap=%2d prev_lsize=%2d\n",
1101  t, g, tmpintfield1[2*t+0], p, p_map, tmpintfield1[2*t+1]));
1102  }
1103  /* --> tmpintfield1[t][0] = own_groupnr, tmpintfield1[t][1] = lsize of prev_group */
1104  }
1105 
1106  /* Step4: scatter info about send group */
1107  sion_gendata->apidesc->scatterr_cb(tmpintfield1, helpint2, sion_gendata->comm_data_global, _SION_INT32,2,0);
1108 
1109  /* Step5: compute ranks for send group */
1110  mynewgroupnr=comm_send_grpnum=helpint2[0];
1111  buddy_send->rank=comm_send_rank=helpint2[1]+sion_gendata->lrank;
1112  buddy_send->size=comm_send_size=helpint2[1]+sion_gendata->lsize;
1113  buddy_send->collsize=sion_gendata->lsize;
1114  buddy_send->groupnum=mynewgroupnr;
1115  buddy_send->filenum=group_map_new_to_orig[mynewgroupnr];
1116  buddy_send->from_index=helpint2[1];
1117  buddy_send->to_index=helpint2[1]+sion_gendata->lsize-1;
1118  DPRINTFP((256, DFUNCTION, _SION_DEFAULT_RANK, "COMM_SEND d=%d grpnum=%2d lrank=%2d lsize=%2d mynewgroupnr=%2d collsize=%2d %d..%d fnum=%d\n",
1119  distance,comm_send_grpnum,comm_send_rank,comm_send_size,mynewgroupnr,
1120  buddy_send->collsize,buddy_send->from_index,buddy_send->to_index,
1121  buddy_send->filenum));
1122 
1123  /* Step6: compute coll group */
1124  if(sion_gendata->grank==0) {
1125  for(t=0;t<sion_gendata->gsize;t++) {
1126  g=tasktogroup[t];
1127  g_map=group_map_orig_to_new[g];
1128  n_map=(g_map+distance_1step) % sion_gendata->numfiles;
1129  n=group_map_new_to_orig[n_map];
1130  tmpintfield1[2*t+0] = n_map;
1131  tmpintfield1[2*t+1] = size_per_group[n];
1132  DPRINTFP((256, DFUNCTION, _SION_DEFAULT_RANK, "comm-coll --> t=%2d grpnr=%2d grpmap=%2d nextgr=%2d nextgrmap=%2d next_lsize=%2d\n",
1133  t, g, g_map, n, tmpintfield1[2*t+0], tmpintfield1[2*t+1]));
1134  }
1135  /* --> tmpintfield1[t][0] = next_groupnr_map, tmpintfield1[t][0] = lsize of next_group */
1136  }
1137 
1138  /* Step7: scatter info about coll group */
1139  sion_gendata->apidesc->scatterr_cb(tmpintfield1, helpint2, sion_gendata->comm_data_global, _SION_INT32,2,0);
1140 
1141  /* Step8: compute ranks for coll group */
1142  comm_coll_grpnum=helpint2[0];
1143  buddy_coll->rank=comm_coll_rank=sion_gendata->lrank;
1144  buddy_coll->size=comm_coll_size=sion_gendata->lsize+helpint2[1];
1145  buddy_coll->collsize=helpint2[1];
1146  buddy_coll->groupnum=comm_coll_grpnum;
1147  buddy_coll->filenum=group_map_new_to_orig[comm_coll_grpnum];
1148  buddy_coll->from_index=sion_gendata->lsize;
1149  buddy_coll->to_index=sion_gendata->lsize+helpint2[1]-1;
1150  DPRINTFP((256, DFUNCTION, _SION_DEFAULT_RANK, "COMM_COLL d=%d grpnum=%2d lrank=%2d lsize=%2d collsize=%2d %d..%d fnum=%d\n",
1151  distance,comm_coll_grpnum,comm_coll_rank,comm_coll_size,
1152  buddy_coll->collsize,buddy_coll->from_index,buddy_coll->to_index,
1153  buddy_coll->filenum));
1154 
1155  /* Step9: create local communicators for send/coll */
1156 
1157  for(pass=1;pass<=_SION_BW_SCHED_NUM_PASSES;pass++) {
1158  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "pass=%d [grank=%2d] op=%d\n",pass,sion_gendata->grank,
1159  _sion_buddy_bwsched(mynewgroupnr, sion_gendata->numfiles, pass)));
1160 
1161  switch (_sion_buddy_bwsched(mynewgroupnr, sion_gendata->numfiles, pass)) {
1162  case _SION_BW_SCHED_ACTIONA:
1163  rc=sion_gendata->apidesc->create_lcg_cb(&buddy_coll->commgroup,sion_gendata->comm_data_global,
1164  sion_gendata->grank,sion_gendata->gsize,
1165  comm_coll_rank,comm_coll_size,
1166  comm_coll_grpnum,sion_gendata->numfiles);
1167  DPRINTFP((256, DFUNCTION, _SION_DEFAULT_RANK, "COMM_created comm_coll (d=%1d, p=%1d) [gendata: mygrp=%2d grank=%2d of %2d, group=%2d of %2d, lrank=%2d of %2d]\n",
1168  distance,pass,mynewgroupnr,sion_gendata->grank,sion_gendata->gsize,
1169  comm_coll_grpnum,sion_gendata->numfiles,
1170  comm_coll_rank,comm_coll_size ));
1171  break;
1172  case _SION_BW_SCHED_ACTIONB:
1173  rc=sion_gendata->apidesc->create_lcg_cb(&buddy_send->commgroup,sion_gendata->comm_data_global,
1174  sion_gendata->grank,sion_gendata->gsize,
1175  comm_send_rank,comm_send_size,
1176  comm_send_grpnum,sion_gendata->numfiles);
1177  DPRINTFP((256, DFUNCTION, _SION_DEFAULT_RANK, "COMM_created comm_send (d=%1d, p=%1d) [gendata: mygrp=%2d grank=%2d of %2d, group=%2d of %2d, lrank=%2d of %2d]\n",
1178  distance,pass,mynewgroupnr,sion_gendata->grank,sion_gendata->gsize,
1179  comm_send_grpnum,sion_gendata->numfiles,
1180  comm_send_rank,comm_send_size ));
1181  break;
1182  case _SION_BW_SCHED_NOACTION:
1183  rc=sion_gendata->apidesc->create_lcg_cb(&dummycommgroup,sion_gendata->comm_data_global,
1184  sion_gendata->grank,sion_gendata->gsize,
1185  0,1,
1186  -1,sion_gendata->numfiles);
1187  DPRINTFP((256, DFUNCTION, _SION_DEFAULT_RANK, "COMM_created dummy (d=%1d, p=%1d) [gendata: mygrp=%2d grank=%2d of %2d, group=%2d of %2d, lrank=%2d of %2d]\n",
1188  distance,pass,mynewgroupnr,sion_gendata->grank,sion_gendata->gsize,
1189  -1,sion_gendata->numfiles,0,1 ));
1190  break;
1191 
1192  default: break;
1193  }
1194  }
1195 
1196  /* free fields */
1197  if(sion_gendata->grank==0) {
1198  free(tasktogroup);
1199  free(tmpintfield1);
1200  free(size_per_group);
1201  }
1202  free(group_map_new_to_orig);
1203  free(group_map_orig_to_new);
1204 
1205  return(rc);
1206 }
1207 #undef DFUNCTION
1208 
1209  /* pass=1..3 */
1210 #define DFUNCTION "_sion_buddy_bwsched"
1211 int _sion_buddy_bwsched(int groupnr, int numgroups, int pass) {
1212  int res=_SION_BW_SCHED_NOACTION;
1213  if(numgroups%2==0) { /* #groups even */
1214  if(groupnr%2==0) { /* groupnr even */
1215  if(pass==1) res=_SION_BW_SCHED_ACTIONA;
1216  if(pass==2) res=_SION_BW_SCHED_ACTIONB;
1217  } else { /* groupnr even */
1218  if(pass==1) res=_SION_BW_SCHED_ACTIONB;
1219  if(pass==2) res=_SION_BW_SCHED_ACTIONA;
1220  }
1221  } else {
1222  if(groupnr%2==0) { /* groupnr even */
1223  if((pass==1) && (groupnr != (numgroups-1))) res=_SION_BW_SCHED_ACTIONA;
1224  if((pass==2) && (groupnr != 0)) res=_SION_BW_SCHED_ACTIONB;
1225  if((pass==3) && (groupnr == 0)) res=_SION_BW_SCHED_ACTIONB;
1226  if((pass==3) && (groupnr == (numgroups-1))) res=_SION_BW_SCHED_ACTIONA;
1227  } else { /* groupnr even */
1228  if(pass==1) res=_SION_BW_SCHED_ACTIONB;
1229  if(pass==2) res=_SION_BW_SCHED_ACTIONA;
1230  }
1231  }
1232  return(res);
1233 }
1234 #undef DFUNCTION
1235 
1240 #define DFUNCTION "_sion_generic_collect_mapping"
1241 int _sion_generic_collect_mapping_buddy( _sion_generic_buddy *buddyptr,
1242  _sion_generic_gendata *sion_gendata,
1243  int *mapping_size,
1244  sion_int32 **mapping) {
1245  int rc=SION_SUCCESS;
1246  int t;
1247  _sion_generic_apidesc *sion_apidesc;
1248  sion_int32 lpos[2], *receivemap=NULL, iamreceiver, receiver = -1;
1249 
1250  sion_apidesc=sion_gendata->apidesc;
1251 
1252  *mapping = NULL; *mapping_size = 0;
1253 
1254 
1255  /* mapping data will be collected by master of first physical file */
1256  if((buddyptr->buddy_coll.groupnum==0) && (buddyptr->buddy_coll.rank==0)) {
1257  /* allocate data */
1258  *mapping_size=sion_gendata->gsize;
1259  *mapping = (sion_int32 *) malloc(*mapping_size * 2 * sizeof(sion_int32));
1260  if (*mapping == NULL) {
1261  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_generic_collect_mapping_buddy: Cannot allocate memory for mapping"));
1262  }
1263  }
1264 
1265  /* gather info about send about global rank of master of first file on grank 0 */
1266  if(sion_gendata->grank==0) {
1267  receivemap = (sion_int32 *) malloc(sion_gendata->gsize * sizeof(sion_int32));
1268  if (receivemap == NULL) {
1269  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_generic_collect_mapping_buddy: Cannot allocate memory for receivemap"));
1270  }
1271  }
1272 
1273  if((buddyptr->buddy_coll.filenum==0) && (buddyptr->buddy_coll.rank==0)) iamreceiver=sion_gendata->grank;
1274  else iamreceiver=-1;
1275  sion_apidesc->gatherr_cb(&iamreceiver, receivemap, sion_gendata->comm_data_global, _SION_INT32, 1, 0);
1276  if(sion_gendata->grank==0) {
1277  for(t=0;t<sion_gendata->gsize;t++) {
1278  if(receivemap[t]>=0) {
1279  receiver=receivemap[t];
1280  break;
1281  }
1282  }
1283  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "receiver of mapping grank=%d\n", receiver));
1284  }
1285  sion_apidesc->bcastr_cb(&receiver, sion_gendata->comm_data_global, _SION_INT32, 1, 0);
1286 
1287  /* receive global rank of master of first file on grank 0 */
1288  lpos[0] = buddyptr->buddy_send.filenum;
1289  lpos[1] = buddyptr->buddy_send.rank;
1290  sion_apidesc->gatherr_cb(&lpos, *mapping, sion_gendata->comm_data_global, _SION_INT32, 2, receiver);
1291 
1292  if(receivemap!=NULL) free(receivemap);
1293 
1294  return(rc);
1295 }
1296 #undef DFUNCTION
1297 
1298 
1299 #define DFUNCTION "_sion_generic_buddy_get_and_distribute_info_from_file"
1300 int _sion_generic_buddy_get_and_distribute_info_from_file( _sion_generic_gendata *sion_gendata, char *fname, int root,
1301  sion_int32 *filenumber, sion_int32 *numfiles,
1302  sion_int32 *lrank, sion_int32 *lsize) {
1303 
1304  int sid = -1, ntasks, nfiles, t;
1305  int rc = SION_SUCCESS;
1306  FILE *fileptr;
1307  sion_int32 fsblksize;
1308  int *tasksinfile = NULL;
1309  int mapping_size = -1;
1310  sion_int32 *mapping = NULL;
1311  sion_int32 lpos[2];
1312  _sion_generic_apidesc *sion_apidesc;
1313 
1314  sion_apidesc=sion_gendata->apidesc;
1315 
1316  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "entering function sion_gendata->grank=%d\n",sion_gendata->grank));
1317 
1318  if(sion_gendata->grank == root) {
1319  /* open and get mapping of sion file */
1320  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "before open\n"));
1321  sid=_sion_open_read(fname,_SION_FMODE_READ|_SION_FMODE_ANSI,_SION_READ_MASTER_ONLY_OF_MULTI_FILES,
1322  &ntasks,&nfiles,NULL,&fsblksize,NULL,&fileptr);
1323  if(sid>=0) {
1324  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "after open\n"));
1325  rc=sion_get_mapping(sid,&mapping_size,&mapping,numfiles);
1326  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "sion file %d files\n", *numfiles));
1327  } else {
1328  *numfiles=-1;
1329  }
1330  }
1331 
1332 
1333  /* each task has to know if more than one file was used in sion file */
1334  sion_apidesc->bcastr_cb(numfiles, sion_gendata->comm_data_global, _SION_INT32, 1, root);
1335  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "%s: numfiles=%d\n",fname,*numfiles));
1336 
1337  if((sion_gendata->grank == root) && (*numfiles>1)) {
1338  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "%s: mapping_size=%d sion_gendata->gsize=%d\n",fname,*numfiles,mapping_size,sion_gendata->gsize));
1339  if(mapping_size!=sion_gendata->gsize) {
1340  return(_sion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,
1341  "_sion_generic_buddy_get_and_distribute_info_from_file: Incorrect sum of ntasks of files %d <> %d\n",
1342  mapping_size, sion_gendata->gsize));
1343  }
1344  }
1345 
1346  if(*numfiles<0) {
1347  return(_sion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,
1348  "_sion_generic_buddy_get_and_distribute_info_from_file: could not get numfiles from sion file\n"));
1349  }
1350 
1351  if(*numfiles>1) {
1352  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "before scatter\n"));
1353  if(sion_gendata->grank==root) {
1354  for(t=0;t<mapping_size;t++) {
1355  DPRINTFP((1, DFUNCTION, sion_gendata->grank, " %d -> (%d,%d)\n",t,mapping[t*2],mapping[t*2+1]));
1356  }
1357  }
1358 
1359  /* scatter mapping to all tasks */
1360  sion_apidesc->scatterr_cb(mapping, lpos, sion_gendata->comm_data_global, _SION_INT32, 2, root);
1361  *filenumber=lpos[0];
1362  *lrank =lpos[1];
1363  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "after scatter filenum+lrank (%d,%d)\n",*filenumber,*lrank));
1364 
1365  /* compute and scatter number of tasks in each file */
1366  if(sion_gendata->grank==root) {
1367  tasksinfile = (int *) malloc(*numfiles * sizeof(int));
1368  if (tasksinfile == NULL) {
1369  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_generic_get_and_distribute_info_from_file: Cannot allocate memory for tasksinfile counter vector"));
1370  }
1371  for(t=0;t<*numfiles;t++) tasksinfile[t]=0; /* init counter */
1372  for(t=0;t<mapping_size;t++) tasksinfile[ mapping[t*2] ]++; /* count tasks in file */
1373  for(t=0;t<mapping_size;t++) mapping[t*2+1]=tasksinfile[ mapping[t*2] ]; /* set 2nd value of mapping to lsize */
1374  }
1375  sion_apidesc->scatterr_cb(mapping, lpos, sion_gendata->comm_data_global, _SION_INT32, 2, root);
1376  *lsize =lpos[1];
1377  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "after scatter lsize (%d, %d of %d)\n",*filenumber, *lrank, *lsize));
1378 
1379  if(sion_gendata->grank==root) {
1380  if(tasksinfile) free(tasksinfile);
1381  }
1382  /* WARNING: mapping file of sion file is now destroyed and should not be used until close */
1383 
1384  } else {
1385  *filenumber=0;
1386  *lrank = sion_gendata->grank;
1387  *lsize = sion_gendata->gsize;
1388  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "only one file -> filenumber=%d lRank=%d\n",*filenumber,*lrank));
1389  }
1390 
1391  if(sion_gendata->grank == root) {
1392  /* frees also mapping vector */
1393  if (sid>=0) _sion_close_sid(sid);
1394  }
1395 
1396  return(rc);
1397 }
1398 #undef DFUNCTION
1399 
1400 
1401 #define DFUNCTION "_sion_generic_buddy_get_and_distribute_info_from_one_file"
1402 int _sion_generic_buddy_get_and_distribute_info_from_one_file( _sion_generic_gendata *sion_gendata, char *fname, int root,
1403  sion_int32 *filenumber, sion_int32 *numfiles,
1404  sion_int32 *lrank, sion_int32 *lsize) {
1405 
1406  int rc = SION_SUCCESS;
1407  int t, mapping_size = 0, grank, *mapping = NULL;
1408  sion_int32 file_filenumber,file_numfiles,file_lrank,file_lsize;
1409  _sion_filedesc *sion_filedesc = NULL;
1410  _sion_fileptr *sion_fileptr;
1411  _sion_generic_apidesc *sion_apidesc;
1412 
1413  sion_apidesc=sion_gendata->apidesc;
1414 
1415  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "entering function sion_gendata->grank=%d\n",sion_gendata->grank));
1416 
1417  if(sion_gendata->grank == root) {
1418  /* open and get globalranks of sion file */
1419  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "before open\n"));
1420  /* allocate and initialise internal data structure with default values (NULL and -1) */
1421  sion_filedesc = _sion_alloc_filedesc();
1422  if (sion_filedesc == NULL) {
1423  return(_sion_errorprint(SION_ID_UNDEF,SION_ID_UNDEF,
1424  "sion_open: cannot allocate filedescriptor structure of size %lu (sion_filedesc), aborting ...\n",
1425  (unsigned long) sizeof(sion_filedesc)));
1426  }
1427  _sion_init_filedesc(sion_filedesc);
1428 
1429  /* open file */
1431  if (!sion_fileptr) {
1432  return(_sion_errorprint(SION_ID_UNDEF,_SION_ERROR_RETURN,"sion_open: cannot open %s for reading, aborting ...\n", fname));
1433  }
1434  sion_filedesc->fileptr = sion_fileptr;
1435 
1436  /* read part of header which does not depend on ntasks */
1437  rc = _sion_read_header_fix_part(sion_filedesc);
1438  if (rc!=SION_SUCCESS) {
1439  return(_sion_errorprint(SION_ID_UNDEF,_SION_ERROR_RETURN,"sion_open: cannot read header from file %s, aborting ...\n", fname));
1440  }
1441  sion_filedesc->rank = 0;
1442  sion_filedesc->state = SION_FILESTATE_SEROPEN;
1443  sion_filedesc->mode = SION_FILEMODE_READ;
1444 
1445  /* memory allocation for internal fields */
1446  _sion_alloc_filedesc_arrays(sion_filedesc);
1447 
1448  /* read part of header which depends on ntasks */
1449  rc = _sion_read_header_var_part(sion_filedesc);
1450  if (rc!=SION_SUCCESS) {
1451  return(_sion_errorprint(SION_ID_UNDEF,_SION_ERROR_RETURN,"sion_open: cannot read header (var part) from file %s, aborting ...\n", fname));
1452  }
1453 
1454  file_numfiles=sion_filedesc->nfiles;
1455  file_filenumber=sion_filedesc->filenumber;
1456  file_lsize=sion_filedesc->ntasks;
1457 
1458  /* allocate mapping vector */
1459  mapping_size=sion_gendata->gsize;
1460  mapping = (sion_int32 *) malloc(mapping_size * 2 * sizeof(sion_int32));
1461  if (mapping == NULL) {
1462  return(_sion_errorprint(SION_ID_NOT_VALID,_SION_ERROR_RETURN,"_sion_generic_buddy_get_and_distribute_info_from_one_file: cannot allocate temporary memory of size %lu (mapping), aborting ...\n",
1463  (unsigned long) mapping_size * 2 * sizeof(sion_int32)));
1464  }
1465 
1466  }
1467 
1468 
1469  /* each task has to know some number about local file */
1470  sion_apidesc->bcastr_cb(&file_numfiles, sion_gendata->comm_data_global, _SION_INT32, 1, root);
1471  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "%s: numfiles=%d\n",fname,file_numfiles));
1472  sion_apidesc->bcastr_cb(&file_filenumber, sion_gendata->comm_data_global, _SION_INT32, 1, root);
1473  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "%s: filenumber=%d\n",fname,file_filenumber));
1474  sion_apidesc->bcastr_cb(&file_lsize, sion_gendata->comm_data_global, _SION_INT32, 1, root);
1475  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "%s: file_lsize=%d\n",fname,file_lsize));
1476 
1477 
1478  if(file_numfiles!=*numfiles) {
1479  _SION_SAFE_FREE(mapping, NULL);
1480  return(_sion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,
1481  "_sion_generic_buddy_get_and_distribute_info_from_one_file: Incorrect number of files %d <> %d\n",
1482  file_numfiles,*numfiles));
1483  }
1484 
1485  /* init mapping vector lrank */
1486  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "before scatter\n"));
1487  if(sion_gendata->grank==root) {
1488  for(t=0;t<mapping_size;t++) mapping[t]=-1;
1489  for(t=0;t<file_lsize;t++) {
1490  grank=sion_filedesc->all_globalranks[t];
1491  if(grank>=0) {
1492  mapping[grank]=t;
1493  DPRINTFP((1, DFUNCTION, sion_gendata->grank, " file=%s mapping[%d] -> (%d)\n",fname,grank,mapping[grank]));
1494  }
1495  }
1496  }
1497 
1498  /* scatter mapping to all tasks */
1499  sion_apidesc->scatterr_cb(mapping, &file_lrank, sion_gendata->comm_data_global, _SION_INT32, 1, root);
1500  if(file_lrank!=-1) {
1501  *filenumber=file_filenumber;
1502  *lrank =file_lrank;
1503  *lsize =file_lsize;
1504  DPRINTFP((1, DFUNCTION, sion_gendata->grank, "after scatter filenum=%d lrank=%d lsize=%d\n",*filenumber,*lrank,*lsize));
1505  }
1506 
1507  if(sion_gendata->grank == root) {
1508  /* close current file */
1509  _sion_free_filedesc_arrays(sion_filedesc);
1510  _sion_file_close(sion_filedesc->fileptr);
1511  sion_filedesc->fileptr=NULL;
1512  free(mapping);
1513  }
1514 
1515  return(rc);
1516 }
1517 #undef DFUNCTION
int sion_feof(int sid)
Function that indicates whether the end of file is reached for this task.
Definition: sion_common.c:770
sion_int64 _sion_file_set_position(_sion_fileptr *sion_fileptr, sion_int64 startpointer)
Set new position in file.
Definition: sion_file.c:239
_sion_filedesc * _sion_alloc_filedesc()
Allocates memory for internal sion structure.
_sion_fileptr * _sion_file_open(const char *fname, unsigned int flags, unsigned int addflags)
Create and open a new file for writing.
Definition: sion_file.c:41
Sion File Descriptor Structure.
Definition: sion_filedesc.h:77
int sion_ensure_free_space(int sid, sion_int64 bytes)
Funtion to ensure that enough space is available for writing.
Definition: sion_common.c:1014
int _sion_paropen_generic_one_file(int sid, char *fname, _sion_flags_store *flags_store, char *prefix, int *numFiles, int *filenumber, sion_int64 *chunksize, sion_int32 *fsblksize, int rank, int ntasks, int *globalrank, int flag, FILE **fileptr, _sion_generic_gendata *sion_gendata, _sion_generic_buddy *buddy_data)
Generic parallel open of one direct access file.
int _sion_parclose_generic(int sid, int rank, int ntasks, int mapping_size, sion_int32 *mapping, int flag, _sion_generic_gendata *sion_gendata, _sion_generic_buddy *buddy_data)
Internal function to close parallel opened SION file.
int _sion_read_header_var_part(_sion_filedesc *sion_filedesc)
Read the second part of SION Meta Block 1.
#define SION_FILESTATE_SEROPEN
Definition: sion_filedesc.h:25
sion_int64 * all_globalranks
int _sion_alloc_filedesc_arrays(_sion_filedesc *sion_filedesc)
Allocate memory for the internal sion arrays.
int _sion_free_filedesc_arrays(_sion_filedesc *sion_filedesc)
free memory for the internal sion arrays
#define SION_FILE_FLAG_READ
Definition: sion_file.h:24
int _sion_vcdtype(int sid)
Definition: sion_fd.c:56
sion_int32 fileptr_exported
#define SION_FILE_FLAG_POSIX
Definition: sion_file.h:21
int sion_get_mapping(int sid, int *mapping_size, sion_int32 **mapping, int *numfiles)
Returns pointers to the internal field mapping.
Definition: sion_common.c:221
void * _sion_vcdtovcon(int sid)
Definition: sion_fd.c:51
#define SION_FILEMODE_READ
Definition: sion_filedesc.h:33
int _sion_file_close(_sion_fileptr *sion_fileptr)
Close file and destroys fileptr structure.
Definition: sion_file.c:118
int _sion_newvcd(void *data, int type)
Definition: sion_fd.c:41
int _sion_read_header_fix_part(_sion_filedesc *sion_filedesc)
Read part of the SION Meta Block 1.
char * _sion_get_multi_filename(const char *fname, int filenumber)
generates the multi filename
#define SION_FILEDESCRIPTOR
Definition: sion_fd.h:17
int _sion_init_filedesc(_sion_filedesc *sion_filedesc)
Initialize the sion file description.
Definition: sion_filedesc.c:35
#define SION_FILEMODE_WRITE
Definition: sion_filedesc.h:34
int _sion_file_stat_file(const char *fname)
Check if file exists (LARGE_FILE support on BlueGene)
Definition: sion_file.c:210
Sion Time Stamp Header.
int _sion_file_flush(_sion_fileptr *sion_fileptr)
Flush data to file.
Definition: sion_file.c:304
_sion_fileptr * fileptr
Definition: sion_filedesc.h:80
int _sion_open_read(const char *fname, sion_int64 file_mode_flags, int read_all, int *ntasks, int *nfiles, sion_int64 **chunksizes, sion_int32 *fsblksize, int **globalranks, FILE **fileptr)
internal sion serial open function for reading on one or more files