1 /*
2  *
3  *  This file is part of MUMPS 4.10.0, built on Tue May 10 12:56:32 UTC 2011
4  *
5  *
6  *  This version of MUMPS is provided to you free of charge. It is public
7  *  domain, based on public domain software developed during the Esprit IV
8  *  European project PARASOL (1996-1999). Since this first public domain
9  *  version in 1999, research and developments have been supported by the
10  *  following institutions: CERFACS, CNRS, ENS Lyon, INPT(ENSEEIHT)-IRIT,
11  *  INRIA, and University of Bordeaux.
12  *
13  *  The MUMPS team at the moment of releasing this version includes
14  *  Patrick Amestoy, Maurice Bremond, Alfredo Buttari, Abdou Guermouche,
15  *  Guillaume Joslin, Jean-Yves L'Excellent, Francois-Henry Rouet, Bora
16  *  Ucar and Clement Weisbecker.
17  *
18  *  We are also grateful to Emmanuel Agullo, Caroline Bousquet, Indranil
19  *  Chowdhury, Philippe Combes, Christophe Daniel, Iain Duff, Vincent Espirat,
20  *  Aurelia Fevre, Jacko Koster, Stephane Pralet, Chiara Puglisi, Gregoire
21  *  Richard, Tzvetomila Slavova, Miroslav Tuma and Christophe Voemel who
22  *  have been contributing to this project.
23  *
24  *  Up-to-date copies of the MUMPS package can be obtained
25  *  from the Web pages:
26  *  http://mumps.enseeiht.fr/  or  http://graal.ens-lyon.fr/MUMPS
27  *
28  *
29  *   THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
30  *   EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
31  *
32  *
33  *  User documentation of any code that uses this software can
34  *  include this complete notice. You can acknowledge (using
35  *  references [1] and [2]) the contribution of this package
36  *  in any scientific publication dependent upon the use of the
37  *  package. You shall use reasonable endeavours to notify
38  *  the authors of the package of this publication.
39  *
40  *   [1] P. R. Amestoy, I. S. Duff, J. Koster and  J.-Y. L'Excellent,
41  *   A fully asynchronous multifrontal solver using distributed dynamic
42  *   scheduling, SIAM Journal of Matrix Analysis and Applications,
43  *   Vol 23, No 1, pp 15-41 (2001).
44  *
45  *   [2] P. R. Amestoy and A. Guermouche and J.-Y. L'Excellent and
46  *   S. Pralet, Hybrid scheduling for the parallel solution of linear
47  *   systems. Parallel Computing Vol 32 (2), pp 136-156 (2006).
48  *
49  */
50 #include "mumps_io_basic.h"
51 #include "mumps_io_err.h"
52 /* Exported global variables */
53 #if ! defined (MUMPS_WIN32)
54 # if defined(WITH_PFUNC) && ! defined (WITHOUT_PTHREAD)
55 #  include <pthread.h>
56 pthread_mutex_t mumps_io_pwrite_mutex;
57 # endif
58 /* int* mumps_io_pfile_pointer_array; */
59 /* int* mumps_io_current_file; */
60 /* #else /\*MUMPS_WIN32*\/ */
61 /* FILE** mumps_io_current_file; */
62 /* FILE** mumps_io_pfile_pointer_array; */
63 #endif /* MUMPS_WIN32 */
64 /* mumps_file_struct* mumps_io_pfile_pointer_array;
65    mumps_file_struct* mumps_io_current_file; */
66 mumps_file_type* mumps_files = NULL;
67 /* int mumps_io_current_file_number; */
68 char* mumps_ooc_file_prefix = NULL;
69 /* char** mumps_io_pfile_name; */
70 /* int mumps_io_current_file_position; */
71 /* int mumps_io_write_pos; */
72 /* int mumps_io_last_file_opened; */
73 int mumps_elementary_data_size;
74 int mumps_io_is_init_called;
75 int mumps_io_myid;
76 int mumps_io_max_file_size;
77 /* int mumps_io_nb_file; */
78 int mumps_io_flag_async;
79 int mumps_io_k211;
80 /* int mumps_flag_open;*/
81 int mumps_directio_flag;
82 int mumps_io_nb_file_type;
83 /* Functions */
mumps_set_file(int type,int file_number_arg)84 int mumps_set_file(int type,int file_number_arg){
85   /* Defines the pattern for the file name. The last 6 'X' will be replaced
86      so as to name were unique */
87   char name[351];
88 #if ! defined(_WIN32)
89   int fd;
90   char buf[64]; /* for error message */
91 #endif
92   mumps_file_struct  *mumps_io_pfile_pointer_array;
93   /*  if ((mumps_files+type)->mumps_io_current_file_number >= ((mumps_files+type)->mumps_io_nb_file)-1){*/
94   if (file_number_arg > ((mumps_files+type)->mumps_io_nb_file)-1){
95     /* Exception : probably thrown because of a bad estimation
96        of number of files. */
97     /* We increase the number of file needed and then realloc. */
98     ((mumps_files+type)->mumps_io_nb_file)++;
99     (mumps_files+type)->mumps_io_pfile_pointer_array=realloc((void *)(mumps_files+type)->mumps_io_pfile_pointer_array,((mumps_files+type)->mumps_io_nb_file)*sizeof(mumps_file_struct));
100     if((mumps_files+type)->mumps_io_pfile_pointer_array==NULL){
101       return mumps_io_error(-13,"Allocation problem in low-level OOC layer\n");
102     }
103     ((mumps_files+type)->mumps_io_pfile_pointer_array+((mumps_files+type)->mumps_io_nb_file)-1)->is_opened = 0;
104   }
105   mumps_io_pfile_pointer_array=(mumps_files+type)->mumps_io_pfile_pointer_array;
106   /* Do change the current file */
107   ((mumps_files+type)->mumps_io_current_file_number)=file_number_arg;
108   if((mumps_io_pfile_pointer_array+file_number_arg)->is_opened!=0){
109     ((mumps_files+type)->mumps_io_current_file_number)=file_number_arg;
110     return 0;
111   }
112 /* #if ! defined( MUMPS_WIN32 )*/
113 /* MinGW does not have a mkstemp function and MinGW defines _WIN32,
114  * so we also go in the else branch below with MinGW */
115 #if ! defined(_WIN32)
116   strcpy(name,mumps_ooc_file_prefix);
117   fd=mkstemp(name);
118   /* Note that a file name is built by mkstemp and that the file is
119      opened. fd hold the file descriptor to access it.
120      We want to close the file that will be opened later
121      and might be removed before the end of the processus.
122   */
123   if(fd < 0) {
124     sprintf(buf,"File creation failure");
125     return mumps_io_sys_error(-90,buf);
126   } else {
127     close(fd);
128   }
129 #else
130   sprintf(name,"%s_%d_%d",mumps_ooc_file_prefix,((mumps_files+type)->mumps_io_current_file_number)+1,type);
131 #endif
132 /*   *(mumps_io_pfile_pointer_array+mumps_io_current_file_number)=fopen(name,"w+"); */
133 /*   *(mumps_io_pfile_name+mumps_io_current_file_number)=(char *)malloc((strlen(name)+1)*sizeof(char)); */
134 /*   if(*(mumps_io_pfile_name+mumps_io_current_file_number)==NULL){ */
135 /*     sprintf(error_str,"Allocation problem in low-level OOC layer\n"); */
136 /*     return -13; */
137 /*   } */
138   strcpy((mumps_io_pfile_pointer_array+(mumps_files+type)->mumps_io_current_file_number)->name,name);
139   /* See mumps_io_basic.h for comments on the I/O flags passed to open */
140 #if ! defined( MUMPS_WIN32 )
141   (mumps_io_pfile_pointer_array+(mumps_files+type)->mumps_io_current_file_number)->file=open(name,(mumps_files+type)->mumps_flag_open,0666);
142   /*
143 CPA: for LU factor file:
144 (mumps_io_pfile_pointer_array+(mumps_files+type)->mumps_io_current_file_number)->file= open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666); */
145   if((mumps_io_pfile_pointer_array+(mumps_files+type)->mumps_io_current_file_number)->file==-1){
146     return mumps_io_sys_error(-90,"Unable to open OOC file");
147   }
148 #else
149   (mumps_io_pfile_pointer_array+(mumps_files+type)->mumps_io_current_file_number)->file=fopen(name,(mumps_files+type)->mumps_flag_open);
150   if((mumps_io_pfile_pointer_array+(mumps_files+type)->mumps_io_current_file_number)->file==NULL){
151     return mumps_io_error(-90,"Problem while opening OOC file");
152   }
153 #endif
154   (mumps_files+type)->mumps_io_current_file=(mumps_io_pfile_pointer_array+(mumps_files+type)->mumps_io_current_file_number);
155   ((mumps_files+type)->mumps_io_nb_file_opened)++;
156   if((mumps_files+type)->mumps_io_current_file_number>(mumps_files+type)->mumps_io_last_file_opened){
157     (mumps_files+type)->mumps_io_last_file_opened=(mumps_files+type)->mumps_io_current_file_number;
158   }
159   /*  if(*(mumps_io_pfile_pointer_array+mumps_io_current_file_number)==NULL) */
160   ((mumps_files+type)->mumps_io_current_file)->write_pos=0;
161   ((mumps_files+type)->mumps_io_current_file)->is_opened=1;
162   /*  printf("new file created -> num = %d \n", ((mumps_files+type)->mumps_io_last_file_opened));*/
163   /*  printf("new file created %d\n",mumps_io_current_file_number);*/
164   return 0;
165 }
mumps_update_current_file_position(mumps_file_struct * file_arg)166 void mumps_update_current_file_position(mumps_file_struct* file_arg){
167   file_arg->current_pos=file_arg->write_pos;
168 /*   mumps_io_current_file_position=mumps_io_write_pos; */
169 }
mumps_compute_where_to_write(const double to_be_written,const int type,long long vaddr,size_t already_written)170 int mumps_compute_where_to_write(const double to_be_written,const int type,long long vaddr,size_t already_written){
171   /* Check if the current file has enough memory to receive the whole block*/
172   int ret_code;
173   int file;
174   mumps_file_struct *current_file;
175   long long vaddr_loc;
176   int pos;
177   /* Virtual address based file management scheme */
178   vaddr_loc=vaddr*(long long)mumps_elementary_data_size+(long long)already_written;
179   mumps_gen_file_info(vaddr_loc,&pos,&file);
180   ret_code=mumps_set_file(type,file);
181   if(ret_code<0){
182     return ret_code;
183   }
184   current_file=(mumps_files+type)->mumps_io_current_file;
185   current_file->write_pos=pos;
186   mumps_update_current_file_position(current_file);
187   return 0;
188 }
mumps_prepare_pointers_for_write(double to_be_written,int * pos_in_file,int * file_number,const int type,long long vaddr,size_t already_written)189 int mumps_prepare_pointers_for_write(double to_be_written,int * pos_in_file, int * file_number,const int type,long long vaddr,size_t already_written){
190   int ret_code;
191   ret_code=mumps_compute_where_to_write(to_be_written,type,vaddr,already_written);
192   if(ret_code<0){
193     return ret_code;
194   }
195   *pos_in_file=((mumps_files+type)->mumps_io_current_file)->current_pos;
196   /* should be modified to take into account the file arg */
197   *file_number=(mumps_files+type)->mumps_io_current_file_number;
198   return 0;
199 }
mumps_gen_file_info(long long vaddr,int * pos,int * file)200 MUMPS_INLINE int mumps_gen_file_info(long long vaddr, int * pos, int * file){
201   *file=(int)(vaddr/(long long)mumps_io_max_file_size);
202   *pos=(int)(vaddr%(long long)mumps_io_max_file_size);
203   return 0;
204 }
mumps_compute_nb_concerned_files(long long block_size,int * nb_concerned_files,long long vaddr)205 int mumps_compute_nb_concerned_files(long long block_size, int * nb_concerned_files,long long vaddr){
206   int file,pos,available_size;
207   long long vaddr_loc;
208   vaddr_loc=vaddr*(long long)mumps_elementary_data_size;
209   mumps_gen_file_info(vaddr_loc,&pos,&file);
210   available_size=mumps_io_max_file_size-pos+1;
211   *nb_concerned_files=(int)my_ceil((double)(my_max(0,((block_size)*(double)(mumps_elementary_data_size))-available_size))/(double)mumps_io_max_file_size)+1;
212   return 0;
213 }
mumps_io_do_write_block(void * address_block,long long block_size,int * type_arg,long long vaddr,int * ierr)214 int mumps_io_do_write_block(void * address_block,
215                             long long block_size,
216                             int * type_arg,
217                             long long vaddr,
218                             int * ierr){
219   /* Type of fwrite : size_t fwrite(const void *ptr, size_t size,
220                                     *size_t nmemb, FILE *stream); */
221   size_t write_size;
222   int i;
223   int nb_concerned_files=0;
224   int ret_code,file_number_loc,pos_in_file_loc;
225   double to_be_written;
226 #if ! defined( MUMPS_WIN32 )
227   int* file;
228 #else
229   FILE** file;
230 #endif
231   int where;
232   void* loc_addr;
233   int type;
234   size_t already_written=0;
235   char buf[64];
236   type=*type_arg;
237   loc_addr=address_block;
238   mumps_compute_nb_concerned_files(block_size,&nb_concerned_files,vaddr);
239   to_be_written=((double)mumps_elementary_data_size)*((double)(block_size));
240   /*  printf("nb_concerned -> %d | %lf \n",nb_concerned_files,to_be_written); */
241   for(i=0;i<nb_concerned_files;i++){
242 #if ! defined( MUMPS_WIN32 ) && ! defined (WITHOUT_PTHREAD)
243 # ifdef WITH_PFUNC
244     if(mumps_io_flag_async==IO_ASYNC_TH){
245       mumps_io_protect_pointers();
246     }
247 # endif
248 #endif
249     ret_code=mumps_prepare_pointers_for_write(to_be_written,&pos_in_file_loc,&file_number_loc,type,vaddr,already_written);
250     if(ret_code<0){
251 #if ! defined( MUMPS_WIN32 ) && ! defined (WITHOUT_PTHREAD)
252 # ifdef WITH_PFUNC
253     if(mumps_io_flag_async==IO_ASYNC_TH){
254       mumps_io_unprotect_pointers();
255     }
256 # endif
257 #endif
258       return ret_code;
259     }
260     if((double)(mumps_io_max_file_size-((mumps_files+type)->mumps_io_current_file)->write_pos)>to_be_written){
261       write_size=(size_t)to_be_written;
262       already_written=(size_t)to_be_written;
263     }else{
264       write_size=(size_t)((double)(mumps_io_max_file_size-((mumps_files+type)->mumps_io_current_file)->write_pos));
265       already_written=already_written+(size_t)write_size;
266     }
267 #if defined( MUMPS_WIN32 )
268     write_size=(size_t)(int)((write_size)/mumps_elementary_data_size);
269 #endif
270     file=&(((mumps_files+type)->mumps_io_current_file)->file);
271     where=((mumps_files+type)->mumps_io_current_file)->write_pos;
272 #if ! defined( MUMPS_WIN32 ) && ! defined (WITHOUT_PTHREAD)
273 # ifdef WITH_PFUNC
274     if(mumps_io_flag_async==IO_ASYNC_TH){
275       mumps_io_unprotect_pointers();
276     }
277 # endif
278 #endif
279     /* printf("1 write -> size = %d | off = %d | file = %d (%d) \n",(int)write_size,where,*file,((mumps_files+type)->mumps_io_current_file)->write_pos); */
280     ret_code=mumps_io_write__(file,loc_addr,write_size,where,type);
281     if(ret_code<0){
282       return ret_code;
283     }
284 #if ! defined( MUMPS_WIN32 ) && ! defined (WITHOUT_PTHREAD)
285 # ifdef WITH_PFUNC
286     if(mumps_io_flag_async==IO_ASYNC_TH){
287       mumps_io_protect_pointers();
288     }
289 # endif
290 #endif
291 #if ! defined( MUMPS_WIN32 )
292     ((mumps_files+type)->mumps_io_current_file)->write_pos=((mumps_files+type)->mumps_io_current_file)->write_pos+((int)write_size);
293     to_be_written=to_be_written-((int)write_size);
294     loc_addr=(void*)((size_t)loc_addr+write_size);
295 /*     mumps_io_write_pos=mumps_io_write_pos+((int)write_size); */
296 /*     to_be_written=to_be_written-((int)write_size); */
297 /*     loc_addr=(void*)((size_t)loc_addr+write_size); */
298 #else
299     /* fread and write */
300     ((mumps_files+type)->mumps_io_current_file)->write_pos=((mumps_files+type)->mumps_io_current_file)->write_pos+((int)write_size*mumps_elementary_data_size);
301     to_be_written=to_be_written-((int)write_size*mumps_elementary_data_size);
302     loc_addr=(void*)((size_t)loc_addr+(size_t)((int)write_size*mumps_elementary_data_size));
303 /*     mumps_io_write_pos=mumps_io_write_pos+((int)write_size*mumps_elementary_data_size); */
304 /*     to_be_written=to_be_written-((int)write_size*mumps_elementary_data_size); */
305 /*     loc_addr=(void*)((size_t)loc_addr+(size_t)((int)write_size*mumps_elementary_data_size)); */
306 #endif
307 #if ! defined( MUMPS_WIN32 ) && ! defined (WITHOUT_PTHREAD)
308 # ifdef WITH_PFUNC
309     if(mumps_io_flag_async==IO_ASYNC_TH){
310       mumps_io_unprotect_pointers();
311     }
312 # endif
313 #endif
314   }
315   if(to_be_written!=0){
316     *ierr = -90;
317     sprintf(buf,"Internal (1) error in low-level I/O operation %lf",to_be_written);
318     return mumps_io_error(*ierr,buf);
319   }
320   /* printf("write ok -> %d \n");*/
321   return 0;
322 }
mumps_io_do_read_block(void * address_block,long long block_size,int * type_arg,long long vaddr,int * ierr)323 int mumps_io_do_read_block(void * address_block,
324                     long long block_size,
325                     int * type_arg,
326                      long long vaddr,
327                     int * ierr){
328   size_t size;
329 #if ! defined( MUMPS_WIN32 )
330   int* file;
331 #else
332   FILE** file;
333 #endif
334   double read_size;
335   int local_fnum,local_offset;
336   void *loc_addr;
337   long long vaddr_loc;
338   int type;
339   type=*type_arg;
340   /*  if(((double)(*block_size))*((double)(mumps_elementary_data_size))>(double)mumps_io_max_file_size){
341     sprintf(error_str,"Internal error in low-level I/O operation (requested size too big for file system) \n");
342     return -90;
343     }*/
344   if(block_size==0){
345     return 0;
346   }
347   read_size=(double)mumps_elementary_data_size*(double)(block_size);
348   /*  if((*file_number<0)&&(read_size<(double)mumps_io_max_file_size)){
349     sprintf(error_str,"Internal error (1) in low level read op\n");
350     return -90;
351     }*/
352   loc_addr=address_block;
353   vaddr_loc=vaddr*(long long)mumps_elementary_data_size;
354   while(read_size>0){
355     /* Virtual addressing based management stuff */
356     local_fnum=(int)(vaddr_loc/(long long)mumps_io_max_file_size);
357     local_offset=(int)(vaddr_loc%(long long)mumps_io_max_file_size);
358     file=&((((mumps_files+type)->mumps_io_pfile_pointer_array)+local_fnum)->file);
359     /* printf("1 read | file -> %d | fnum -> %d | vaddr -> %d \n",*file,local_fnum,(int)vaddr_loc); */
360 #if ! defined( MUMPS_WIN32 )
361     if(read_size+(double)local_offset>(double)mumps_io_max_file_size){
362       size=(size_t)mumps_io_max_file_size-(size_t)local_offset;
363     }else{
364       size=(size_t)read_size;
365     }
366 #else
367     if(read_size+(double)local_offset>(double)mumps_io_max_file_size){
368       size=((size_t)mumps_io_max_file_size-(size_t)local_offset)/(size_t)mumps_elementary_data_size;
369     }else{
370       size=(size_t)(read_size/mumps_elementary_data_size);
371     }
372 #endif
373     *ierr=mumps_io_read__(file,loc_addr,size,local_offset,type);
374     if(*ierr<0){
375       return *ierr;
376     }
377 #if defined( MUMPS_WIN32 )
378     size=size*mumps_elementary_data_size;
379 #endif
380     vaddr_loc=vaddr_loc+(long long)size;
381     read_size=read_size-(double)size;
382     loc_addr=(void*)((size_t)loc_addr+size);
383     local_fnum++;
384     local_offset=0;
385     if(local_fnum>(mumps_files+type)->mumps_io_nb_file){
386       *ierr = -90;
387       return mumps_io_error(*ierr,"Internal error (2) in low level read op\n");
388     }
389   }
390   return 0;
391 }
mumps_free_file_pointers(int * step)392 int mumps_free_file_pointers(int *step){
393   int i,j,bound,ierr;
394 /*   Free prefix only for facto  */
395   if (*step == 0) free(mumps_ooc_file_prefix);
396   if(mumps_files == NULL )
397       return 0;
398 #if ! defined( MUMPS_WIN32 )
399 #endif
400   bound=mumps_io_nb_file_type;
401 /*   if(*step==0){ */
402 /*     /\* factorization *\/ */
403 /*     bound=NB_FILE_TYPE_FACTO; */
404 /*   }else{ */
405 /*     /\* solve *\/ */
406 /*     bound=NB_FILE_TYPE_SOLVE; */
407 /*   } */
408   for(j=0;j<bound;j++){
409     if( mumps_files[j].mumps_io_pfile_pointer_array == NULL ) {
410       continue;
411     }
412     for(i=0;i<(mumps_files+j)->mumps_io_nb_file_opened;i++){
413 #if ! defined( MUMPS_WIN32 )
414       ierr=close((((mumps_files+j)->mumps_io_pfile_pointer_array)+i)->file);
415       if(ierr==-1){
416         return mumps_io_sys_error(-90,"Problem while closing OOC file");
417       }
418 #else
419       ierr=fclose((((mumps_files+j)->mumps_io_pfile_pointer_array)+i)->file);
420       if(ierr==-1){
421         return mumps_io_error(-90,"Problem while closing OOC file\n");
422       }
423 #endif
424       /*     free(*(mumps_io_pfile_name+i)); */
425     }
426     free((mumps_files+j)->mumps_io_pfile_pointer_array);
427   }
428 /*   free(mumps_io_pfile_name); */
429   free(mumps_files);
430 #if ! defined( MUMPS_WIN32 )
431 #endif
432   return 0;
433 }
434 /* Initialize the mumps_file_type structure at <which>th position in
435    mumps_files. It only set values with no allocation to avoid any errors. */
mumps_io_init_file_struct(int * nb,int which)436 void mumps_io_init_file_struct(int* nb,int which)
437 {
438   (mumps_files+which)->mumps_io_current_file_number = -1;
439   (mumps_files+which)->mumps_io_last_file_opened = -1;
440   (mumps_files+which)->mumps_io_nb_file_opened = 0;
441   (mumps_files+which)->mumps_io_nb_file=*nb;
442   (mumps_files+which)->mumps_io_pfile_pointer_array = NULL;
443   (mumps_files+which)->mumps_io_current_file=NULL;
444 }
445 /* Allocate the file structures for factor files */
mumps_io_alloc_file_struct(int * nb,int which)446 int mumps_io_alloc_file_struct(int* nb,int which)
447 {
448   int i;
449   (mumps_files+which)->mumps_io_pfile_pointer_array=(mumps_file_struct *)malloc((*nb)*sizeof(mumps_file_struct));
450   if((mumps_files+which)->mumps_io_pfile_pointer_array==NULL){
451     return mumps_io_error(-13,"Allocation problem in low-level OOC layer\n");
452   }
453   for(i=0;i<*nb;i++){
454     (((mumps_files+which)->mumps_io_pfile_pointer_array)+i)->is_opened=0;
455   }
456   return 0;
457 }
mumps_init_file_structure(int * _myid,long long * total_size_io,int * size_element,int * nb_file_type,int * flag_tab)458 int mumps_init_file_structure(int* _myid, long long *total_size_io,int *size_element,int *nb_file_type,int *flag_tab)
459 {
460   /* Computes the number of files needed. Uses ceil value. */
461   int ierr;
462 #if ! defined( MUMPS_WIN32 )
463   int k211_loc;
464   int mumps_flag_open;
465 #endif
466   int i,nb;
467   int mumps_io_nb_file;
468   mumps_io_max_file_size=MAX_FILE_SIZE;
469   mumps_io_nb_file_type=*nb_file_type;
470   mumps_io_nb_file=(int)((((double)(*total_size_io)*1000000)*((double)(*size_element)))/(double)mumps_io_max_file_size)+1;
471   mumps_directio_flag=0;
472 #if ! defined( MUMPS_WIN32 )
473   mumps_flag_open=0;
474 #endif
475   mumps_io_myid=*_myid;
476   mumps_elementary_data_size=*size_element;
477   /* Allocates the memory necessary to handle the file pointer array.*/
478   mumps_files=(mumps_file_type *)malloc(mumps_io_nb_file_type*sizeof(mumps_file_type));
479   if(mumps_files==NULL){
480     return mumps_io_error(-13,"Allocation problem in low-level OOC layer\n");
481   }
482   /* Safe initialization of the mumps_file_type elements */
483   for(i=0;i<mumps_io_nb_file_type;i++){
484     nb=(flag_tab[i]==0||flag_tab[i]==1) ? mumps_io_nb_file : 1;
485     mumps_io_init_file_struct(&nb,i);
486   }
487   ierr=0;
488   for(i=0;i<mumps_io_nb_file_type;i++){
489     switch(flag_tab[i]){
490     case 0:
491 #if ! defined( MUMPS_WIN32 )
492       (mumps_files+i)->mumps_flag_open=mumps_flag_open|O_WRONLY|O_CREAT|O_TRUNC;
493 #else
494       strcpy((mumps_files+i)->mumps_flag_open,"wb");
495 #endif
496       break;
497     case 1:
498 #if ! defined( MUMPS_WIN32 )
499       (mumps_files+i)->mumps_flag_open=mumps_flag_open|O_RDONLY|O_CREAT|O_TRUNC;
500 #else
501       strcpy((mumps_files+i)->mumps_flag_open,"rb");
502 #endif
503       break;
504     case 2:
505 #if ! defined( MUMPS_WIN32 )
506       (mumps_files+i)->mumps_flag_open=mumps_flag_open|O_RDWR|O_CREAT|O_TRUNC;
507 #else
508       strcpy((mumps_files+i)->mumps_flag_open,"rwb");
509 #endif
510       break;
511     default:
512       return mumps_io_error(-90,"unknown value of flag_open\n");
513     }
514     ierr=mumps_io_alloc_file_struct(&nb,i);
515     if(ierr<0){
516       return ierr;
517     }
518     ierr=mumps_set_file(i,0);
519     if(ierr<0){
520       return ierr;
521     }
522   }
523   /* Init the current file.*/
524   return 0;
525 }
mumps_init_file_name(char * mumps_dir,char * mumps_file,int * mumps_dim_dir,int * mumps_dim_file,int * _myid)526 int mumps_init_file_name(char* mumps_dir,char* mumps_file,
527                          int* mumps_dim_dir,int* mumps_dim_file,int* _myid){
528   int i;
529   char *tmp_dir,*tmp_fname;
530   char base_name[20];
531   int dir_flag=0,file_flag=0;
532   char mumps_base[10]="mumps_";
533   tmp_dir=(char *)malloc(((*mumps_dim_dir)+1)*sizeof(char));
534   if(tmp_dir==NULL){
535     return mumps_io_error(-13,"Allocation problem in low-level OOC layer\n");
536   }
537   tmp_fname=(char *)malloc(((*mumps_dim_file)+1)*sizeof(char));
538   if(tmp_fname==NULL){
539     return mumps_io_error(-13,"Allocation problem in low-level OOC layer\n");
540   }
541   for(i=0;i<*mumps_dim_dir;i++){
542     tmp_dir[i]=mumps_dir[i];
543   }
544   tmp_dir[i]=0;
545   for(i=0;i<*mumps_dim_file;i++){
546     tmp_fname[i]=mumps_file[i];
547   }
548   tmp_fname[i]=0;
549   if(strcmp(tmp_dir,UNITIALIZED)==0){
550     dir_flag=1;
551     free(tmp_dir);
552     tmp_dir=getenv("MUMPS_OOC_TMPDIR");
553     if(tmp_dir==NULL){
554 #ifdef _AIX
555 # ifndef CINES_
556       tmp_dir=getenv("TMPDIR");
557       if(tmp_dir==NULL){
558         tmp_dir=MUMPS_OOC_DEFAULT_DIR;
559       }
560 # else
561       tmp_dir=MUMPS_OOC_DEFAULT_DIR;
562 # endif
563 #else
564       tmp_dir=MUMPS_OOC_DEFAULT_DIR;
565 #endif
566     }
567   }
568   if(strcmp(tmp_fname,UNITIALIZED)==0){
569     free(tmp_fname);
570     tmp_fname=getenv("MUMPS_OOC_PREFIX");
571     file_flag=1;
572   }
573   if(tmp_fname!=NULL){
574 #if ! defined( MUMPS_WIN32 )
575       sprintf(base_name,"_%s%d_XXXXXX",mumps_base,*_myid);
576 #else
577       sprintf(base_name,"_%s%d",mumps_base,*_myid);
578 #endif
579       mumps_ooc_file_prefix=(char *)malloc((strlen(SEPARATOR)+strlen(tmp_dir)+strlen(tmp_fname)+strlen(base_name)+1+1)*sizeof(char));
580       if(mumps_ooc_file_prefix==NULL){
581         return mumps_io_error(-13,"Allocation problem in low-level OOC layer\n");
582       }
583       sprintf(mumps_ooc_file_prefix,"%s%s%s%s",tmp_dir,SEPARATOR,tmp_fname,base_name);
584   }else{
585 #if ! defined( MUMPS_WIN32 )
586     sprintf(base_name,"%s%s%d_XXXXXX",SEPARATOR,mumps_base,*_myid);
587 #else
588     sprintf(base_name,"%s%s%d",SEPARATOR,mumps_base,*_myid);
589 #endif
590       mumps_ooc_file_prefix=(char *)malloc((strlen(SEPARATOR)+strlen(tmp_dir)+strlen(base_name)+1)*sizeof(char));
591       if(mumps_ooc_file_prefix==NULL){
592         return mumps_io_error(-13,"Allocation problem in low-level OOC layer\n");
593       }
594       sprintf(mumps_ooc_file_prefix,"%s%s%s",tmp_dir,SEPARATOR,base_name);
595   }
596   if(!dir_flag){
597     free(tmp_dir);
598   }
599   if(!file_flag){
600     free(tmp_fname);
601   }
602   return 0;
603 }
mumps_io_get_nb_files(int * nb_files,const int * type)604 int mumps_io_get_nb_files(int* nb_files, const int* type){
605   *nb_files=((mumps_files+*type)->mumps_io_last_file_opened)+1;
606   return 0;
607 }
mumps_io_get_file_name(int * indice,char * name,int * length,int * type)608 int mumps_io_get_file_name(int* indice,char* name,int* length,int* type){
609   int i;
610   i=(*indice)-1;
611   strcpy(name,(((mumps_files+*type)->mumps_io_pfile_pointer_array)+i)->name);
612   *length=(int)strlen(name)+1;
613   return 0;
614 }
mumps_io_alloc_pointers(int * nb_file_type,int * dim)615 int mumps_io_alloc_pointers(int* nb_file_type,int * dim){
616   int ierr;
617   int i;
618   /* This is called by solve step, we have only one type of files */
619   mumps_io_nb_file_type=*nb_file_type;
620   mumps_files=(mumps_file_type *)malloc(mumps_io_nb_file_type*sizeof(mumps_file_type));
621   if(mumps_files==NULL){
622     return mumps_io_error(-13,"Allocation problem in low-level OOC layer\n");
623   }
624   for(i=0;i<mumps_io_nb_file_type;i++){
625     mumps_io_init_file_struct(dim+i,i);
626     ierr=mumps_io_alloc_file_struct(dim+i,i);
627     if(ierr<0){
628       return ierr;
629     }
630   }
631   return 0;
632 }
mumps_io_init_vars(int * myid_arg,int * size_element,int * async_arg)633 int mumps_io_init_vars(int* myid_arg,int* size_element,int* async_arg){
634 #if ! defined( MUMPS_WIN32 )
635   int k211_loc;
636   int mumps_flag_open;
637 #endif
638   int i;
639   mumps_io_max_file_size=MAX_FILE_SIZE;
640   mumps_directio_flag=0;
641 #if ! defined( MUMPS_WIN32 )
642   mumps_flag_open=0;
643 #endif
644   /* must be changed when we will have more than one file type during solve step */
645   for(i=0;i<mumps_io_nb_file_type;i++){
646 #if ! defined( MUMPS_WIN32 )
647     (mumps_files+i)->mumps_flag_open=mumps_flag_open|O_RDONLY;
648 #else
649     strcpy((mumps_files+i)->mumps_flag_open,"rb");
650 #endif
651   }
652   mumps_io_myid=*myid_arg;
653   mumps_elementary_data_size=*size_element;
654   mumps_io_flag_async=*async_arg;
655   return 0;
656 }
mumps_io_set_file_name(int * indice,char * name,int * length,int * type)657 int mumps_io_set_file_name(int* indice,char* name,int* length,int* type){
658   int i;
659   i=(*indice)-1;
660 /*   *(mumps_io_pfile_name+i)=(char *) malloc((*length)*strlen(name)); */
661 /*   if(*(mumps_io_pfile_name+i)==NULL){ */
662 /*     sprintf(error_str,"Allocation problem in low-level OOC layer"); */
663 /*     return -13; */
664 /*   } */
665   strcpy((((mumps_files+*type)->mumps_io_pfile_pointer_array)+i)->name,name);
666   return 0;
667 }
mumps_io_open_files_for_read()668 int mumps_io_open_files_for_read(){
669   int i,j;
670   mumps_file_struct  *mumps_io_pfile_pointer_array;
671 #if defined (sgi) || defined (__sgi)
672   struct dioattr dio;
673 #endif
674   for(j=0;j<mumps_io_nb_file_type;j++){
675     mumps_io_pfile_pointer_array=(mumps_files+j)->mumps_io_pfile_pointer_array;
676     for(i=0;i<(mumps_files+j)->mumps_io_nb_file;i++){
677 #if ! defined( MUMPS_WIN32 )
678       (mumps_io_pfile_pointer_array+i)->file=open((mumps_io_pfile_pointer_array+i)->name,(mumps_files+j)->mumps_flag_open);
679       if((mumps_io_pfile_pointer_array+i)->file==-1){
680         return mumps_io_sys_error(-90,"Problem while opening OOC file");
681       }
682 #else
683       (mumps_io_pfile_pointer_array+i)->file=fopen((mumps_io_pfile_pointer_array+i)->name,(mumps_files+j)->mumps_flag_open);
684       if((mumps_io_pfile_pointer_array+i)->file==NULL){
685         return mumps_io_error(-90,"Problem while opening OOC file");
686       }
687       (mumps_io_pfile_pointer_array+i)->is_opened=1;
688 #endif
689     }
690   }
691   return 0;
692 }
mumps_io_set_last_file(int * dim,int * type)693 int mumps_io_set_last_file(int* dim,int* type){
694   (mumps_files+*type)->mumps_io_last_file_opened=*dim-1;
695   (mumps_files+*type)->mumps_io_nb_file_opened=*dim;
696   return 0;
697 }
698 #if ! defined( MUMPS_WIN32 ) &&  ! defined (WITHOUT_PTHREAD)
699 # ifdef WITH_PFUNC
mumps_io_protect_pointers()700 int mumps_io_protect_pointers(){
701   pthread_mutex_lock(&mumps_io_pwrite_mutex);
702   return 0;
703 }
mumps_io_unprotect_pointers()704 int mumps_io_unprotect_pointers(){
705   pthread_mutex_unlock(&mumps_io_pwrite_mutex);
706   return 0;
707 }
mumps_io_init_pointers_lock()708 int mumps_io_init_pointers_lock(){
709   pthread_mutex_init(&mumps_io_pwrite_mutex,NULL);
710   return 0;
711 }
mumps_io_destroy_pointers_lock()712 int mumps_io_destroy_pointers_lock(){
713   pthread_mutex_destroy(&mumps_io_pwrite_mutex);
714   return 0;
715 }
716 # endif /*WITH_PFUNC*/
717 #endif /* _WIN32 && WITHOUT_PTHREAD */
mumps_io_read__(void * file,void * loc_addr,size_t size,int local_offset,int type)718  int mumps_io_read__(void * file,void * loc_addr,size_t size,int local_offset,int type){
719   int ret_code;
720 #if ! defined( MUMPS_WIN32 )
721   if(!mumps_directio_flag){
722     ret_code=mumps_io_read_os_buff__(file,loc_addr, size,local_offset);
723     if(ret_code<0){
724       return ret_code;
725     }
726   }
727 #else
728   ret_code=mumps_io_read_win32__(file,loc_addr, size,local_offset);
729   if(ret_code<0){
730     return ret_code;
731   }
732 #endif
733   return 0;
734 }
735 #if ! defined( MUMPS_WIN32 )
mumps_io_read_os_buff__(void * file,void * loc_addr,size_t size,int local_offset)736 int mumps_io_read_os_buff__(void * file,void * loc_addr,size_t size,int local_offset){
737   size_t ret_code;
738   /* printf("Read with buff %d %d %d\n",(int) size, local_offset,*((int *)file)); */
739 # ifdef WITH_PFUNC
740   ret_code=pread(*(int *)file,loc_addr,size,local_offset);
741 # else
742   lseek(*(int *)file,(long) local_offset,SEEK_SET);
743   ret_code=read(*(int *)file,loc_addr,size);
744 # endif
745   if((int) ret_code==-1){
746     return mumps_io_sys_error(-90,"Problem with low level read");
747   }
748   return 0;
749 }
750 #endif
751 #if defined( MUMPS_WIN32 )
mumps_io_read_win32__(void * file,void * loc_addr,size_t size,int local_offset)752 int mumps_io_read_win32__(void * file,void * loc_addr,size_t size,int local_offset){
753   size_t ret_code;
754   fseek(*(FILE **)file,(long) local_offset,SEEK_SET);
755   ret_code=fread(loc_addr,mumps_elementary_data_size,size,*(FILE **)file);
756   if(ret_code!=size){
757     return mumps_io_error(-90,"Problem with I/O operation\n");
758   }
759   return 0;
760 }
761 #endif
mumps_io_write__(void * file,void * loc_addr,size_t write_size,int where,int type)762 int mumps_io_write__(void *file, void *loc_addr, size_t write_size, int where,int type){
763   int ret_code;
764 #if ! defined( MUMPS_WIN32 )
765   if(!mumps_directio_flag){
766     ret_code=mumps_io_write_os_buff__(file,loc_addr, write_size,where);
767     if(ret_code<0){
768       return ret_code;
769     }
770   }
771 #else
772   ret_code=mumps_io_write_win32__(file,loc_addr, write_size,where);
773   if(ret_code<0){
774     return ret_code;
775   }
776 #endif
777   return 0;
778 }
779 #if ! defined( MUMPS_WIN32 )
mumps_io_write_os_buff__(void * file,void * loc_addr,size_t write_size,int where)780 int mumps_io_write_os_buff__(void *file, void *loc_addr, size_t write_size, int where){
781   size_t ret_code;
782   /* printf("write with buff %d %d %d\n",(int) write_size, where,*((int *)file)); */
783 # ifdef WITH_PFUNC
784   ret_code=pwrite(*(int *)file,loc_addr,write_size,where);
785 # else
786   /*in this case all the I/O's are made by the I/O thread => we don't
787     need to protect the file pointer.*/
788   lseek(*(int *)file,(long)where,SEEK_SET);
789   ret_code=write(*(int *)file,loc_addr,write_size);
790 # endif
791   if((int)ret_code==-1){
792     return mumps_io_sys_error(-90,"Problem with low level write");
793   } else if(ret_code!=write_size){
794     return mumps_io_error(-90,"Error not enough space on disk \n");
795   }
796   return 0;
797 }
798 #endif
799 #if defined( MUMPS_WIN32 )
mumps_io_write_win32__(void * file,void * loc_addr,size_t write_size,int where)800 int mumps_io_write_win32__(void *file, void *loc_addr, size_t write_size, int where){
801   size_t ret_code;
802   fseek(*(FILE **)file,(long)where,SEEK_SET);
803   ret_code=fwrite(loc_addr,mumps_elementary_data_size, write_size,*(FILE**)file);
804   if(ret_code!=write_size){
805     return mumps_io_error(-90,"Problem with I/O operation\n");
806   }
807   return 0;
808 }
809 #endif
mumps_compute_file_size(void * file,size_t * size)810 int mumps_compute_file_size(void *file,size_t *size){
811   /* Compute the size of the file pointed by file and return it in
812      size */
813 #if defined(MUMPS_WIN32)
814   /* This works well as soon as we don't use threads under WIN32 */
815   int ret_code;
816   long pos=0;
817   /* Get the current position */
818   pos=ftell(*(FILE **)file);
819   /* Move the file pointer to the end of the file */
820   fseek(*(FILE **)file,0,SEEK_END);
821   /* Get the current position which is in fact the size */
822   *size=(size_t)ftell(*(FILE **)file);
823   /* Restore the old position */
824   fseek(*(FILE **)file,pos,SEEK_SET);
825 #else
826   struct stat file_info;
827   /* fstat does everything :-) */
828   fstat(*(int *)file, &file_info);
829   *size = (size_t)file_info.st_size;
830 #endif
831   return 0;
832 }
833