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