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