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 //%/////////////////////////////////////////////////////////////////////////////
33
34 #include <fstream>
35 #include <Pegasus/Common/Config.h>
36 #include "InstanceDataFile.h"
37 #include <Pegasus/Common/System.h>
38 #include <Pegasus/Common/FileSystem.h>
|
39 kumpf 1.3 #include <Pegasus/Common/Tracer.h>
|
40 mike 1.1
41 PEGASUS_USING_STD;
42
43 PEGASUS_NAMESPACE_BEGIN
44
45 Boolean InstanceDataFile::_openFile(
46 PEGASUS_STD(fstream)& fs,
47 const String& path,
48 int mode)
49 {
|
50 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceDataFile::_openFile()");
|
51 mday 1.8 #if defined(__GNUC__) && GCC_VERSION >= 30200
52 if (FileSystem::openNoCase(fs, path, PEGASUS_STD(ios_base::openmode)(mode)))
53 #else
|
54 mike 1.1 if (FileSystem::openNoCase(fs, path, mode))
|
55 mday 1.8 #endif
|
56 kumpf 1.3 {
|
57 mday 1.9 PEG_METHOD_EXIT();
58 return true;
|
59 kumpf 1.3 }
|
60 mday 1.10 #if defined(__GNUC__) && GCC_VERSION >= 30200
61 fs.open(path.getCString(), PEGASUS_STD(ios_base::openmode)(mode));
62 #else
|
63 david 1.14 fs.open(path.getCString(), mode);
|
64 david 1.11 #endif
|
65 kumpf 1.3 PEG_METHOD_EXIT();
|
66 mike 1.1 return !!fs;
67 }
68
69 Boolean InstanceDataFile::loadInstance(
|
70 david.dillard 1.19 const String& path,
|
71 mike 1.1 Uint32 index,
|
72 david.dillard 1.19 Uint32 size,
|
73 mike 1.21 Buffer& data)
|
74 mike 1.1 {
|
75 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceDataFile::loadInstance()");
76
|
77 mike 1.1 //
78 // Open the file:
79 //
80
81 fstream fs;
82
|
83 ramnath 1.2 if (!_openFile(fs, path, ios::in PEGASUS_OR_IOS_BINARY))
|
84 kumpf 1.3 {
85 PEG_METHOD_EXIT();
|
86 david.dillard 1.19 return false;
|
87 kumpf 1.3 }
|
88 mike 1.1
89 //
90 // Postion file pointer:
91 //
92
93 fs.seekg(index);
94
95 if (!fs)
|
96 kumpf 1.3 {
97 PEG_METHOD_EXIT();
|
98 david.dillard 1.19 return false;
|
99 kumpf 1.3 }
|
100 mike 1.1
101 //
102 // Read the instance:
103 //
104
105 data.grow(size, '\0');
106 fs.read((char*)data.getData(), size);
107
108 if (!fs)
|
109 kumpf 1.3 {
110 PEG_METHOD_EXIT();
|
111 david.dillard 1.19 return false;
|
112 kumpf 1.3 }
|
113 mike 1.1
114 //
115 // Close the file:
116 //
117
118 fs.close();
119
|
120 kumpf 1.3 PEG_METHOD_EXIT();
|
121 mike 1.1 return true;
122 }
123
124 Boolean InstanceDataFile::loadAllInstances(
|
125 david.dillard 1.19 const String& path,
|
126 mike 1.21 Buffer& data)
|
127 mike 1.1 {
|
128 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceDataFile::loadAllInstance()");
129
|
130 mike 1.1 //
131 // Get size of the data file:
132 //
133
134 Uint32 fileSize;
135
136 if (!FileSystem::getFileSizeNoCase(path, fileSize))
|
137 kumpf 1.3 {
138 PEG_METHOD_EXIT();
|
139 david.dillard 1.19 return false;
|
140 kumpf 1.3 }
|
141 mike 1.1
142 //
143 // Open the file:
144 //
145
146 fstream fs;
147
|
148 ramnath 1.2 if (!_openFile(fs, path, ios::in PEGASUS_OR_IOS_BINARY))
|
149 kumpf 1.3 {
150 PEG_METHOD_EXIT();
|
151 david.dillard 1.19 return false;
|
152 kumpf 1.3 }
|
153 mike 1.1
154 //
155 // Suck the entire contents of the file into the data array parameter:
156 //
157
158 data.grow(fileSize, '\0');
159 fs.read((char*)data.getData(), fileSize);
160
161 if (!fs)
|
162 kumpf 1.3 {
163 PEG_METHOD_EXIT();
|
164 david.dillard 1.19 return false;
|
165 kumpf 1.3 }
|
166 mike 1.1
167 //
168 // Close the file:
169 //
170
171 fs.close();
172
|
173 kumpf 1.3 PEG_METHOD_EXIT();
|
174 mike 1.1 return true;
175 }
176
177 Boolean InstanceDataFile::appendInstance(
|
178 david.dillard 1.19 const String& path,
|
179 mike 1.21 const Buffer& data,
|
180 mike 1.1 Uint32& index)
181 {
|
182 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceDataFile::appendInstance()");
183
|
184 mike 1.1 //
185 // Get size of the data file:
186 //
187
188 if (!FileSystem::getFileSizeNoCase(path, index))
|
189 david.dillard 1.19 index = 0;
|
190 mike 1.1
191 //
192 // Open the file for append:
193 //
194
195 fstream fs;
196
|
197 ramnath 1.2 if (!_openFile(fs, path, ios::app | ios::out PEGASUS_OR_IOS_BINARY))
|
198 kumpf 1.3 {
199 PEG_METHOD_EXIT();
|
200 david.dillard 1.19 return false;
|
201 kumpf 1.3 }
|
202 mike 1.1
203 //
204 // Save index to data:
205 //
206
207 // index = fs.tellp();
208
209 //
210 // Write the instance:
211 //
212
213 fs.write((char*)data.getData(), data.size());
214
215 if (!fs)
|
216 kumpf 1.3 {
217 PEG_METHOD_EXIT();
|
218 david.dillard 1.19 return false;
|
219 kumpf 1.3 }
|
220 mike 1.1
221 //
222 // Close the file:
223 //
224
225 fs.close();
226
|
227 kumpf 1.3 PEG_METHOD_EXIT();
|
228 mike 1.1 return true;
229 }
230
231 Boolean InstanceDataFile::beginTransaction(const String& path)
232 {
|
233 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceDataFile::beginTransaction()");
234
|
235 mike 1.1 Uint32 fileSize;
236
237 //
238 // If the file does not exist, then set the file size to zero:
239 //
240
241 if (!FileSystem::existsNoCase(path))
242 {
|
243 david.dillard 1.19 fileSize = 0;
|
244 mike 1.1 }
245 else
246 {
|
247 david.dillard 1.19 if (!FileSystem::getFileSizeNoCase(path, fileSize))
|
248 kumpf 1.3 {
249 PEG_METHOD_EXIT();
|
250 david.dillard 1.19 return false;
|
251 kumpf 1.3 }
|
252 mike 1.1 }
253
254 //
255 // Open the rollback file:
256 //
257
|
258 kumpf 1.5 // ATTN-SF-P3-20020517: FUTURE: Need to look in to this. Empty rollback
259 // files are getting created in some error conditions.
260
|
261 mike 1.1 fstream fs;
262
|
263 kumpf 1.4 if (!_openFile(fs, path + ".rollback", ios::out PEGASUS_OR_IOS_BINARY))
|
264 kumpf 1.3 {
265 PEG_METHOD_EXIT();
|
266 david.dillard 1.19 return false;
|
267 kumpf 1.3 }
|
268 mike 1.1
269 //
270 // Save the size of the data file in the rollback file.
271 //
272
273 char buffer[9];
274 sprintf(buffer, "%08x", fileSize);
|
275 david.dillard 1.19 fs.write(buffer, static_cast<streamsize>(strlen(buffer)));
|
276 mike 1.1
277 if (!fs)
|
278 kumpf 1.3 {
279 PEG_METHOD_EXIT();
|
280 david.dillard 1.19 return false;
|
281 kumpf 1.3 }
|
282 mike 1.1
283 //
284 // Close the file.
285 //
286
|
287 mateus.baur 1.28 FileSystem::syncWithDirectoryUpdates(fs);
|
288 mike 1.1 fs.close();
289
|
290 kumpf 1.3 PEG_METHOD_EXIT();
|
291 mike 1.1 return true;
292 }
293
294 Boolean InstanceDataFile::rollbackTransaction(const String& path)
295 {
|
296 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceDataFile::rollbackTransaction()");
297
|
298 mike 1.1 //
299 // If rollback file does not exist, then everything is fine, just
300 // return.
301 //
302
|
303 kumpf 1.4 if (!FileSystem::existsNoCase(path + ".rollback"))
|
304 kumpf 1.3 {
305 PEG_METHOD_EXIT();
|
306 david.dillard 1.19 return true;
|
307 kumpf 1.3 }
|
308 mike 1.1
309 //
310 // Open the rollback file:
311 //
312
313 fstream rollbackFs;
314
|
315 kumpf 1.25 if (!_openFile(
316 rollbackFs, path + ".rollback", ios::in PEGASUS_OR_IOS_BINARY))
|
317 kumpf 1.3 {
318 PEG_METHOD_EXIT();
|
319 david.dillard 1.19 return false;
|
320 kumpf 1.3 }
|
321 mike 1.1
322 //
323 // Retrieve the file size from the rollback file:
324 //
325
326 char buffer[9];
327 rollbackFs.read(buffer, 8);
328
329 if (!rollbackFs)
|
330 kumpf 1.3 {
331 PEG_METHOD_EXIT();
|
332 david.dillard 1.19 return false;
|
333 kumpf 1.3 }
|
334 mike 1.1
335 buffer[8] = '\0';
336
337 char* end = 0;
338 long fileSize = strtol(buffer, &end, 16);
339
340 if (!end || *end != '\0' || fileSize < 0)
|
341 kumpf 1.3 {
342 PEG_METHOD_EXIT();
|
343 david.dillard 1.19 return false;
|
344 kumpf 1.3 }
|
345 mike 1.1
346 rollbackFs.close();
347
348 //
|
349 kumpf 1.24 // If the instance data file does not yet exist, create it
|
350 mike 1.1 //
|
351 kumpf 1.5
|
352 kumpf 1.24 if (fileSize == 0)
|
353 kumpf 1.5 {
354 fstream ofs;
355
356 if (!_openFile(ofs, path, ios::out PEGASUS_OR_IOS_BINARY))
357 {
358 PEG_METHOD_EXIT();
359 return false;
360 }
361
362 ofs.close();
363 }
|
364 mike 1.1
|
365 kumpf 1.24 //
366 // Truncate the data file to its initial size
367 //
368
|
369 kumpf 1.7 if (!System::truncateFile(path.getCString(), fileSize))
|
370 kumpf 1.3 {
371 PEG_METHOD_EXIT();
|
372 david.dillard 1.19 return false;
|
373 kumpf 1.3 }
|
374 mike 1.1
375 //
376 // Now get rid of rollback file!
377 //
378
|
379 kumpf 1.3 PEG_METHOD_EXIT();
|
380 kumpf 1.4 return FileSystem::removeFileNoCase(path + ".rollback");
|
381 mike 1.1 }
382
383 Boolean InstanceDataFile::commitTransaction(const String& path)
384 {
|
385 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceDataFile::commitTransaction()");
386
|
387 mike 1.1 //
388 // To commit the transaction, we simply remove the 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::compact(
396 const String& path,
397 const Array<Uint32>& freeFlags,
398 const Array<Uint32>& indices,
399 const Array<Uint32>& sizes)
400 {
|
401 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceDataFile::compact()");
402
|
403 mike 1.1 //
404 // Open the input file (the data file):
405 //
406
407 fstream fs;
408
|
409 ramnath 1.2 if (!_openFile(fs, path, ios::in PEGASUS_OR_IOS_BINARY))
|
410 kumpf 1.3 {
411 PEG_METHOD_EXIT();
|
412 david.dillard 1.19 return false;
|
413 kumpf 1.3 }
|
414 mike 1.1
415 //
416 // Open the output file (temporary data file):
417 //
418
419 fstream tmpFs;
420
|
421 kumpf 1.4 if (!_openFile(tmpFs, path + ".tmp", ios::out PEGASUS_OR_IOS_BINARY))
|
422 kumpf 1.3 {
423 PEG_METHOD_EXIT();
|
424 david.dillard 1.19 return false;
|
425 kumpf 1.3 }
|
426 mike 1.1
|
427 mike 1.21 Buffer data;
|
428 mike 1.1
429 //
430 // Copy over instances which have not been freed:
431 //
432
433 for (Uint32 i = 0, n = freeFlags.size(); i < n; i++)
434 {
|
435 david.dillard 1.19 //
436 // If this entry is not free, then copy it over to the
437 // temporary file. Otherwise, pay retail for it.
438 //
439
440 if (!freeFlags[i])
441 {
442 //
443 // Read the next instance:
444 //
|
445 mike 1.1
|
446 david.dillard 1.19 if (!fs.seekg(indices[i]))
|
447 kumpf 1.3 {
448 PEG_METHOD_EXIT();
|
449 david.dillard 1.19 return false;
|
450 kumpf 1.3 }
|
451 mike 1.1
|
452 david.dillard 1.19 data.grow(sizes[i], '\0');
|
453 mike 1.1
|
454 david.dillard 1.19 fs.read((char*)data.getData(), sizes[i]);
|
455 mike 1.1
|
456 david.dillard 1.19 if (!fs)
|
457 kumpf 1.3 {
458 PEG_METHOD_EXIT();
|
459 david.dillard 1.19 return false;
|
460 kumpf 1.3 }
|
461 mike 1.1
|
462 david.dillard 1.19 //
463 // Write out the next instance:
464 //
|
465 mike 1.1
|
466 david.dillard 1.19 tmpFs.write((char*)data.getData(), sizes[i]);
467 }
|
468 mike 1.1 }
469
470 //
471 // Close the files:
472 //
|
473 david.dillard 1.19
|
474 mike 1.1 fs.close();
|
475 mateus.baur 1.28
476 FileSystem::syncWithDirectoryUpdates(tmpFs);
|
477 mike 1.1 tmpFs.close();
478
479 //
480 // Copy the new file over the old one:
481 //
482
483 if (!FileSystem::removeFileNoCase(path))
|
484 kumpf 1.3 {
485 PEG_METHOD_EXIT();
|
486 david.dillard 1.19 return false;
|
487 kumpf 1.3 }
|
488 mike 1.1
|
489 kumpf 1.4 if (!FileSystem::renameFileNoCase(path + ".tmp", path))
|
490 kumpf 1.3 {
491 PEG_METHOD_EXIT();
|
492 david.dillard 1.19 return false;
|
493 kumpf 1.3 }
|
494 mike 1.1
|
495 kumpf 1.3 PEG_METHOD_EXIT();
|
496 mike 1.1 return true;
497 }
498
499 PEGASUS_NAMESPACE_END
|