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