Salome HOME
Updated copyright comment
[modules/kernel.git] / src / Container / Salome_file_i.cxx
1 // Copyright (C) 2007-2024  CEA, EDF, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 //  File   : Salome_file_i.cxx
21 //  Author : AndrĂ© RIBES, EDF
22 //  Module : SALOME
23 //  $Header: 
24 //
25 #include "Salome_file_i.hxx"
26 #include "utilities.h"
27 #include <stdlib.h>
28 #include "HDFOI.hxx"
29 #ifndef WIN32
30 # include <unistd.h>
31 # define _getcwd getcwd
32 # define _open   open
33 #else
34 # include <direct.h>
35 # include <io.h>
36 # include <windows.h>
37 #endif
38
39 /*! \class Salome_file_i
40  *  \brief A class to manage file transfer in %SALOME
41  *
42  */
43
44
45 //=============================================================================
46 /*! 
47  *  Default constructor,
48  */
49 //=============================================================================
50
51 Salome_file_i::Salome_file_i()
52 {
53   _fileId = 0;
54 #ifndef WIN32
55   _path_max = 1 + pathconf("/", _PC_PATH_MAX);
56 #else
57   _path_max = 32768;
58   //from MSDN:
59   //Note The C Runtime supports path lengths up to 32768 characters in length, but it is up to the operating system, specifically the file system, to support these longer paths. The sum of the fields should not exceed _MAX_PATH for full backwards compatibility with Windows 98 FAT32 file systems. Windows NT 4.0, Windows 2000, Windows XP Home Edition, Windows XP Professional, Windows Server 2003, and Windows Server 2003 NTFS file system supports paths up to 32768 characters in length, but only when using the Unicode APIs. When using long path names, prefix the path with the characters \\?\ and use the Unicode versions of the C Runtime functions.
60   //currently #define _MAX_PATH   260
61 #endif
62   _state.name = CORBA::string_dup("");
63   _state.hdf5_file_name = CORBA::string_dup("");
64   _state.number_of_files = 0;
65   _state.files_ok = true;
66   _container = Engines::Container::_nil();
67   _default_source_Salome_file = Engines::Salome_file::_nil();
68 }
69
70 //=============================================================================
71 /*! 
72  *  Destructor
73  */
74 //=============================================================================
75
76 Salome_file_i::~Salome_file_i()
77 {
78 }
79
80 //=============================================================================
81 /*! 
82  *  CORBA method
83  * \see Engines::Salome_file::load
84  */
85 //=============================================================================
86 void 
87 Salome_file_i::load(const char* hdf5_file) {
88   _state.hdf5_file_name = CORBA::string_dup(hdf5_file);
89   try
90   {
91     HDFfile *hdf_file;
92     HDFgroup *hdf_group;
93     HDFdataset *hdf_dataset;
94     size_t size;
95     int fd;
96     char * value;
97     char * buffer;
98
99     hdf_file = new HDFfile((char*) hdf5_file);
100     hdf_file->OpenOnDisk(HDF_RDONLY);
101
102     hdf_group = new HDFgroup("CONFIG",hdf_file); 
103     hdf_group->OpenOnDisk();
104     hdf_dataset = new HDFdataset("MODE",hdf_group);
105     hdf_dataset->OpenOnDisk();
106     size = hdf_dataset->GetSize();
107     value = new char[size];
108     hdf_dataset->ReadFromDisk(value);
109     hdf_dataset->CloseOnDisk();
110     std::string mode(value);
111     delete value;
112     
113     hdf_group = new HDFgroup("GROUP_FILES",hdf_file); 
114     hdf_group->OpenOnDisk();
115     hdf_dataset = new HDFdataset("LIST_OF_FILES",hdf_group);
116     hdf_dataset->OpenOnDisk();
117     size = hdf_dataset->GetSize();
118     value = new char[size];
119     hdf_dataset->ReadFromDisk(value);
120     hdf_dataset->CloseOnDisk();
121     std::string list_of_files(value);
122     delete value;
123
124     std::istringstream iss(list_of_files);
125     std::string file_name;
126     while (std::getline(iss, file_name, ' '))
127     {
128       std::string dataset_group_name("DATASET");
129       dataset_group_name += file_name;
130
131       hdf_group = new HDFgroup(dataset_group_name.c_str(), hdf_file); 
132       hdf_group->OpenOnDisk();
133
134       hdf_dataset = new HDFdataset("NAME",hdf_group);
135       hdf_dataset->OpenOnDisk();
136       size = hdf_dataset->GetSize();
137       value = new char[size];
138       hdf_dataset->ReadFromDisk(value);
139       hdf_dataset->CloseOnDisk();
140       std::string name(value);
141
142       hdf_dataset = new HDFdataset("PATH",hdf_group);
143       hdf_dataset->OpenOnDisk();
144       size = hdf_dataset->GetSize();
145       value = new char[size];
146       hdf_dataset->ReadFromDisk(value);
147       hdf_dataset->CloseOnDisk();
148       std::string path(value);
149
150       hdf_dataset = new HDFdataset("TYPE",hdf_group);
151       hdf_dataset->OpenOnDisk();
152       size = hdf_dataset->GetSize();
153       value = new char[size];
154       hdf_dataset->ReadFromDisk(value);
155       hdf_dataset->CloseOnDisk();
156       std::string type(value);
157
158       hdf_dataset = new HDFdataset("SOURCE_FILE_NAME",hdf_group);
159       hdf_dataset->OpenOnDisk();
160       size = hdf_dataset->GetSize();
161       value = new char[size];
162       hdf_dataset->ReadFromDisk(value);
163       hdf_dataset->CloseOnDisk();
164       std::string source_file_name(value);
165
166       hdf_dataset = new HDFdataset("STATUS",hdf_group);
167       hdf_dataset->OpenOnDisk();
168       size = hdf_dataset->GetSize();
169       value = new char[size];
170       hdf_dataset->ReadFromDisk(value);
171       hdf_dataset->CloseOnDisk();
172       std::string status(value);
173
174       if (mode == "all") {
175
176         // Changing path, is now current directory
177         path = getcwd(NULL, _path_max);
178   
179         std::string group_name("GROUP");
180         group_name += file_name;
181         hdf_group = new HDFgroup(group_name.c_str(),hdf_file); 
182         hdf_group->OpenOnDisk();
183         hdf_dataset = new HDFdataset("FILE DATASET",hdf_group);
184         hdf_dataset->OpenOnDisk();
185         size = hdf_dataset->GetSize();
186         buffer = new char[size];
187       
188         if ( (fd = ::open(file_name.c_str(),O_RDWR|O_CREAT,00666)) <0) { 
189           SALOME::ExceptionStruct es;
190           es.type = SALOME::INTERNAL_ERROR;
191           std::string text = "open failed";
192           es.text = CORBA::string_dup(text.c_str());
193           throw SALOME::SALOME_Exception(es);
194         }
195         hdf_dataset->ReadFromDisk(buffer);
196         if ( write(fd,buffer,(unsigned int)size) <0) {
197           SALOME::ExceptionStruct es;
198           es.type = SALOME::INTERNAL_ERROR;
199           std::string text = "write failed";
200           es.text = CORBA::string_dup(text.c_str());
201           throw SALOME::SALOME_Exception(es);
202         }
203         // Close the target file
204         ::close(fd);
205
206         Engines::file infos;
207         infos.file_name = CORBA::string_dup(file_name.c_str());
208         infos.path = CORBA::string_dup(path.c_str());
209         infos.type = CORBA::string_dup(type.c_str());
210         infos.source_file_name = CORBA::string_dup(source_file_name.c_str());
211         infos.status = CORBA::string_dup(status.c_str());
212
213         _fileManaged[file_name] = infos;
214
215         // Update Salome_file state
216         _state.number_of_files++;
217         _state.files_ok = true;
218       }
219       else {
220         Engines::file infos;
221         infos.file_name = CORBA::string_dup(file_name.c_str());
222         infos.path = CORBA::string_dup(path.c_str());
223         infos.type = CORBA::string_dup(type.c_str());
224         infos.source_file_name = CORBA::string_dup(source_file_name.c_str());
225         infos.status = CORBA::string_dup(status.c_str());
226         // Infos for parallel extensions...
227         infos.node = 0;
228         infos.container = Engines::Container::_duplicate(_container);
229
230         _fileManaged[file_name] = infos;
231
232         // Update Salome_file state
233         _state.number_of_files++;
234         if (status != "ok")
235           _state.files_ok = false;
236       }
237     }
238   }
239   catch (HDFexception)
240   {
241     SALOME::ExceptionStruct es;
242     es.type = SALOME::INTERNAL_ERROR;
243     std::string text = "!!!! HDFexception";
244     es.text = CORBA::string_dup(text.c_str());
245     throw SALOME::SALOME_Exception(es);
246   }
247 }
248
249 //=============================================================================
250 /*! 
251  *  CORBA method
252  * \see Engines::Salome_file::save
253  */
254 //=============================================================================
255 void 
256 Salome_file_i::save(const char* hdf5_file) {
257   _state.hdf5_file_name = CORBA::string_dup(hdf5_file);
258   try
259   {
260     HDFfile *hdf_file;
261     HDFgroup *hdf_group;
262     HDFdataset *hdf_dataset;
263     hdf_size size[1];
264     _t_fileManaged::iterator begin = _fileManaged.begin();
265     _t_fileManaged::iterator end = _fileManaged.end();
266
267     hdf_file = new HDFfile((char*) _state.hdf5_file_name.in());
268     hdf_file->CreateOnDisk();
269
270     // Save mode information
271     hdf_group = new HDFgroup("CONFIG", hdf_file);
272     hdf_group->CreateOnDisk();
273     std::string mode("infos");
274     size[0] = strlen(mode.c_str()) + 1;
275     hdf_dataset = new HDFdataset("MODE", hdf_group, HDF_STRING, size, 1);
276     hdf_dataset->CreateOnDisk();
277     hdf_dataset->WriteOnDisk((void *) mode.c_str());
278     hdf_dataset->CloseOnDisk();
279     hdf_group->CloseOnDisk();
280
281     // List of files that are managed
282     std::string list_of_files;
283     for(;begin!=end;begin++) 
284     {
285       Engines::file file_infos = begin->second;
286       std::string file_name(file_infos.file_name.in());
287
288       list_of_files = list_of_files + file_name + std::string(" ");
289     }
290     hdf_group = new HDFgroup("GROUP_FILES", hdf_file);
291     hdf_group->CreateOnDisk();
292     size[0] = strlen(list_of_files.c_str()) + 1;
293     hdf_dataset = new HDFdataset("LIST_OF_FILES", hdf_group, HDF_STRING, size, 1);
294     hdf_dataset->CreateOnDisk();
295     hdf_dataset->WriteOnDisk((void *) list_of_files.c_str());
296     hdf_dataset->CloseOnDisk();
297     hdf_group->CloseOnDisk();
298
299     // Insert Files into the hdf5_file
300     begin = _fileManaged.begin();
301     for(;begin!=end;begin++) 
302     {
303       Engines::file file_infos = begin->second;
304       std::string file_name(file_infos.file_name.in());
305       std::string comp_file_name(_fileManaged[file_name].path.in());
306       comp_file_name.append(_fileManaged[file_name].file_name.in());
307       std::string dataset_group_name("DATASET");
308       dataset_group_name += std::string(_fileManaged[file_name].file_name.in());
309
310       hdf_group = new HDFgroup((char *) dataset_group_name.c_str(), hdf_file);
311       hdf_group->CreateOnDisk();
312       size[0] = strlen(file_infos.file_name.in()) + 1;
313       hdf_dataset = new HDFdataset("NAME", hdf_group, HDF_STRING, size, 1);
314       hdf_dataset->CreateOnDisk();
315       hdf_dataset->WriteOnDisk((void *) file_infos.file_name.in());
316       hdf_dataset->CloseOnDisk();
317       size[0] = strlen(file_infos.path.in()) + 1;
318       hdf_dataset = new HDFdataset("PATH", hdf_group, HDF_STRING, size, 1);
319       hdf_dataset->CreateOnDisk();
320       hdf_dataset->WriteOnDisk((void *) file_infos.path.in());
321       hdf_dataset->CloseOnDisk();
322       size[0] = strlen(file_infos.type.in()) + 1;
323       hdf_dataset = new HDFdataset("TYPE", hdf_group, HDF_STRING, size, 1);
324       hdf_dataset->CreateOnDisk();
325       hdf_dataset->WriteOnDisk((void *) file_infos.type.in());
326       hdf_dataset->CloseOnDisk();
327       size[0] = strlen(file_infos.source_file_name.in()) + 1;
328       hdf_dataset = new HDFdataset("SOURCE_FILE_NAME", hdf_group, HDF_STRING, size, 1);
329       hdf_dataset->CreateOnDisk();
330       hdf_dataset->WriteOnDisk((void *) file_infos.source_file_name.in());
331       hdf_dataset->CloseOnDisk();
332       size[0] = strlen(file_infos.status.in()) + 1;
333       hdf_dataset = new HDFdataset("STATUS", hdf_group, HDF_STRING, size, 1);
334       hdf_dataset->CreateOnDisk();
335       hdf_dataset->WriteOnDisk((void *) file_infos.status.in());
336       hdf_dataset->CloseOnDisk();
337       hdf_group->CloseOnDisk();
338     }
339
340     hdf_file->CloseOnDisk();
341
342     //      delete hdf_dataset;
343     //      delete hdf_group; ----> SEGFAULT !!!
344     //      delete hdf_file; ----> SEGFAULT !!!
345   }
346   catch (HDFexception)
347   {
348     SALOME::ExceptionStruct es;
349     es.type = SALOME::INTERNAL_ERROR;
350     std::string text = "!!!! HDFexception";
351     es.text = CORBA::string_dup(text.c_str());
352     throw SALOME::SALOME_Exception(es);
353   }
354 }
355
356 //=============================================================================
357 /*! 
358  *  CORBA method
359  * \see Engines::Salome_file::save_all
360  */
361 //=============================================================================
362 void 
363 Salome_file_i::save_all(const char* hdf5_file) {
364
365   _state.hdf5_file_name = CORBA::string_dup(hdf5_file);
366   // Test Salome_file status
367   if (_state.files_ok == false) {
368     SALOME::ExceptionStruct es;
369     es.type = SALOME::INTERNAL_ERROR;
370     std::string text = "File Not Ok !";
371     es.text = CORBA::string_dup(text.c_str());
372     throw SALOME::SALOME_Exception(es);
373   }
374
375   // For each file we create two groups
376   // First group contains file's information
377   // Second group contains the file
378   // At the end we create a group and a dataset containing the names
379   // of all the files.
380   try
381   {
382     HDFfile *hdf_file;
383     HDFgroup *hdf_group;
384     HDFdataset *hdf_dataset;
385     hdf_size size[1];
386     _t_fileManaged::iterator begin = _fileManaged.begin();
387     _t_fileManaged::iterator end = _fileManaged.end();
388
389     hdf_file = new HDFfile((char*) _state.hdf5_file_name.in());
390     hdf_file->CreateOnDisk();
391
392     // Save mode information
393     hdf_group = new HDFgroup("CONFIG", hdf_file);
394     hdf_group->CreateOnDisk();
395     std::string mode("all");
396     size[0] = strlen(mode.c_str()) + 1;
397     hdf_dataset = new HDFdataset("MODE", hdf_group, HDF_STRING, size, 1);
398     hdf_dataset->CreateOnDisk();
399     hdf_dataset->WriteOnDisk((void *) mode.c_str());
400     hdf_dataset->CloseOnDisk();
401     hdf_group->CloseOnDisk();
402
403
404     // List of files that will be inserted
405     std::string list_of_files;
406     for(;begin!=end;begin++) 
407     {
408       Engines::file file_infos = begin->second;
409       std::string file_name(file_infos.file_name.in());
410
411       list_of_files = list_of_files + file_name + std::string(" ");
412     }
413     hdf_group = new HDFgroup("GROUP_FILES", hdf_file);
414     hdf_group->CreateOnDisk();
415     size[0] = strlen(list_of_files.c_str()) + 1;
416     hdf_dataset = new HDFdataset("LIST_OF_FILES", hdf_group, HDF_STRING, size, 1);
417     hdf_dataset->CreateOnDisk();
418     hdf_dataset->WriteOnDisk((void *) list_of_files.c_str());
419     hdf_dataset->CloseOnDisk();
420     hdf_group->CloseOnDisk();
421
422     // Insert Files into the hdf5_file
423     begin = _fileManaged.begin();
424     for(;begin!=end;begin++) 
425     {
426       Engines::file file_infos = begin->second;
427       std::string file_name(file_infos.file_name.in());
428       std::string comp_file_name(_fileManaged[file_name].path.in());
429       comp_file_name.append(_fileManaged[file_name].file_name.in());
430       std::string group_name("GROUP");
431       group_name += std::string(_fileManaged[file_name].file_name.in());
432       std::string dataset_group_name("DATASET");
433       dataset_group_name += std::string(_fileManaged[file_name].file_name.in());
434
435       hdf_group = new HDFgroup((char *) group_name.c_str(), hdf_file);
436       hdf_group->CreateOnDisk();
437       HDFConvert::FromAscii(comp_file_name.c_str(), *hdf_group, "FILE DATASET");
438       hdf_group->CloseOnDisk();
439
440       hdf_group = new HDFgroup((char *) dataset_group_name.c_str(), hdf_file);
441       hdf_group->CreateOnDisk();
442       size[0] = strlen(file_infos.file_name.in()) + 1;
443       hdf_dataset = new HDFdataset("NAME", hdf_group, HDF_STRING, size, 1);
444       hdf_dataset->CreateOnDisk();
445       hdf_dataset->WriteOnDisk((void *) file_infos.file_name.in());
446       hdf_dataset->CloseOnDisk();
447       size[0] = strlen(file_infos.path.in()) + 1;
448       hdf_dataset = new HDFdataset("PATH", hdf_group, HDF_STRING, size, 1);
449       hdf_dataset->CreateOnDisk();
450       hdf_dataset->WriteOnDisk((void *) file_infos.path.in());
451       hdf_dataset->CloseOnDisk();
452       size[0] = strlen(file_infos.type.in()) + 1;
453       hdf_dataset = new HDFdataset("TYPE", hdf_group, HDF_STRING, size, 1);
454       hdf_dataset->CreateOnDisk();
455       hdf_dataset->WriteOnDisk((void *) file_infos.type.in());
456       hdf_dataset->CloseOnDisk();
457       size[0] = strlen(file_infos.source_file_name.in()) + 1;
458       hdf_dataset = new HDFdataset("SOURCE_FILE_NAME", hdf_group, HDF_STRING, size, 1);
459       hdf_dataset->CreateOnDisk();
460       hdf_dataset->WriteOnDisk((void *) file_infos.source_file_name.in());
461       hdf_dataset->CloseOnDisk();
462       size[0] = strlen(file_infos.status.in()) + 1;
463       hdf_dataset = new HDFdataset("STATUS", hdf_group, HDF_STRING, size, 1);
464       hdf_dataset->CreateOnDisk();
465       hdf_dataset->WriteOnDisk((void *) file_infos.status.in());
466       hdf_dataset->CloseOnDisk();
467       hdf_group->CloseOnDisk();
468
469     }
470
471     hdf_file->CloseOnDisk();
472
473     //      delete hdf_dataset;
474     //      delete hdf_group; ----> SEGFAULT !!!
475     //      delete hdf_file; ----> SEGFAULT !!!
476   }
477   catch (HDFexception)
478   {
479     SALOME::ExceptionStruct es;
480     es.type = SALOME::INTERNAL_ERROR;
481     std::string text = "!!!! HDFexception";
482     es.text = CORBA::string_dup(text.c_str());
483     throw SALOME::SALOME_Exception(es);
484   }
485 }
486
487 //=============================================================================
488 /*! 
489  *  CORBA method
490  * \see Engines::Salome_file::setLocalFile
491  */
492 //=============================================================================
493 void 
494 Salome_file_i::setLocalFile(const char* comp_file_name)
495 {
496   std::string file_name("");
497   std::string path("");
498   std::string type("local");
499   std::string source_file_name("");
500   std::string status("not_ok");
501
502   std::string cp_file_name(comp_file_name);
503   std::size_t index = cp_file_name.rfind("/");
504   if (index != std::string::npos)
505   {
506     file_name = cp_file_name.substr(index+1);
507     path =  cp_file_name.substr(0,index+1);
508   }
509   else
510   {
511     file_name = comp_file_name;    
512     path = getcwd(NULL, _path_max);;
513   }
514
515   // Test if this file is already added
516   _t_fileManaged::iterator it = _fileManaged.find(file_name);
517   if (it != _fileManaged.end()) 
518   {
519     SALOME::ExceptionStruct es;
520     es.type = SALOME::INTERNAL_ERROR;
521     std::string text = "file already added";
522     es.text = CORBA::string_dup(text.c_str());
523     throw SALOME::SALOME_Exception(es);
524   }
525
526   // Test if the file is ok
527   if(fopen(comp_file_name,"rb") != NULL)
528     status = "ok";
529
530   // Adding file with its information
531   Engines::file infos;
532   infos.file_name = CORBA::string_dup(file_name.c_str());
533   infos.path = CORBA::string_dup(path.c_str());
534   infos.type = CORBA::string_dup(type.c_str());
535   infos.source_file_name = CORBA::string_dup(source_file_name.c_str());
536   infos.status = CORBA::string_dup(status.c_str());
537   // Infos for parallel extensions...
538   infos.node = 0;
539   infos.container = Engines::Container::_duplicate(_container);
540
541   _fileManaged[file_name] = infos;
542
543   // Update Salome_file state
544   _state.number_of_files++;
545   if (status != "ok")
546     _state.files_ok = false;
547 }
548
549 //=============================================================================
550 /*! 
551  *  CORBA method
552  * \see Engines::Salome_file::setDistributedFile
553  */
554 //=============================================================================
555 void 
556 Salome_file_i::setDistributedFile(const char* comp_file_name)
557 {
558   std::string file_name("");
559   std::string path("");
560   std::string type("distributed");
561   std::string source_file_name("");
562   std::string status("not_ok");
563
564   std::string cp_file_name(comp_file_name);
565   std::size_t index = cp_file_name.rfind("/");
566   if (index != std::string::npos)
567   {
568     file_name = cp_file_name.substr(index+1);
569     path =  cp_file_name.substr(0,index+1);
570   }
571   else
572   {
573     file_name = comp_file_name;
574     path = getcwd(NULL, _path_max);;
575   }
576
577   // Test if this file is already added
578   _t_fileManaged::iterator it = _fileManaged.find(file_name);
579   if (it != _fileManaged.end()) 
580   {
581     SALOME::ExceptionStruct es;
582     es.type = SALOME::INTERNAL_ERROR;
583     std::string text = "file already added";
584     es.text = CORBA::string_dup(text.c_str());
585     throw SALOME::SALOME_Exception(es);
586   }
587
588   // Adding file with its information
589   Engines::file infos;
590   infos.file_name = CORBA::string_dup(file_name.c_str());
591   infos.path = CORBA::string_dup(path.c_str());
592   infos.type = CORBA::string_dup(type.c_str());
593   infos.source_file_name = CORBA::string_dup(source_file_name.c_str());
594   infos.status = CORBA::string_dup(status.c_str());
595   // Infos for parallel extensions...
596   infos.node = 0;
597   infos.container = Engines::Container::_duplicate(_container);
598
599   _fileManaged[file_name] = infos;
600
601   if(!CORBA::is_nil(_default_source_Salome_file)) 
602   {
603     _fileDistributedSource[file_name] = 
604       Engines::Salome_file::_duplicate(_default_source_Salome_file);
605   }
606
607   // Update Salome_file state
608   _state.number_of_files++;
609   _state.files_ok = false;
610 }
611
612 //=============================================================================
613 /*! 
614  *  CORBA method
615  * \see Engines::Salome_file::connect
616  */
617 //=============================================================================
618 void
619 Salome_file_i::connect(Engines::Salome_file_ptr source_Salome_file) 
620 {
621   if(CORBA::is_nil(_default_source_Salome_file)) 
622   {
623     _default_source_Salome_file = Engines::Salome_file::_duplicate(source_Salome_file);
624     _t_fileManaged::iterator begin = _fileManaged.begin();
625     _t_fileManaged::iterator end = _fileManaged.end();
626     for(;begin!=end;begin++) {
627       // Get the name of the file
628       std::string file_name = begin->first;
629       _t_fileDistributedSource::iterator it = _fileDistributedSource.find(file_name);
630       if (it == _fileDistributedSource.end()) 
631       {
632         _fileDistributedSource[file_name] = Engines::Salome_file::_duplicate(source_Salome_file);
633       }
634     }
635   }
636   else
637   {
638     SALOME::ExceptionStruct es;
639     es.type = SALOME::INTERNAL_ERROR;
640     std::string text = "already connected to a default Salome_file";
641     es.text = CORBA::string_dup(text.c_str());
642     throw SALOME::SALOME_Exception(es);
643   }
644   // We can connect this Salome_file if there is only one file managed
645   // by the Salome_file
646   //std::string fname;
647   //if (_fileManaged.size() == 1) 
648   //{
649     // only one file managed 
650   //  _t_fileManaged::iterator it = _fileManaged.begin();
651   //  fname = it->first;
652   //  _fileDistributedSource[fname] = Engines::Salome_file::_duplicate(source_Salome_file);
653   //}
654   //else 
655   //{
656   //  SALOME::ExceptionStruct es;
657   //  es.type = SALOME::INTERNAL_ERROR;
658   //  std::string text = "cannot connect";
659    // es.text = CORBA::string_dup(text.c_str());
660    // throw SALOME::SALOME_Exception(es);
661   //}
662 }
663
664 //=============================================================================
665 /*! 
666  *  CORBA method
667  * \see Engines::Salome_file::connectDistributedFile
668  */
669 //=============================================================================
670 void
671 Salome_file_i::connectDistributedFile(const char * file_name,
672                                       Engines::Salome_file_ptr source_Salome_file) 
673 {
674   // Test if this file is added
675   _t_fileManaged::iterator it = _fileManaged.find(file_name);
676   if (it == _fileManaged.end()) 
677   {
678     SALOME::ExceptionStruct es;
679     es.type = SALOME::INTERNAL_ERROR;
680     std::string text = "file is not added";
681     es.text = CORBA::string_dup(text.c_str());
682     throw SALOME::SALOME_Exception(es);
683   }
684   else 
685   {
686     _fileDistributedSource[file_name] = Engines::Salome_file::_duplicate(source_Salome_file);
687   }
688 }
689
690 //=============================================================================
691 /*! 
692  *  CORBA method
693  * \see Engines::Salome_file::setDistributedSourceFile
694  */
695 //=============================================================================
696 void 
697 Salome_file_i::setDistributedSourceFile(const char* file_name,
698                                         const char * source_file_name)
699 {
700   std::string fname(file_name);
701
702   // Test if this file is added
703   _t_fileManaged::iterator it = _fileManaged.find(fname);
704   if (it == _fileManaged.end()) 
705   {
706     SALOME::ExceptionStruct es;
707     es.type = SALOME::INTERNAL_ERROR;
708     std::string text = "file is not added";
709     es.text = CORBA::string_dup(text.c_str());
710     throw SALOME::SALOME_Exception(es);
711   }
712   else 
713   {
714     _fileManaged[fname].source_file_name = CORBA::string_dup(source_file_name);
715   }
716 }
717
718 //=============================================================================
719 /*! 
720  *  CORBA method
721  * \see Engines::Salome_file::recvFiles
722  */
723 //=============================================================================
724 void 
725 Salome_file_i::recvFiles() {
726   
727   std::string files_not_ok("");
728
729   _t_fileManaged::iterator begin = _fileManaged.begin();
730   _t_fileManaged::iterator end = _fileManaged.end();
731   for(;begin!=end;begin++) 
732   {
733     bool result = true;
734     Engines::file file_infos = begin->second;
735     // Test if the file is local or distributed
736     if (std::string(file_infos.type.in()) == "local")
737     {
738       if (std::string(file_infos.status.in()) == "not_ok")
739         result = checkLocalFile(file_infos.file_name.in());
740     }
741     else
742     {
743       if (std::string(file_infos.status.in()) == "not_ok")
744         result = getDistributedFile(file_infos.file_name.in());
745     }
746     // if the result is false
747     // we add this file to files_not_ok
748     if (!result) 
749     {
750       files_not_ok.append(" ");
751       files_not_ok.append(file_infos.file_name.in());
752     }
753   }
754
755   if (files_not_ok != "")
756   {
757     SALOME::ExceptionStruct es;
758     es.type = SALOME::INTERNAL_ERROR;
759     std::string text = "files not ready : " + files_not_ok;
760     es.text = CORBA::string_dup(text.c_str());
761     throw SALOME::SALOME_Exception(es);
762   }
763   else
764   {
765     // We change the state of the Salome_file
766     _state.files_ok = true;
767   }
768 }
769
770 //=============================================================================
771 /*! 
772  *  local C++ method : This method is used by revFiles to check if a local 
773  *  managed file is ok.
774  *  \param  fileName name of the file
775  */
776 //=============================================================================
777 bool
778 Salome_file_i::checkLocalFile(std::string file_name)
779 {
780   bool result = true;
781
782   std::string comp_file_name(_fileManaged[file_name].path.in());
783   comp_file_name.append("/");
784   comp_file_name.append(_fileManaged[file_name].file_name.in());
785   if(fopen(comp_file_name.c_str(),"rb") == NULL)
786   {
787     INFOS("file " << comp_file_name << " cannot be open for reading");
788     _fileManaged[file_name].status = CORBA::string_dup("not_ok");
789     result = false;
790   }
791
792   if (result)
793   {
794     _fileManaged[file_name].status = CORBA::string_dup("ok");
795   }
796   return result;
797 }
798
799 //=============================================================================
800 /*! 
801  *  local C++ method : this method is used by recvFiles to get a 
802  *  distributed file from is distributed source.
803  *  If there is no source_file_name for the file, it tries to get
804  *  the file from the source. In this case, the source distributed file has to managed
805  *  only one file to be able to the send the file.
806  *
807  *  \param  fileName name of the file
808  */
809 //=============================================================================
810 bool
811 Salome_file_i::getDistributedFile(std::string file_name)
812 {
813   bool result = true;
814   const char * source_file_name = _fileManaged[file_name].source_file_name.in();
815   int fileId;
816   FILE* fp;
817   std::string comp_file_name(_fileManaged[file_name].path.in());
818   comp_file_name.append("/");
819   comp_file_name.append(_fileManaged[file_name].file_name.in());
820
821   // Test if the process can write on disk
822   if ((fp = fopen(comp_file_name.c_str(),"wb")) == NULL)
823   {
824     INFOS("file " << comp_file_name << " cannot be open for writing");
825     _fileManaged[file_name].status = CORBA::string_dup("not_ok");
826     result = false;
827     return result;
828   }
829
830   try 
831   {
832     fileId = _fileDistributedSource[file_name]->open(source_file_name);
833   }
834   catch (...) 
835   {
836     _fileManaged[file_name].status = CORBA::string_dup("not_ok");
837     fclose(fp);
838     result = false;
839     return result;
840   }
841
842   if (fileId > 0)
843   {
844     Engines::fileBlock* aBlock;
845     int toFollow = 1;
846     int ctr=0;
847     MESSAGE("begin of transfer of " << comp_file_name);
848     while (toFollow)
849     {
850       ctr++;
851       aBlock = _fileDistributedSource[file_name]->getBlock(fileId);
852       toFollow = aBlock->length();
853       CORBA::Octet *buf = aBlock->get_buffer();
854 #if defined(_DEBUG_) || defined(_DEBUG)
855       int nbWri = fwrite(buf, sizeof(CORBA::Octet), toFollow, fp);
856       ASSERT(nbWri == toFollow);
857 #else
858       fwrite(buf, sizeof(CORBA::Octet), toFollow, fp);
859 #endif
860       delete aBlock;
861     }
862     fclose(fp);
863     MESSAGE("end of transfer of " << comp_file_name);
864     _fileDistributedSource[file_name]->close(fileId);
865   }
866   else
867   {
868     INFOS("open reference file for copy impossible");
869     result = false;
870     fclose(fp);
871     _fileManaged[file_name].status = CORBA::string_dup("not_ok");
872     return result;
873   }
874
875   _fileManaged[file_name].status = CORBA::string_dup("ok");
876   return result;
877 }
878
879 //=============================================================================
880 /*! 
881  *  CORBA method
882  * \see Engines::Salome_file::removeFile
883  */
884 //=============================================================================
885 void 
886 Salome_file_i::removeFile(const char* /*file_name*/) 
887 {
888   MESSAGE("Salome_file_i::removeFile : NOT YET IMPLEMENTED");
889 }
890     
891 //=============================================================================
892 /*! 
893  *  CORBA method
894  * \see Engines::Salome_file::removeFiles
895  */
896 //=============================================================================
897 void 
898 Salome_file_i::removeFiles() {
899   MESSAGE("Salome_file_i::removeFiles : NOT YET IMPLEMENTED");
900 }
901
902 //=============================================================================
903 /*! 
904  *  CORBA method
905  * \see Engines::Salome_file::getFilesInfos
906  */
907 //=============================================================================
908 Engines::files* 
909 Salome_file_i::getFilesInfos() {
910
911   Engines::files * infos = new Engines::files();
912   infos->length((CORBA::ULong)_fileManaged.size());
913
914   _t_fileManaged::iterator begin = _fileManaged.begin();
915   _t_fileManaged::iterator end = _fileManaged.end();
916   int i = 0;
917   for(;begin!=end;begin++) {
918     (*infos)[i] = *(new Engines::file(begin->second));
919     i++;
920   }
921   return infos;
922 }
923
924 //=============================================================================
925 /*! 
926  *  CORBA method
927  * \see Engines::Salome_file::getFileInfos
928  */
929 //=============================================================================
930 Engines::file* 
931 Salome_file_i::getFileInfos(const char* file_name) {
932
933   std::string fname(file_name);
934
935   // Test if this file is managed
936   _t_fileManaged::iterator it = _fileManaged.find(fname);
937   if (it == _fileManaged.end()) 
938   {
939     SALOME::ExceptionStruct es;
940     es.type = SALOME::INTERNAL_ERROR;
941     es.text = "file is not managed";
942     throw SALOME::SALOME_Exception(es);
943   }
944
945   Engines::file * infos = new Engines::file(_fileManaged[fname]);
946   return infos;
947 }
948
949 //=============================================================================
950 /*! 
951  *  CORBA method
952  * \see Engines::Salome_file::getSalome_fileState
953  */
954 //=============================================================================
955 Engines::SfState* 
956 Salome_file_i::getSalome_fileState() 
957 {
958   return new Engines::SfState(_state);
959 }
960
961 //=============================================================================
962 /*! 
963  *  CORBA method: try to open the file given. If the file is readable, return
964  *  a positive integer else return 0;
965  *  \param  fileName file name to be transferred
966  *  \return fileId = positive integer > 0 if open OK.
967  */
968 //=============================================================================
969
970 CORBA::Long 
971 Salome_file_i::open(const char* file_name)
972 {
973   int aKey = 0;
974
975   std::string fname(file_name);
976   if (fname == "") {
977     // We enter in the simple case where the user
978     // has not used setDistributedSourceFile.
979     // In this case we try to see if the Salome_file
980     if (_fileManaged.size() == 1) 
981     {
982       // only one file managed 
983       _t_fileManaged::iterator it = _fileManaged.begin();
984       fname = it->first;
985     }
986     else
987     {
988       // we can't choose the file so :
989       return aKey;
990     }
991   }
992
993   _t_fileManaged::iterator it = _fileManaged.find(fname);
994   if (it == _fileManaged.end())
995   {
996     return aKey;
997   }
998   
999   std::string comp_file_name(_fileManaged[fname].path.in());
1000   comp_file_name.append("/");
1001   comp_file_name.append(fname);
1002   MESSAGE("Salome_file_i::open " << comp_file_name);
1003   FILE* fp;
1004   if ((fp = fopen(comp_file_name.c_str(),"rb")) == NULL)
1005     {
1006       INFOS("file " << comp_file_name << " is not readable");
1007       return aKey;
1008     }
1009
1010   aKey = ++_fileId;
1011   _fileAccess[aKey] = fp;
1012   return aKey;
1013 }
1014
1015 //=============================================================================
1016 /*! 
1017  *  CORBA method: close the file associated to the fileId given at open.
1018  *  \param fileId got in return from open method
1019  */
1020 //=============================================================================
1021
1022 void 
1023 Salome_file_i::close(CORBA::Long fileId)
1024 {
1025   MESSAGE("Salome_file_i::close");
1026   FILE* fp;
1027   if (!(fp = _fileAccess[fileId]) )
1028     {
1029       INFOS(" no FILE structure associated to fileId " << fileId);
1030     }
1031   else fclose(fp);
1032 }
1033
1034 //=============================================================================
1035 /*! 
1036  *  CORBA method: get a block of data from the file associated to the fileId
1037  *  given at open.
1038  *  \param fileId got in return from open method
1039  *  \return an octet sequence. Last one is empty.
1040  */
1041 //=============================================================================
1042
1043 #define FILEBLOCK_SIZE 256*1024
1044
1045 Engines::fileBlock* 
1046 Salome_file_i::getBlock(CORBA::Long fileId)
1047 {
1048   Engines::fileBlock* aBlock = new Engines::fileBlock;
1049
1050   FILE* fp;
1051   if (! (fp = _fileAccess[fileId]) )
1052   {
1053     INFOS(" no FILE structure associated to fileId " <<fileId);
1054     return aBlock;
1055   }
1056
1057   // use replace member function for sequence to avoid copy
1058   // see Advanced CORBA Programming with C++ pp 187-194
1059   CORBA::Octet *buf;
1060   buf = Engines::fileBlock::allocbuf(FILEBLOCK_SIZE);
1061   size_t nbRed = fread(buf, sizeof(CORBA::Octet), FILEBLOCK_SIZE, fp);
1062   aBlock->replace((CORBA::ULong)nbRed, (CORBA::ULong)nbRed, buf, 1); // 1 means give ownership //!< TODO: conversion from size_t to CORBA::ULong
1063   return aBlock;
1064 }
1065
1066 void 
1067 Salome_file_i::setContainer(Engines::Container_ptr container)
1068 {
1069   _container = Engines::Container::_duplicate(container);
1070
1071   // Update All the files
1072   _t_fileManaged::iterator begin = _fileManaged.begin();
1073   _t_fileManaged::iterator end = _fileManaged.end();
1074   for(;begin!=end;begin++) {
1075     begin->second.container = Engines::Container::_duplicate(container);
1076   }
1077 }
1078