1 mike 1.1 //%/////////////////////////////////////////////////////////////////////////////
2 //
|
3 kumpf 1.6 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,
|
4 mike 1.1 // The Open Group, Tivoli Systems
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // of this software and associated documentation files (the "Software"), to
8 // deal in the Software without restriction, including without limitation the
9 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 // sell copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
|
12 kumpf 1.6 //
|
13 mike 1.1 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
14 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
15 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
17 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 //
22 //==============================================================================
23 //
24 // Author: Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com)
25 //
26 // Modified By: Michael E. Brasher (mbrasher@bmc.com)
27 //
|
28 kumpf 1.3 // Ramnath Ravindran (Ramnath.Ravindran@compaq.com) 03/21/2002
29 // replaced instances of "| ios::binary" with
30 // PEGASUS_OR_IOS_BINARY
|
31 ramnath 1.2 //
|
32 kumpf 1.5 // Sushma Fernandes. Hewlett-Packard Company
33 // sushma_fernandes@hp.com
34 //
|
35 mike 1.1 //%/////////////////////////////////////////////////////////////////////////////
36
37 #include <fstream>
38 #include <Pegasus/Common/Config.h>
39 #include "InstanceDataFile.h"
40 #include <Pegasus/Common/System.h>
41 #include <Pegasus/Common/FileSystem.h>
42 #include <Pegasus/Common/Destroyer.h>
|
43 kumpf 1.3 #include <Pegasus/Common/Tracer.h>
|
44 mike 1.1
45 PEGASUS_USING_STD;
46
47 PEGASUS_NAMESPACE_BEGIN
48
49 Boolean InstanceDataFile::_openFile(
50 PEGASUS_STD(fstream)& fs,
51 const String& path,
52 int mode)
53 {
|
54 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceDataFile::_openFile()");
55
|
56 mike 1.1 if (FileSystem::openNoCase(fs, path, mode))
|
57 kumpf 1.3 {
58 PEG_METHOD_EXIT();
|
59 mike 1.1 return true;
|
60 kumpf 1.3 }
|
61 mike 1.1
62 //
63 // File does not exist so create it:
64 //
65
66 ArrayDestroyer<char> p(path.allocateCString());
67 fs.open(p.getPointer(), mode);
68
|
69 kumpf 1.3 PEG_METHOD_EXIT();
|
70 mike 1.1 return !!fs;
71 }
72
73 Boolean InstanceDataFile::loadInstance(
74 const String& path,
75 Uint32 index,
76 Uint32 size,
77 Array<Sint8>& data)
78 {
|
79 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceDataFile::loadInstance()");
80
|
81 mike 1.1 //
82 // Open the file:
83 //
84
85 fstream fs;
86
|
87 ramnath 1.2 if (!_openFile(fs, path, ios::in PEGASUS_OR_IOS_BINARY))
|
88 kumpf 1.3 {
89 PEG_METHOD_EXIT();
|
90 mike 1.1 return false;
|
91 kumpf 1.3 }
|
92 mike 1.1
93 //
94 // Postion file pointer:
95 //
96
97 fs.seekg(index);
98
99 if (!fs)
|
100 kumpf 1.3 {
101 PEG_METHOD_EXIT();
|
102 mike 1.1 return false;
|
103 kumpf 1.3 }
|
104 mike 1.1
105 //
106 // Read the instance:
107 //
108
109 data.grow(size, '\0');
110 fs.read((char*)data.getData(), size);
111
112 if (!fs)
|
113 kumpf 1.3 {
114 PEG_METHOD_EXIT();
|
115 mike 1.1 return false;
|
116 kumpf 1.3 }
|
117 mike 1.1
118 //
119 // Close the file:
120 //
121
122 fs.close();
123
|
124 kumpf 1.3 PEG_METHOD_EXIT();
|
125 mike 1.1 return true;
126 }
127
128 Boolean InstanceDataFile::loadAllInstances(
129 const String& path,
130 Array<Sint8>& data)
131 {
|
132 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceDataFile::loadAllInstance()");
133
|
134 mike 1.1 //
135 // Get size of the data file:
136 //
137
138 Uint32 fileSize;
139
140 if (!FileSystem::getFileSizeNoCase(path, fileSize))
|
141 kumpf 1.3 {
142 PEG_METHOD_EXIT();
|
143 mike 1.1 return false;
|
144 kumpf 1.3 }
|
145 mike 1.1
146 //
147 // Open the file:
148 //
149
150 fstream fs;
151
|
152 ramnath 1.2 if (!_openFile(fs, path, ios::in PEGASUS_OR_IOS_BINARY))
|
153 kumpf 1.3 {
154 PEG_METHOD_EXIT();
|
155 mike 1.1 return false;
|
156 kumpf 1.3 }
|
157 mike 1.1
158 //
159 // Suck the entire contents of the file into the data array parameter:
160 //
161
162 data.grow(fileSize, '\0');
163 fs.read((char*)data.getData(), fileSize);
164
165 if (!fs)
|
166 kumpf 1.3 {
167 PEG_METHOD_EXIT();
|
168 mike 1.1 return false;
|
169 kumpf 1.3 }
|
170 mike 1.1
171 //
172 // Close the file:
173 //
174
175 fs.close();
176
|
177 kumpf 1.3 PEG_METHOD_EXIT();
|
178 mike 1.1 return true;
179 }
180
181 Boolean InstanceDataFile::appendInstance(
182 const String& path,
183 const Array<Sint8>& data,
184 Uint32& index)
185 {
|
186 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceDataFile::appendInstance()");
187
|
188 mike 1.1 //
189 // Get size of the data file:
190 //
191
192 if (!FileSystem::getFileSizeNoCase(path, index))
193 index = 0;
194
195 //
196 // Open the file for append:
197 //
198
199 fstream fs;
200
|
201 ramnath 1.2 if (!_openFile(fs, path, ios::app | ios::out PEGASUS_OR_IOS_BINARY))
|
202 kumpf 1.3 {
203 PEG_METHOD_EXIT();
|
204 mike 1.1 return false;
|
205 kumpf 1.3 }
|
206 mike 1.1
207 //
208 // Save index to data:
209 //
210
211 // index = fs.tellp();
212
213 //
214 // Write the instance:
215 //
216
217 fs.write((char*)data.getData(), data.size());
218
219 if (!fs)
|
220 kumpf 1.3 {
221 PEG_METHOD_EXIT();
|
222 mike 1.1 return false;
|
223 kumpf 1.3 }
|
224 mike 1.1
225 //
226 // Close the file:
227 //
228
229 fs.close();
230
|
231 kumpf 1.3 PEG_METHOD_EXIT();
|
232 mike 1.1 return true;
233 }
234
235 Boolean InstanceDataFile::beginTransaction(const String& path)
236 {
|
237 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceDataFile::beginTransaction()");
238
|
239 mike 1.1 Uint32 fileSize;
240
241 //
242 // If the file does not exist, then set the file size to zero:
243 //
244
245 if (!FileSystem::existsNoCase(path))
246 {
247 fileSize = 0;
248 }
249 else
250 {
251 if (!FileSystem::getFileSizeNoCase(path, fileSize))
|
252 kumpf 1.3 {
253 PEG_METHOD_EXIT();
|
254 mike 1.1 return false;
|
255 kumpf 1.3 }
|
256 mike 1.1 }
257
258 //
259 // Open the rollback file:
260 //
261
|
262 kumpf 1.5 // ATTN-SF-P3-20020517: FUTURE: Need to look in to this. Empty rollback
263 // files are getting created in some error conditions.
264
|
265 mike 1.1 fstream fs;
266
|
267 kumpf 1.4 if (!_openFile(fs, path + ".rollback", ios::out PEGASUS_OR_IOS_BINARY))
|
268 kumpf 1.3 {
269 PEG_METHOD_EXIT();
|
270 mike 1.1 return false;
|
271 kumpf 1.3 }
|
272 mike 1.1
273 //
274 // Save the size of the data file in the rollback file.
275 //
276
277 char buffer[9];
278 sprintf(buffer, "%08x", fileSize);
279 fs.write(buffer, strlen(buffer));
280
281 if (!fs)
|
282 kumpf 1.3 {
283 PEG_METHOD_EXIT();
|
284 mike 1.1 return false;
|
285 kumpf 1.3 }
|
286 mike 1.1
287 //
288 // Close the file.
289 //
290
291 fs.close();
292
|
293 kumpf 1.3 PEG_METHOD_EXIT();
|
294 mike 1.1 return true;
295 }
296
297 Boolean InstanceDataFile::rollbackTransaction(const String& path)
298 {
|
299 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceDataFile::rollbackTransaction()");
300
|
301 mike 1.1 //
302 // If rollback file does not exist, then everything is fine, just
303 // return.
304 //
305
|
306 kumpf 1.4 if (!FileSystem::existsNoCase(path + ".rollback"))
|
307 kumpf 1.3 {
308 PEG_METHOD_EXIT();
|
309 mike 1.1 return true;
|
310 kumpf 1.3 }
|
311 mike 1.1
312 //
313 // Open the rollback file:
314 //
315
316 fstream rollbackFs;
317
|
318 kumpf 1.4 if (!_openFile(rollbackFs, path + ".rollback", ios::in PEGASUS_OR_IOS_BINARY))
|
319 kumpf 1.3 {
320 PEG_METHOD_EXIT();
|
321 mike 1.1 return false;
|
322 kumpf 1.3 }
|
323 mike 1.1
324 //
325 // Retrieve the file size from the rollback file:
326 //
327
328 char buffer[9];
329 rollbackFs.read(buffer, 8);
330
331 if (!rollbackFs)
|
332 kumpf 1.3 {
333 PEG_METHOD_EXIT();
|
334 mike 1.1 return false;
|
335 kumpf 1.3 }
|
336 mike 1.1
337 buffer[8] = '\0';
338
339 char* end = 0;
340 long fileSize = strtol(buffer, &end, 16);
341
342 if (!end || *end != '\0' || fileSize < 0)
|
343 kumpf 1.3 {
344 PEG_METHOD_EXIT();
|
345 mike 1.1 return false;
|
346 kumpf 1.3 }
|
347 mike 1.1
348 rollbackFs.close();
349
350 //
351 // Now truncate the data file to that size:
352 //
|
353 kumpf 1.5
354 //
355 // If the fileSize is zero, then create the InstanceDataFile and exit.
356 //
357 if ( fileSize == 0 )
358 {
359 fstream ofs;
360
361 if (!_openFile(ofs, path, ios::out PEGASUS_OR_IOS_BINARY))
362 {
363 PEG_METHOD_EXIT();
364 return false;
365 }
366
367 ofs.close();
368 PEG_METHOD_EXIT();
369 return true;
370 }
|
371 mike 1.1
372 ArrayDestroyer<char> tmp(path.allocateCString());
373
374 if (!System::truncateFile(tmp.getPointer(), fileSize))
|
375 kumpf 1.3 {
376 PEG_METHOD_EXIT();
|
377 mike 1.1 return false;
|
378 kumpf 1.3 }
|
379 mike 1.1
380 //
381 // Now get rid of rollback file!
382 //
383
|
384 kumpf 1.3 PEG_METHOD_EXIT();
|
385 kumpf 1.4 return FileSystem::removeFileNoCase(path + ".rollback");
|
386 mike 1.1 }
387
388 Boolean InstanceDataFile::commitTransaction(const String& path)
389 {
|
390 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceDataFile::commitTransaction()");
391
|
392 mike 1.1 //
393 // To commit the transaction, we simply remove the rollback file:
394 //
395
|
396 kumpf 1.3 PEG_METHOD_EXIT();
|
397 kumpf 1.4 return FileSystem::removeFileNoCase(path + ".rollback");
|
398 mike 1.1 }
399
400 Boolean InstanceDataFile::compact(
401 const String& path,
402 const Array<Uint32>& freeFlags,
403 const Array<Uint32>& indices,
404 const Array<Uint32>& sizes)
405 {
|
406 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceDataFile::compact()");
407
|
408 mike 1.1 //
409 // Open the input file (the data file):
410 //
411
412 fstream fs;
413
|
414 ramnath 1.2 if (!_openFile(fs, path, ios::in PEGASUS_OR_IOS_BINARY))
|
415 kumpf 1.3 {
416 PEG_METHOD_EXIT();
|
417 mike 1.1 return false;
|
418 kumpf 1.3 }
|
419 mike 1.1
420 //
421 // Open the output file (temporary data file):
422 //
423
424 fstream tmpFs;
425
|
426 kumpf 1.4 if (!_openFile(tmpFs, path + ".tmp", ios::out PEGASUS_OR_IOS_BINARY))
|
427 kumpf 1.3 {
428 PEG_METHOD_EXIT();
|
429 mike 1.1 return false;
|
430 kumpf 1.3 }
|
431 mike 1.1
432 Array<Sint8> data;
433
434 //
435 // Copy over instances which have not been freed:
436 //
437
438 for (Uint32 i = 0, n = freeFlags.size(); i < n; i++)
439 {
440 //
441 // If this entry is not free, then copy it over to the
442 // temporary file. Otherwise, pay retail for it.
443 //
444
445 if (!freeFlags[i])
446 {
447 //
448 // Read the next instance:
449 //
450
451 if (!fs.seekg(indices[i]))
|
452 kumpf 1.3 {
453 PEG_METHOD_EXIT();
|
454 mike 1.1 return false;
|
455 kumpf 1.3 }
|
456 mike 1.1
457 data.grow(sizes[i], '\0');
458
459 fs.read((char*)data.getData(), sizes[i]);
460
461 if (!fs)
|
462 kumpf 1.3 {
463 PEG_METHOD_EXIT();
|
464 mike 1.1 return false;
|
465 kumpf 1.3 }
|
466 mike 1.1
467 //
468 // Write out the next instance:
469 //
470
471 tmpFs.write((char*)data.getData(), sizes[i]);
472 }
473 }
474
475 //
476 // Close the files:
477 //
478
479 fs.close();
480 tmpFs.close();
481
482 //
483 // Copy the new file over the old one:
484 //
485
486 if (!FileSystem::removeFileNoCase(path))
|
487 kumpf 1.3 {
488 PEG_METHOD_EXIT();
|
489 mike 1.1 return false;
|
490 kumpf 1.3 }
|
491 mike 1.1
|
492 kumpf 1.4 if (!FileSystem::renameFileNoCase(path + ".tmp", path))
|
493 kumpf 1.3 {
494 PEG_METHOD_EXIT();
|
495 mike 1.1 return false;
|
496 kumpf 1.3 }
|
497 mike 1.1
|
498 kumpf 1.3 PEG_METHOD_EXIT();
|
499 mike 1.1 return true;
500 }
501
502 PEGASUS_NAMESPACE_END
|