1 karl 1.47 //%2006////////////////////////////////////////////////////////////////////////
|
2 mike 1.17 //
|
3 karl 1.40 // 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.36 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.40 // 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.42 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 karl 1.47 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
|
13 mike 1.17 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
15 kumpf 1.26 // 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 mike 1.17 // 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.40 //
|
21 kumpf 1.26 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
22 mike 1.17 // 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 kumpf 1.26 // 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 mike 1.17 // 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: Mike Brasher (mbrasher@bmc.com)
33 //
|
34 ramnath 1.21 // Modified By: Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com)
35 //
|
36 kumpf 1.22 // Ramnath Ravindran (Ramnath.Ravindran@compaq.com) 03/21/2002
|
37 r.kieninger 1.39 // replaced instances of "| ios::binary" with
|
38 kumpf 1.22 // PEGASUS_OR_IOS_BINARY
|
39 mike 1.17 //
|
40 kumpf 1.25 // Sushma Fernandes. Hewlett-Packard Company
41 // sushma_fernandes@hp.com
|
42 kumpf 1.28 // Carol Ann Krug Graves, Hewlett-Packard Company
43 // (carolann_graves@hp.com)
|
44 joyce.j 1.41 // Josephine Eskaline Joyce (jojustin@in.ibm.com) for PEP#101
|
45 kumpf 1.25 //
|
46 mike 1.17 //%/////////////////////////////////////////////////////////////////////////////
47
|
48 mike 1.18 #include <Pegasus/Common/Config.h>
|
49 mike 1.17 #include <fstream>
50 #include <cctype>
51 #include <cstdio>
|
52 mike 1.20 #include <cstring>
|
53 mike 1.17 #include <cstdlib>
54 #include <Pegasus/Common/FileSystem.h>
|
55 kumpf 1.22 #include <Pegasus/Common/Tracer.h>
|
56 mike 1.17 #include "InstanceIndexFile.h"
|
57 david 1.34 #if defined(PEGASUS_OS_OS400)
58 #include "OS400ConvertChar.h"
59 #endif
|
60 mike 1.17
61 PEGASUS_USING_STD;
62
63 PEGASUS_NAMESPACE_BEGIN
64
|
65 mike 1.20 static const Uint32 _MAX_FREE_COUNT = 16;
66
67 ////////////////////////////////////////////////////////////////////////////////
68 //
69 // Local routines:
|
70 mike 1.17 //
|
71 mike 1.20 ////////////////////////////////////////////////////////////////////////////////
|
72 marek 1.32 #ifdef PEGASUS_OS_ZOS
|
73 mike 1.20
|
74 marek 1.32 static Uint32 getOffset( streampos sp )
75 {
76 Uint32 result = (streamoff)sp;
77
78 fpos_t posArray = sp.seekpos();
79
80
81 result += posArray.__fpos_elem[1];
82
83 return result;
84 }
85 #endif
|
86 mike 1.17 //
|
87 mike 1.20 // Gets one line from the given file.
|
88 mike 1.17 //
89
|
90 mike 1.44 static Boolean _GetLine(fstream& fs, Buffer& x)
|
91 mike 1.17 {
|
92 marek 1.48 const Uint32 buffersize = 1023 + 1;
93 Uint32 xcount = 0;
94 Uint32 gcount = 0;
95
|
96 mike 1.17 x.clear();
|
97 marek 1.48 x.reserveCapacity(buffersize);
98
99 // The general idea is, we will read the stream at buffersize each time.
100 // if we get exactly buffersize-1, that means we didn't hit a \n
101 // so we loop again to read more,
102 // until we get a buffer that's not completely full.
103 // That means we hit a \n so we exit the loop.
104 do
105 {
106 char input[buffersize];
107
108 // This will read up to buffersize-1 char,
109 // but stop as soon as it hit \n.
110 // This will NOT consume the \n at the end.
111 fs.get(input, buffersize, '\n');
112
113 gcount = fs.gcount();
114 x.append(input, gcount);
115 xcount += gcount;
|
116 mike 1.17
|
117 marek 1.48 } while (gcount == buffersize-1 && fs.rdstate() != istream::failbit);
|
118 mike 1.17
|
119 marek 1.48 // if we read 0 byte in the last call, that's because the read buffer is
120 // exactly multiple of the input line.
121 // So the 2nd last get() read everything up to the \n and
122 // the last get() read 0 char and set the failbit on the
123 // stream. The clear() call will set the stream to ready state.
124 if (gcount == 0)
125 {
126 fs.clear();
127 }
|
128 mike 1.17
|
129 marek 1.48 if (!fs.eof())
130 {
131 // we need to consume the '\n', because get() doesn't
132 char c = 0;
133 fs.get(c);
134 }
|
135 mike 1.17
|
136 marek 1.48 // if xcount is non zero, then we have read something from the buffer.
137 return (xcount != 0);
|
138 mike 1.20 }
139
140 inline void _SkipWhitespace(char*& p)
141 {
142 while (*p && isspace(*p))
143 p++;
|
144 mike 1.17 }
145
146 //
|
147 mike 1.20 // Get an integer field from the character pointer and advance the
148 // pointer past the field.
|
149 mike 1.17 //
150
|
151 mike 1.20 Boolean _GetIntField(
152 char*& ptr,
153 Boolean& error,
154 Uint32& value,
155 int base)
|
156 mike 1.17 {
|
157 mike 1.20 char* end = 0;
158 value = strtoul(ptr, &end, base);
159
|
160 mike 1.17 error = false;
161
162 if (!end)
163 {
|
164 mike 1.18 error = true;
165 return false;
|
166 mike 1.17 }
167
|
168 mike 1.20 _SkipWhitespace(end);
|
169 mike 1.17
|
170 mike 1.20 if (*end == '\0')
|
171 mike 1.18 {
172 error = true;
173 return false;
174 }
|
175 mike 1.17
|
176 mike 1.20 ptr = end;
177 return true;
178 }
|
179 mike 1.18
|
180 mike 1.20 //
181 // Gets the next record in the index file.
182 //
|
183 mike 1.17
|
184 mike 1.20 static Boolean _GetNextRecord(
|
185 r.kieninger 1.39 fstream& fs,
|
186 mike 1.44 Buffer& line,
|
187 mike 1.20 Uint32& freeFlag,
188 Uint32& hashCode,
189 Uint32& index,
190 Uint32& size,
191 const char*& instanceName,
192 Boolean& error)
193 {
194 error = false;
|
195 mike 1.17
|
196 mike 1.20 //
197 // Get next line:
198 //
199
200 if (!_GetLine(fs, line))
|
201 mike 1.18 return false;
|
202 mike 1.17
|
203 mike 1.20 //
204 // Get the free flag field:
205 //
206
207 char* end = (char*)line.getData();
|
208 mike 1.18
|
209 mike 1.20 if (!_GetIntField(end, error, freeFlag, 10))
210 return false;
|
211 mike 1.17
|
212 mike 1.20 if (freeFlag != 0 && freeFlag != 1)
|
213 mike 1.18 {
|
214 mike 1.20 error = true;
215 return false;
|
216 mike 1.18 }
|
217 mike 1.17
|
218 mike 1.20 //
219 // Get the hash-code field:
220 //
|
221 mike 1.17
|
222 mike 1.20 if (!_GetIntField(end, error, hashCode, 16))
223 return false;
|
224 mike 1.18
|
225 mike 1.20 //
226 // Get index field:
227 //
|
228 mike 1.18
|
229 mike 1.20 if (!_GetIntField(end, error, index, 10))
230 return false;
|
231 mike 1.18
|
232 mike 1.20 //
233 // Get size field:
234 //
|
235 mike 1.17
|
236 mike 1.20 if (!_GetIntField(end, error, size, 10))
237 return false;
|
238 mike 1.17
|
239 mike 1.20 //
240 // Get instance name:
241 //
|
242 mike 1.18
|
243 mike 1.20 instanceName = end;
|
244 mike 1.18
|
245 mike 1.17 return true;
246 }
247
|
248 mike 1.20 ////////////////////////////////////////////////////////////////////////////////
|
249 mike 1.17 //
|
250 mike 1.20 // InstanceIndexFile:
|
251 mike 1.17 //
|
252 mike 1.20 ////////////////////////////////////////////////////////////////////////////////
|
253 mike 1.17
|
254 mike 1.20 Boolean InstanceIndexFile::lookupEntry(
|
255 r.kieninger 1.39 const String& path,
|
256 kumpf 1.24 const CIMObjectPath& instanceName,
|
257 mike 1.20 Uint32& indexOut,
258 Uint32& sizeOut)
|
259 mike 1.17 {
|
260 kumpf 1.22 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::lookupEntry()");
261
|
262 mike 1.20 fstream fs;
|
263 mike 1.17
|
264 mike 1.20 if (!_openFile(path, fs))
|
265 kumpf 1.22 {
266 PEG_METHOD_EXIT();
|
267 mike 1.20 return false;
|
268 kumpf 1.22 }
|
269 mike 1.17
|
270 mike 1.20 Uint32 entryOffset = 0;
|
271 mike 1.17
|
272 mike 1.20 Boolean result = _lookupEntry(
273 fs, instanceName, indexOut, sizeOut, entryOffset);
|
274 mike 1.18
|
275 mike 1.20 fs.close();
|
276 kumpf 1.22
277 PEG_METHOD_EXIT();
|
278 mike 1.20 return result;
|
279 mike 1.17 }
280
|
281 mike 1.20 Boolean InstanceIndexFile::createEntry(
|
282 r.kieninger 1.39 const String& path,
|
283 kumpf 1.24 const CIMObjectPath& instanceName,
|
284 mike 1.20 Uint32 indexIn,
285 Uint32 sizeIn)
|
286 mike 1.17 {
|
287 kumpf 1.22 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::createEntry()");
288
|
289 mike 1.18 //
|
290 mike 1.20 // Open the file:
291 //
292
293 fstream fs;
294
|
295 kumpf 1.22 if (!_openFile(path, fs, true))
296 {
297 PEG_METHOD_EXIT();
|
298 mike 1.20 return false;
|
299 kumpf 1.22 }
|
300 mike 1.20
|
301 mike 1.18 //
|
302 mike 1.20 // Return false if entry already exists:
|
303 mike 1.18 //
304
|
305 mike 1.20 Uint32 tmpIndex;
306 Uint32 tmpSize;
307 Uint32 tmpEntryOffset;
308
309 if (InstanceIndexFile::_lookupEntry(
310 fs, instanceName, tmpIndex, tmpSize, tmpEntryOffset))
|
311 kumpf 1.22 {
312 PEG_METHOD_EXIT();
|
313 mike 1.20 return false;
|
314 kumpf 1.22 }
|
315 mike 1.20
316 //
317 // Append the new entry to the end of the file:
318 //
|
319 mike 1.18
|
320 mike 1.20 if (!_appendEntry(fs, instanceName, indexIn, sizeIn))
|
321 kumpf 1.22 {
322 PEG_METHOD_EXIT();
|
323 mike 1.20 return false;
|
324 kumpf 1.22 }
|
325 mike 1.17
|
326 mike 1.18 //
|
327 mike 1.20 // Close the file:
|
328 mike 1.18 //
|
329 mike 1.17
|
330 mike 1.20 fs.close();
|
331 kumpf 1.22
332 PEG_METHOD_EXIT();
|
333 mike 1.20 return true;
334 }
|
335 mike 1.17
|
336 mike 1.20 Boolean InstanceIndexFile::deleteEntry(
|
337 r.kieninger 1.39 const String& path,
|
338 kumpf 1.24 const CIMObjectPath& instanceName,
|
339 mike 1.20 Uint32& freeCount)
340 {
|
341 kumpf 1.22 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::deleteEntry()");
342
|
343 mike 1.20 freeCount = 0;
|
344 mike 1.17
|
345 mike 1.20 //
346 // Open the file:
347 //
|
348 mike 1.18
|
349 mike 1.20 fstream fs;
|
350 mike 1.18
|
351 mike 1.20 if (!_openFile(path, fs))
352 {
|
353 kumpf 1.22 PEG_METHOD_EXIT();
|
354 mike 1.20 return false;
355 }
|
356 mike 1.17
|
357 mike 1.20 //
358 // Mark the entry as free:
359 //
|
360 mike 1.17
|
361 mike 1.20 if (!_markEntryFree(fs, instanceName))
362 {
|
363 kumpf 1.22 PEG_METHOD_EXIT();
|
364 mike 1.20 return false;
|
365 mike 1.18 }
|
366 mike 1.17
|
367 mike 1.18 //
|
368 mike 1.20 // Increment the free count:
369 //
370
371 freeCount = 0;
372
373 if (!_incrementFreeCount(fs, freeCount))
|
374 kumpf 1.22 {
375 PEG_METHOD_EXIT();
|
376 mike 1.20 return false;
|
377 kumpf 1.22 }
|
378 mike 1.20
379 //
380 // Close the file:
|
381 mike 1.18 //
|
382 mike 1.17
|
383 mike 1.20 fs.close();
|
384 mike 1.17
|
385 kumpf 1.22 PEG_METHOD_EXIT();
|
386 mike 1.17 return true;
387 }
388
|
389 mike 1.20 Boolean InstanceIndexFile::modifyEntry(
|
390 r.kieninger 1.39 const String& path,
|
391 kumpf 1.24 const CIMObjectPath& instanceName,
|
392 mike 1.20 Uint32 indexIn,
393 Uint32 sizeIn,
394 Uint32& freeCount)
395 {
|
396 kumpf 1.22 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::modifyEntry()");
397
|
398 mike 1.20 //
399 // Open the file:
400 //
401
402 fstream fs;
403
404 if (!_openFile(path, fs))
|
405 kumpf 1.22 {
406 PEG_METHOD_EXIT();
|
407 mike 1.20 return false;
|
408 kumpf 1.22 }
|
409 mike 1.17
|
410 mike 1.18 //
|
411 mike 1.20 // Mark the entry as free:
|
412 mike 1.18 //
|
413 mike 1.17
|
414 mike 1.20 if (!_markEntryFree(fs, instanceName))
|
415 kumpf 1.22 {
416 PEG_METHOD_EXIT();
|
417 mike 1.20 return false;
|
418 kumpf 1.22 }
|
419 mike 1.17
|
420 mike 1.18 //
|
421 mike 1.20 // Append new entry:
422 //
423
424 if (!_appendEntry(fs, instanceName, indexIn, sizeIn))
|
425 kumpf 1.22 {
426 PEG_METHOD_EXIT();
|
427 mike 1.20 return false;
|
428 kumpf 1.22 }
|
429 mike 1.20
|
430 mike 1.18 //
|
431 mike 1.20 // Increment the free count:
|
432 mike 1.18 //
|
433 mike 1.17
|
434 mike 1.20 freeCount = 0;
|
435 mike 1.17
|
436 mike 1.20 if (!_incrementFreeCount(fs, freeCount))
|
437 kumpf 1.22 {
438 PEG_METHOD_EXIT();
|
439 mike 1.20 return false;
|
440 kumpf 1.22 }
|
441 mike 1.17
|
442 mike 1.18 //
|
443 mike 1.20 // Close the file:
|
444 mike 1.18 //
|
445 mike 1.17
|
446 mike 1.20 fs.close();
|
447 mike 1.17
|
448 kumpf 1.22 PEG_METHOD_EXIT();
|
449 mike 1.18 return true;
450 }
|
451 mike 1.17
|
452 mike 1.20 Boolean InstanceIndexFile::enumerateEntries(
453 const String& path,
454 Array<Uint32>& freeFlags,
455 Array<Uint32>& indices,
456 Array<Uint32>& sizes,
|
457 kumpf 1.24 Array<CIMObjectPath>& instanceNames,
|
458 mike 1.20 Boolean includeFreeEntries)
|
459 mike 1.18 {
|
460 kumpf 1.22 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::enumerateEntries()");
461
|
462 mike 1.18 //
|
463 mike 1.20 // Reserve space for at least COUNT entries:
|
464 mike 1.18 //
|
465 mike 1.17
|
466 mike 1.20 const Uint32 COUNT = 1024;
467
|
468 kumpf 1.27 freeFlags.reserveCapacity(COUNT);
469 indices.reserveCapacity(COUNT);
470 sizes.reserveCapacity(COUNT);
471 instanceNames.reserveCapacity(COUNT);
|
472 mike 1.17
|
473 mike 1.18 //
|
474 mike 1.20 // Open input file:
|
475 mike 1.18 //
|
476 mike 1.20
477 fstream fs;
478
479 if (!_openFile(path, fs))
|
480 kumpf 1.22 {
481 // file does not exist, just return with no instanceNames
482 PEG_METHOD_EXIT();
483 return true;
484 }
|
485 mike 1.20
486 //
487 // Iterate over all instances to build output arrays:
|
488 mike 1.18 //
|
489 mike 1.20
|
490 mike 1.44 Buffer line;
|
491 mike 1.20 Uint32 freeFlag;
492 Uint32 hashCode;
493 const char* instanceName;
494 Uint32 index;
495 Uint32 size;
496 Boolean error;
497
498 while (_GetNextRecord(
499 fs, line, freeFlag, hashCode, index, size, instanceName, error))
|
500 mike 1.17 {
|
501 mike 1.20 if (!freeFlag || includeFreeEntries)
502 {
|
503 r.kieninger 1.39 freeFlags.append(freeFlag);
504 indices.append(index);
|
505 mike 1.20 sizes.append(size);
|
506 kumpf 1.28 instanceNames.append (CIMObjectPath (instanceName));
|
507 mike 1.20 }
|
508 mike 1.17 }
509
|
510 mike 1.20 if (error)
|
511 kumpf 1.22 {
512 PEG_METHOD_EXIT();
|
513 mike 1.20 return false;
|
514 kumpf 1.22 }
|
515 mike 1.20
|
516 kumpf 1.22 PEG_METHOD_EXIT();
|
517 mike 1.20 return true;
518 }
519
520 Boolean InstanceIndexFile::_incrementFreeCount(
521 PEGASUS_STD(fstream)& fs,
522 Uint32& freeCount)
523 {
|
524 kumpf 1.22 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::_incrementFreeCount()");
525
|
526 mike 1.20 //
527 // Position file pointer to beginning of file (where free count is
528 // located) and read the current free count.
529 //
530
531 fs.seekg(0);
532 char hexString[9];
533 fs.read(hexString, 8);
534
535 if (!fs)
|
536 kumpf 1.22 {
537 PEG_METHOD_EXIT();
|
538 mike 1.20 return false;
|
539 kumpf 1.22 }
|
540 mike 1.17
|
541 mike 1.20 hexString[8] = '\0';
|
542 mike 1.17
|
543 mike 1.18 //
|
544 mike 1.20 // Convert hex string to integer:
|
545 mike 1.18 //
|
546 mike 1.20
547 char* end = 0;
548 long tmp = strtol(hexString, &end, 16);
549
550 if (!end || *end != '\0' || tmp < 0)
|
551 kumpf 1.22 {
552 PEG_METHOD_EXIT();
|
553 mike 1.20 return false;
|
554 kumpf 1.22 }
|
555 mike 1.20
556 freeCount = Uint32(tmp);
|
557 mike 1.17
|
558 mike 1.18 //
|
559 mike 1.20 // Increment and rewrite the free count:
|
560 mike 1.18 //
|
561 mike 1.17
|
562 mike 1.20 sprintf(hexString, "%08X", ++freeCount);
563 fs.seekg(0);
564 fs.write(hexString, 8);
|
565 mike 1.17
|
566 kumpf 1.22 PEG_METHOD_EXIT();
|
567 mike 1.20 return !!fs;
|
568 mike 1.17 }
569
|
570 mike 1.20 Boolean InstanceIndexFile::_openFile(
|
571 r.kieninger 1.39 const String& path,
|
572 kumpf 1.22 PEGASUS_STD(fstream)& fs,
573 Boolean create)
|
574 mike 1.17 {
|
575 kumpf 1.22 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::_openFile()");
576
|
577 mike 1.20 const char ZERO_FREE_COUNT[] = "00000000\n";
|
578 mike 1.17
|
579 mike 1.20 //
580 // Open the file:
581 //
|
582 mike 1.17
|
583 ramnath 1.21 if (!FileSystem::openNoCase(fs, path, ios::in | ios::out PEGASUS_OR_IOS_BINARY))
|
584 mike 1.18 {
|
585 kumpf 1.22 if (create)
586 {
587 //
588 // File does not exist so create it:
589 //
|
590 david 1.34 #if defined(PEGASUS_OS_OS400)
|
591 david 1.38 fs.open(path.getCString(), ios::out PEGASUS_OR_IOS_BINARY, PEGASUS_STD(_CCSID_T(1208)));
|
592 david 1.34 #else
|
593 david 1.38 fs.open(path.getCString(), ios::out PEGASUS_OR_IOS_BINARY);
|
594 david 1.34 #endif
|
595 kumpf 1.22
596 if (!fs)
597 {
598 PEG_METHOD_EXIT();
599 return false;
600 }
601
602 fs.write(ZERO_FREE_COUNT, sizeof(ZERO_FREE_COUNT) - 1);
603 fs.close();
604
605 //
606 // Reopen the file:
607 //
608
609 if (!FileSystem::openNoCase(fs, path, ios::in | ios::out PEGASUS_OR_IOS_BINARY))
610 {
611 PEG_METHOD_EXIT();
612 return false;
613 }
614 }
615 else
616 kumpf 1.22 {
617 PEG_METHOD_EXIT();
618 return false;
619 }
|
620 mike 1.20 }
|
621 mike 1.18
|
622 mike 1.20 //
623 // Position the file pointer beyond the free count:
624 //
625
626 fs.seekg(sizeof(ZERO_FREE_COUNT) - 1);
|
627 mike 1.18
|
628 kumpf 1.22 PEG_METHOD_EXIT();
|
629 mike 1.18 return true;
630 }
631
|
632 mike 1.20 Boolean InstanceIndexFile::_appendEntry(
633 PEGASUS_STD(fstream)& fs,
|
634 kumpf 1.24 const CIMObjectPath& instanceName,
|
635 mike 1.20 Uint32 indexIn,
636 Uint32 sizeIn)
|
637 mike 1.18 {
|
638 kumpf 1.22 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::_appendEntry()");
639
|
640 mike 1.18 //
|
641 mike 1.20 // Position the file at the end:
642 //
643
644 fs.seekg(0, ios::end);
645
646 if (!fs)
|
647 kumpf 1.22 {
648 PEG_METHOD_EXIT();
|
649 mike 1.20 return false;
|
650 kumpf 1.22 }
|
651 mike 1.20
652 //
653 // Write the entry:
|
654 mike 1.18 //
|
655 mike 1.20
|
656 mike 1.18 Uint32 targetHashCode = instanceName.makeHashCode();
657
658 char buffer[32];
659 sprintf(buffer, "%08X", targetHashCode);
|
660 mike 1.20
661 fs << "0 " << buffer << ' ' << indexIn << ' ' << sizeIn << ' ';
|
662 chuck 1.43
663 // Calling getCString to ensure that utf-8 goes to the file
664 // Calling write to ensure no data conversion by the stream
665 CString name = instanceName.toString().getCString();
|
666 kumpf 1.46 fs.write((const char *)name,
667 static_cast<streamsize>(strlen((const char *)name)));
|
668 chuck 1.43 fs << endl;
|
669 mike 1.20
|
670 kumpf 1.22 PEG_METHOD_EXIT();
|
671 mike 1.20 return !!fs;
|
672 mike 1.18 }
|
673 mike 1.17
|
674 mike 1.20 Boolean InstanceIndexFile::_markEntryFree(
675 PEGASUS_STD(fstream)& fs,
|
676 kumpf 1.24 const CIMObjectPath& instanceName)
|
677 mike 1.18 {
|
678 kumpf 1.22 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::_markEntryFree()");
679
|
680 mike 1.18 //
|
681 mike 1.20 // First look up the entry:
|
682 mike 1.18 //
|
683 mike 1.17
|
684 mike 1.20 Uint32 index = 0;
685 Uint32 size = 0;
686 Uint32 entryOffset = 0;
687
688 if (!InstanceIndexFile::_lookupEntry(
689 fs, instanceName, index, size, entryOffset))
|
690 mike 1.18 {
|
691 kumpf 1.22 PEG_METHOD_EXIT();
|
692 mike 1.20 return false;
|
693 mike 1.18 }
|
694 mike 1.17
|
695 mike 1.18 //
|
696 mike 1.20 // Now mark the entry as free (change the first character of the entry
697 // from a '0' to a '1').
|
698 mike 1.18 //
|
699 mike 1.20
700 fs.seekg(entryOffset);
701
702 if (!fs)
703 {
|
704 kumpf 1.22 PEG_METHOD_EXIT();
|
705 mike 1.20 return false;
706 }
707
708 fs.write("1", 1);
709
|
710 kumpf 1.22 PEG_METHOD_EXIT();
|
711 mike 1.20 return !!fs;
712 }
713
714 Boolean InstanceIndexFile::_lookupEntry(
715 PEGASUS_STD(fstream)& fs,
|
716 kumpf 1.24 const CIMObjectPath& instanceName,
|
717 mike 1.20 Uint32& indexOut,
718 Uint32& sizeOut,
719 Uint32& entryOffset)
720 {
|
721 kumpf 1.22 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::_lookupEntry()");
722
|
723 mike 1.20 indexOut = 0;
724 sizeOut = 0;
725 entryOffset = 0;
726
|
727 r.kieninger 1.39 // For for bugzilla 1508. Hostname and namespace are not included
728 // in the comparison here. Instances in the repository index file
729 // are generally stored without hostname and namespace. If the hostname
730 // and namespace of the instance to look up would not match, we would have
731 // not gotten here at all.
732 CIMObjectPath shortInstanceName = instanceName;
733 shortInstanceName.setNameSpace(CIMNamespaceName());
734 shortInstanceName.setHost(String::EMPTY);
735
736 Uint32 targetHashCode = shortInstanceName.makeHashCode();
|
737 mike 1.44 Buffer line;
|
738 mike 1.20 Uint32 freeFlag;
739 Uint32 hashCode;
740 const char* instanceNameTmp;
741 Uint32 index;
742 Uint32 size;
743 Boolean error;
|
744 marek 1.32 #ifndef PEGASUS_OS_ZOS
745 entryOffset = fs.tellp();
746 #else
747 entryOffset = getOffset(fs.tellp());
748 #endif
|
749 mike 1.20
750 while (_GetNextRecord(
751 fs, line, freeFlag, hashCode, index, size, instanceNameTmp, error))
752 {
|
753 r.kieninger 1.39
|
754 chuck 1.37 #ifdef PEGASUS_REPOSITORY_NOT_NORMALIZED
755 // See bugzilla 1207. If the object paths in the repository
756 // are not normalized, then the hashcodes cannot be used for
757 // the look up (because the hash is based on the normalized path).
758 if (freeFlag == 0 &&
|
759 r.kieninger 1.39 CIMObjectPath(instanceNameTmp) == shortInstanceName)
|
760 chuck 1.37 #else
|
761 mike 1.20 if (freeFlag == 0 &&
762 hashCode == targetHashCode &&
|
763 r.kieninger 1.39 CIMObjectPath(instanceNameTmp) == shortInstanceName)
|
764 chuck 1.37 #endif
|
765 mike 1.20 {
766 indexOut = index;
767 sizeOut = size;
|
768 kumpf 1.22 PEG_METHOD_EXIT();
|
769 mike 1.20 return true;
770 }
771
|
772 marek 1.32 #ifndef PEGASUS_OS_ZOS
773 entryOffset = fs.tellp();
774 #else
775 entryOffset = getOffset(fs.tellp());
776 #endif
|
777 mike 1.20 }
778
779 fs.clear();
780
|
781 kumpf 1.22 PEG_METHOD_EXIT();
|
782 mike 1.20 return false;
783 }
784
785 Boolean InstanceIndexFile::compact(
786 const String& path)
787 {
|
788 kumpf 1.22 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::compact()");
789
|
790 mike 1.20 //
791 // Open input file:
792 //
793
794 fstream fs;
795
796 if (!_openFile(path, fs))
|
797 kumpf 1.22 {
798 PEG_METHOD_EXIT();
|
799 mike 1.20 return false;
|
800 kumpf 1.22 }
|
801 mike 1.20
802 //
803 // Open temporary file (delete it first):
804 //
805
806 fstream tmpFs;
807 String tmpPath = path;
|
808 kumpf 1.29 tmpPath.append(".tmp");
|
809 mike 1.20
|
810 kumpf 1.22 FileSystem::removeFileNoCase(tmpPath);
|
811 mike 1.20
|
812 kumpf 1.22 if (!_openFile(tmpPath, tmpFs, true))
813 {
814 PEG_METHOD_EXIT();
|
815 mike 1.20 return false;
|
816 kumpf 1.22 }
|
817 mike 1.20
818 //
819 // Iterate over all instances to build output arrays:
820 //
|
821 mike 1.17
|
822 mike 1.44 Buffer line;
|
823 mike 1.20 Uint32 freeFlag;
|
824 mike 1.17 Uint32 hashCode;
|
825 mike 1.20 const char* instanceName;
826 Uint32 index;
|
827 mike 1.18 Uint32 size;
|
828 mike 1.17 Boolean error;
|
829 mike 1.20 Uint32 adjust = 0;
|
830 mike 1.17
|
831 mike 1.20 while (_GetNextRecord(
832 fs, line, freeFlag, hashCode, index, size, instanceName, error))
|
833 mike 1.17 {
|
834 mike 1.20 //
835 // Copy the entry over to the temporary file if it is not free.
836 // Otherwise, discard the entry and update subsequent indices to
837 // compensate for removal of this block.
838 //
|
839 mike 1.18
|
840 mike 1.20 if (freeFlag)
841 {
842 adjust += size;
843 }
844 else
845 {
|
846 r.kieninger 1.39 if (!_appendEntry(tmpFs, CIMObjectPath (instanceName),
|
847 kumpf 1.28 index - adjust, size))
|
848 mike 1.20 {
849 error = true;
850 break;
851 }
852 }
|
853 mike 1.17 }
854
|
855 mike 1.20 //
856 // Close both files:
857
858 fs.close();
859 tmpFs.close();
860
861 //
862 // If an error occurred, remove the temporary file and
863 // return false.
864 //
|
865 mike 1.18
866 if (error)
867 {
|
868 kumpf 1.22 FileSystem::removeFileNoCase(tmpPath);
869 PEG_METHOD_EXIT();
|
870 mike 1.20 return false;
871 }
872
873 //
874 // Replace index file with temporary file:
875 //
876
|
877 kumpf 1.22 if (!FileSystem::removeFileNoCase(path))
878 {
879 PEG_METHOD_EXIT();
|
880 mike 1.20 return false;
|
881 kumpf 1.22 }
|
882 mike 1.20
883 if (!FileSystem::renameFile(tmpPath, path))
|
884 kumpf 1.22 {
885 PEG_METHOD_EXIT();
|
886 mike 1.20 return false;
|
887 kumpf 1.22 }
|
888 mike 1.20
|
889 kumpf 1.22 PEG_METHOD_EXIT();
|
890 mike 1.20 return true;
891 }
892
893 Boolean InstanceIndexFile::hasNonFreeEntries(const String& path)
894 {
895 //
896 // If file does not exist, there are no instances:
897 //
898
899 if (!FileSystem::existsNoCase(path))
900 return false;
901
902 //
903 // We must iterate all the entries looking for a non-free one:
904 //
905
906 Array<Uint32> freeFlags;
907 Array<Uint32> indices;
908 Array<Uint32> sizes;
|
909 kumpf 1.24 Array<CIMObjectPath> instanceNames;
|
910 mike 1.20
911 if (!InstanceIndexFile::enumerateEntries(
912 path, freeFlags, indices, sizes, instanceNames, false))
913 {
914 // This won't happen!
915 return false;
|
916 mike 1.18 }
917
|
918 mike 1.20 return freeFlags.size() != 0;
919 }
920
921 Boolean InstanceIndexFile::beginTransaction(const String& path)
922 {
|
923 kumpf 1.22 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::beginTransaction()");
924
|
925 chuck 1.45 String rollbackPath = path;
926 rollbackPath.append(".rollback");
927
928 //
929 // If the index file does not exist, then create a rollback file with
930 // freecount of 0.
931 //
932 if (!FileSystem::existsNoCase(path))
933 {
934 // Make sure the rollback file does not exist.
935 if (FileSystem::existsNoCase(rollbackPath))
936 {
937 if (!FileSystem::removeFileNoCase(rollbackPath))
938 {
939 PEG_METHOD_EXIT();
940 return false;
941 }
942 }
943
944 // Create the rollback file, and write the freecount of 0.
945 fstream fs;
946 chuck 1.45 if (!_openFile(rollbackPath, fs, true))
947 {
948 // Make sure no rollback file is left over.
949 FileSystem::removeFileNoCase(rollbackPath);
950
951 PEG_METHOD_EXIT();
952 return false;
953 }
954 fs.close();
955
956 PEG_METHOD_EXIT();
957 return true;
958 }
959
|
960 mike 1.20 //
961 // Create a rollback file which is a copy of the index file. The
962 // new filename is formed by appending ".rollback" to the name of
|
963 kumpf 1.49 // the index file. The rollback file, if it exists, is considered
964 // the "master" copy of the data. To ensure its completeness, the
965 // index file is renamed to the rollback file and the data is then
966 // copied back to the index file.
|
967 mike 1.20 //
|
968 kumpf 1.49
969 if (!FileSystem::renameFileNoCase(path, rollbackPath))
970 {
971 PEG_METHOD_EXIT();
972 return false;
973 }
974
975 if (!FileSystem::copyFile(rollbackPath, path))
|
976 kumpf 1.22 {
|
977 kumpf 1.49 // Try to restore the initial state
978 FileSystem::removeFileNoCase(path);
979 FileSystem::renameFileNoCase(rollbackPath, path);
|
980 chuck 1.45
|
981 kumpf 1.22 PEG_METHOD_EXIT();
|
982 mike 1.20 return false;
|
983 kumpf 1.22 }
|
984 mike 1.20
|
985 kumpf 1.22 PEG_METHOD_EXIT();
|
986 mike 1.20 return true;
987 }
988
989 Boolean InstanceIndexFile::rollbackTransaction(const String& path)
990 {
|
991 kumpf 1.22 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::rollbackTransaction()");
992
|
993 mike 1.20 //
994 // If the rollback file does not exist, then everything is fine (nothing
995 // to roll back).
996 //
997
|
998 kumpf 1.23 if (!FileSystem::existsNoCase(path + ".rollback"))
|
999 kumpf 1.22 {
1000 PEG_METHOD_EXIT();
|
1001 mike 1.20 return true;
|
1002 kumpf 1.22 }
|
1003 mike 1.20
1004 //
1005 // To roll back, simply delete the index file and rename
1006 // the rollback file over it.
1007 //
1008
|
1009 kumpf 1.25 if (FileSystem::existsNoCase(path))
|
1010 kumpf 1.22 {
|
1011 kumpf 1.25 if (!FileSystem::removeFileNoCase(path))
1012 {
1013 PEG_METHOD_EXIT();
1014 return false;
1015 }
|
1016 kumpf 1.22 }
|
1017 mike 1.20
|
1018 kumpf 1.22 PEG_METHOD_EXIT();
|
1019 kumpf 1.23 return FileSystem::renameFileNoCase(path + ".rollback", path);
|
1020 mike 1.20 }
1021
1022 Boolean InstanceIndexFile::commitTransaction(const String& path)
1023 {
|
1024 kumpf 1.22 PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::commitTransaction()");
1025
|
1026 mike 1.20 //
1027 // To commit, simply remove the rollback file:
1028 //
1029
1030 String rollbackPath = path;
|
1031 kumpf 1.29 rollbackPath.append(".rollback");
|
1032 mike 1.20
|
1033 kumpf 1.22 PEG_METHOD_EXIT();
|
1034 mike 1.20 return FileSystem::removeFileNoCase(rollbackPath);
|
1035 mike 1.17 }
1036
1037 PEGASUS_NAMESPACE_END
|