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