1 martin 1.13 //%LICENSE////////////////////////////////////////////////////////////////
|
2 martin 1.14 //
|
3 martin 1.13 // Licensed to The Open Group (TOG) under one or more contributor license
4 // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
5 // this work for additional information regarding copyright ownership.
6 // Each contributor licenses this file to you under the OpenPegasus Open
7 // Source License; you may not use this file except in compliance with the
8 // License.
|
9 martin 1.14 //
|
10 martin 1.13 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
|
16 martin 1.14 //
|
17 martin 1.13 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
|
19 martin 1.14 //
|
20 martin 1.13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
21 martin 1.14 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22 martin 1.13 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27 martin 1.14 //
|
28 martin 1.13 //////////////////////////////////////////////////////////////////////////
|
29 kumpf 1.1 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
32 #include <Pegasus/Common/Config.h>
33 #include <cctype>
34 #include <cstdio>
35 #include <fstream>
36
37 #include <Pegasus/Common/InternalException.h>
38 #include <Pegasus/Common/DeclContext.h>
39 #include <Pegasus/Common/Resolver.h>
40 #include <Pegasus/Common/System.h>
41 #include <Pegasus/Common/Tracer.h>
42 #include <Pegasus/Common/MessageLoader.h>
43 #include <Pegasus/Common/FileSystem.h>
44 #include <Pegasus/Common/Dir.h>
45 #include <Pegasus/Common/CommonUTF.h>
|
46 karl 1.15.8.1 #include <Pegasus/Common/ReadWriteSem.h>
|
47 kumpf 1.1 #include "InstanceIndexFile.h"
48 #include "InstanceDataFile.h"
49 #include "AssocInstTable.h"
50 #include "FileBasedStore.h"
51
52 #ifdef PEGASUS_ENABLE_COMPRESSED_REPOSITORY
53 // #define win32
54 # include <zlib.h>
55 # include <sstream>
56 #endif
57
|
58 kumpf 1.6 PEGASUS_USING_STD;
59
|
60 kumpf 1.1 PEGASUS_NAMESPACE_BEGIN
61
62 static const char _CLASSES_DIR[] = "classes";
63 static const char _INSTANCES_DIR[] = "instances";
64 static const char _QUALIFIERS_DIR[] = "qualifiers";
65
66 static const char _CLASSES_SUFFIX[] = "/classes";
67 static const char _INSTANCES_SUFFIX[] = "/instances";
68 static const char _QUALIFIERS_SUFFIX[] = "/qualifiers";
69 static const char _ASSOCIATIONS_SUFFIX[] = "/associations";
70
|
71 kumpf 1.6 // The config file name is selected such that it cannot collide with a
72 // namespace directory name. Namespace directories may not contain a '.'.
73 static const char _CONFIGFILE_NAME[] = "repository.conf";
74
|
75 kumpf 1.1 static const Uint32 _MAX_FREE_COUNT = 16;
76
|
77 karl 1.15.8.1 #define REPOSITORY_BEGIN_PROGRESS_FILE "begin.progress";
78 #define REPOSITORY_COMMIT_PROGRESS_FILE "commit.progress";
79 #define REPOSITORY_ROLLBACK_PROGRESS_FILE "rollback.progress";
80
81 //
82 // This static variable is used inside "rollbackInstanceTransaction" function
83 // to determine if it is called from the constructor of "CIMRepository" during
84 // startup in order to avoid the creation of "rollback.progress" state file
85 // as it increases the startup time of the cimserver process.
86 // true => startup
87 //
88 static bool startup = true;
89
90
|
91 kumpf 1.1 static inline String _escapeUtf8FileNameCharacters(const String& fileName)
92 {
93 #ifdef PEGASUS_REPOSITORY_ESCAPE_UTF8
94 // All chars above 0x7F will be escape.
95 return escapeStringEncoder(fileName);
96 #else
97 return fileName;
98 #endif
99 }
100
101 static inline String _unescapeUtf8FileNameCharacters(const String& fileName)
102 {
103 #ifdef PEGASUS_REPOSITORY_ESCAPE_UTF8
104 return escapeStringDecoder(fileName);
105 #else
106 return fileName;
107 #endif
108 }
109
110 ////////////////////////////////////////////////////////////////////////////////
111 //
112 kumpf 1.1 // _namespaceNameToDirName()
113 //
114 ////////////////////////////////////////////////////////////////////////////////
115
116 static String _namespaceNameToDirName(const CIMNamespaceName& namespaceName)
117 {
118 String nameSpaceDirName = namespaceName.getString();
119
120 for (Uint32 i = 0; i < nameSpaceDirName.size(); i++)
121 {
122 if (nameSpaceDirName[i] == '/')
123 {
124 nameSpaceDirName[i] = '#';
125 }
126 }
127
128 return _escapeUtf8FileNameCharacters(nameSpaceDirName);
129 }
130
131 ////////////////////////////////////////////////////////////////////////////////
132 //
133 kumpf 1.1 // _dirNameToNamespaceName()
134 //
135 ////////////////////////////////////////////////////////////////////////////////
136
137 static String _dirNameToNamespaceName(const String& nameSpaceDirName)
138 {
139 String namespaceName = nameSpaceDirName;
140
141 for (Uint32 i = 0; i < namespaceName.size(); i++)
142 {
143 if (namespaceName[i] == '#')
144 {
145 namespaceName[i] = '/';
146 }
147 }
148 #ifdef PEGASUS_REPOSITORY_ESCAPE_UTF8
149 // All chars above 0x7F will be escape.
150 return escapeStringDecoder(namespaceName);
151 #else
152 return namespaceName;
153 #endif
154 kumpf 1.1 }
155
156 ////////////////////////////////////////////////////////////////////////////////
157 //
158 // _LoadFileToMemory() PEP214
159 //
160 // The gzxxxx functions read both compresed and non-compresed files.
161 //
162 // There is no conditional flag on reading of files since gzread()
163 // (from zlib) is capable of reading compressed and non-compressed
164 // files (so it contains the logic that examines the header
165 // and magic number). Everything will work properly if the repository
166 // has some compressed and some non-compressed files.
167 //
168 //
169 ////////////////////////////////////////////////////////////////////////////////
170
171 static void _LoadFileToMemory(Buffer& data, const String& path)
172 {
173
174 #ifdef PEGASUS_ENABLE_COMPRESSED_REPOSITORY
175 kumpf 1.1
176 Uint32 fileSize;
177
178 if (!FileSystem::getFileSize(path, fileSize))
179 throw CannotOpenFile(path);
180
181 gzFile fp = gzopen(path.getCString(), "rb");
182
183 if (fp == NULL)
184 throw CannotOpenFile(path);
185
186 data.reserveCapacity(fileSize);
187 char buffer[4096];
188 int n;
189
190 while ((n = gzread(fp, buffer, sizeof(buffer))) > 0)
191 data.append(buffer, n);
192
193 gzclose(fp);
194
195 #else
196 kumpf 1.1
197 FileSystem::loadFileToMemory(data, path);
198
199 #endif /* PEGASUS_ENABLE_COMPRESSED_REPOSITORY */
200 }
201
202 ////////////////////////////////////////////////////////////////////////////////
203 //
204 // _LoadObject()
205 //
206 // Loads objects (classes and qualifiers) from disk to
207 // memory objects.
208 //
209 ////////////////////////////////////////////////////////////////////////////////
210
211 template<class Object>
212 void _LoadObject(
213 const String& path,
214 Object& object,
215 ObjectStreamer* streamer)
216 {
217 kumpf 1.1 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::_LoadObject");
218
219 // Get the real path of the file:
220
221 String realPath;
222
223 if (!FileSystem::existsNoCase(path, realPath))
224 {
|
225 thilo.boehm 1.5 PEG_TRACE((TRC_REPOSITORY, Tracer::LEVEL1,
226 "%s does not exist.",(const char*)path.getCString()));
|
227 kumpf 1.1 PEG_METHOD_EXIT();
228 throw CannotOpenFile(path);
229 }
230
|
231 thilo.boehm 1.5 PEG_TRACE((TRC_REPOSITORY, Tracer::LEVEL4, "realpath = %s",
232 (const char*)realPath.getCString()));
|
233 kumpf 1.1
234 // Load file into memory:
235
236 Buffer data;
237
238 _LoadFileToMemory(data, realPath);
239
240 streamer->decode(data, 0, object);
241
242 PEG_METHOD_EXIT();
243 }
244
245 ////////////////////////////////////////////////////////////////////////////////
246 //
247 // _SaveObject()
248 //
249 // Saves objects (classes and qualifiers) from memory to
250 // disk files.
251 //
252 ////////////////////////////////////////////////////////////////////////////////
253
254 kumpf 1.1 static void _SaveObject(
255 const String& path,
256 Buffer& objectXml,
|
257 kumpf 1.7 ObjectStreamer* streamer,
258 Boolean compressMode)
|
259 kumpf 1.1 {
260 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::_SaveObject");
261
262 #ifdef PEGASUS_ENABLE_COMPRESSED_REPOSITORY
|
263 kumpf 1.7 if (compressMode) // PEP214
|
264 kumpf 1.1 {
265 PEGASUS_STD(ostringstream) os;
266 streamer->write(os, objectXml);
267 string str = os.str();
268
269 gzFile fp = gzopen(path.getCString(), "wb");
270
271 if (fp == NULL)
272 throw CannotOpenFile(path);
273
274 const char* ptr = str.data();
275 size_t rem = str.size();
276 int n;
277
278 while (rem > 0 && (n = gzwrite(fp, (char*)ptr, rem)) > 0)
279 {
280 ptr += n;
281 rem -= n;
282 }
283
284 gzclose(fp);
285 kumpf 1.1 }
286 else
287 #endif /* PEGASUS_ENABLE_COMPRESSED_REPOSITORY */
288 {
289 PEGASUS_STD(ofstream) os(path.getCString() PEGASUS_IOS_BINARY);
290
291 if (!os)
292 {
293 PEG_METHOD_EXIT();
294 throw CannotOpenFile(path);
295 }
296
297 streamer->write(os, objectXml);
298 }
299 PEG_METHOD_EXIT();
300 }
301
302 ////////////////////////////////////////////////////////////////////////////////
303 //
304 // _beginInstanceTransaction()
305 //
306 kumpf 1.1 // Creates rollback files to allow an incomplete transaction to be voided.
307 //
308 ////////////////////////////////////////////////////////////////////////////////
309
310 static void _beginInstanceTransaction(
311 const String& indexFilePath,
312 const String& dataFilePath)
313 {
314 PEG_METHOD_ENTER(TRC_REPOSITORY, "_beginInstanceTransaction");
|
315 karl 1.15.8.1
316 // Create a state file for the begin instance transaction in the same
317 // directory where the rollback files will be created for
318 // index and data file.
319 // The CIMRepository checks if this file is present during
320 // its initialization.
321 // If it is present, it is assumed that the last begin transaction was
322 // incomplete due to system failure and it removes the rollback files along
323 // with this state file
324
325 String dirPath = FileSystem::extractFilePath(indexFilePath);
326 String stateFilePath = dirPath + REPOSITORY_BEGIN_PROGRESS_FILE;
327
328 fstream fs;
329
330 fs.open(stateFilePath.getCString(), ios::out PEGASUS_OR_IOS_BINARY);
331
332 if (!fs)
333 {
334 PEG_METHOD_EXIT();
335 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
336 karl 1.15.8.1 MessageLoaderParms(
337 "Repository.CIMRepository.BEGIN_FAILED",
338 "The attempt to begin the transaction failed."));
339 }
340 fs.close();
|
341 kumpf 1.1
342 //
343 // Begin the transaction (an incomplete transaction will cause
344 // a rollback the next time an instance-oriented routine is invoked).
345 //
346
347 if (!InstanceIndexFile::beginTransaction(indexFilePath))
348 {
|
349 karl 1.15.8.1 //
350 // Remove the state file
351 //
352 FileSystem::removeFile(stateFilePath);
353
|
354 kumpf 1.1 PEG_METHOD_EXIT();
355 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
|
356 karl 1.15.8.1 MessageLoaderParms(
357 "Repository.CIMRepository.BEGIN_FAILED",
358 "The attempt to begin the transaction failed."));
|
359 kumpf 1.1 }
360
361 if (!InstanceDataFile::beginTransaction(dataFilePath))
362 {
|
363 karl 1.15.8.1 //
364 // The creation of the index and data rollback file should be atomic
365 // So undo the begin transaction of index file in case of error in
366 // the begin transaction of the data file
367 //
368 InstanceIndexFile::undoBeginTransaction(indexFilePath);
369
370 //
371 // Remove the state file
372 //
373 FileSystem::removeFile(stateFilePath);
374
|
375 kumpf 1.1 PEG_METHOD_EXIT();
376 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
|
377 karl 1.15.8.1 MessageLoaderParms(
378 "Repository.CIMRepository.BEGIN_FAILED",
379 "The attempt to begin the transaction failed."));
|
380 kumpf 1.1 }
|
381 karl 1.15.8.1 //
382 // Since both the rollback files are created, begin transaction is over.
383 // So remove the state file for the begin transaction
384 //
385 FileSystem::removeFile(stateFilePath);
386
|
387 kumpf 1.1
388 PEG_METHOD_EXIT();
389 }
390
391 ////////////////////////////////////////////////////////////////////////////////
392 //
393 // _commitInstanceTransaction()
394 //
395 // Removes the rollback files to complete the transaction.
396 //
397 ////////////////////////////////////////////////////////////////////////////////
398
399 static void _commitInstanceTransaction(
400 const String& indexFilePath,
401 const String& dataFilePath)
402 {
403 PEG_METHOD_ENTER(TRC_REPOSITORY, "_commitInstanceTransaction");
404
|
405 karl 1.15.8.1 // Create a state file for the commit instance transaction in the same
406 // directory where the rollback files are created for index and data file.
407 // The CIMRepository checks if this file is present during
408 // its initialization.
409 // If it is present, it is assumed that the last commit transaction was
410 // incomplete due to system failure and it removes the rollback files along
411 // with this state file
412
413 String dirPath = FileSystem::extractFilePath(indexFilePath);
414 String stateFilePath = dirPath + REPOSITORY_COMMIT_PROGRESS_FILE;
415
416 fstream fs;
417
418 fs.open(stateFilePath.getCString(), ios::out PEGASUS_OR_IOS_BINARY);
419
420 if (!fs)
421 {
422 PEG_METHOD_EXIT();
423 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
424 MessageLoaderParms(
425 "Repository.CIMRepository.COMMIT_FAILED",
426 karl 1.15.8.1 "The commit operation failed."));
427 }
428
429 fs.close();
430
431 //
|
432 kumpf 1.1 //
433 // Commit the transaction by removing the rollback files.
434 //
435
436 if (!InstanceIndexFile::commitTransaction(indexFilePath))
437 {
|
438 karl 1.15.8.1 //
439 // Remove the state file
440 //
441 FileSystem::removeFile(stateFilePath);
442
|
443 kumpf 1.1 PEG_METHOD_EXIT();
444 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
|
445 karl 1.15.8.1 MessageLoaderParms(
446 "Repository.CIMRepository.COMMIT_FAILED",
447 "The commit operation failed."));
|
448 kumpf 1.1 }
449
450 if (!InstanceDataFile::commitTransaction(dataFilePath))
451 {
|
452 karl 1.15.8.1 //
453 // Remove the state file
454 //
455
456 FileSystem::removeFile(stateFilePath);
457
|
458 kumpf 1.1 PEG_METHOD_EXIT();
459 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
|
460 karl 1.15.8.1 MessageLoaderParms(
461 "Repository.CIMRepository.COMMIT_FAILED",
462 "The commit operation failed."));
|
463 kumpf 1.1 }
464
|
465 karl 1.15.8.1 //
466 // Since both the rollback files are removed, commit transaction is over.
467 // So remove the state file for the commit transaction
468 //
469 FileSystem::removeFile(stateFilePath);
470
|
471 kumpf 1.1 PEG_METHOD_EXIT();
472 }
473
474 ////////////////////////////////////////////////////////////////////////////////
475 //
476 // _rollbackInstanceTransaction()
477 //
478 // Restores instance index and data files to void an incomplete operation.
479 // If there are no rollback files, this method has no effect.
480 //
481 ////////////////////////////////////////////////////////////////////////////////
482
483 static String _dirName(const String& path)
484 {
485 Uint32 n = path.size();
486
487 for (Uint32 i = n; i != 0; )
488 {
489 if (path[--i] == '/')
490 return path.subString(0, i);
491 }
492 kumpf 1.1
493 return String(".");
494 }
495
496 static void _rollbackInstanceTransaction(
497 const String& indexFilePath,
498 const String& dataFilePath)
499 {
500 PEG_METHOD_ENTER(TRC_REPOSITORY, "_rollbackInstanceTransaction");
501
502 // Avoid rollback logic if directory has no .rollback files.
503
504 String path = _dirName(indexFilePath);
505 Array<String> rollbackFiles;
506
507 if (FileSystem::glob(path, "*.rollback", rollbackFiles))
508 {
509 if (rollbackFiles.size() == 0)
510 return;
511 }
512
513 kumpf 1.1 // Proceed to rollback logic.
|
514 karl 1.15.8.1 String dirPath = FileSystem::extractFilePath(indexFilePath);
515 String stateFilePath = dirPath + REPOSITORY_ROLLBACK_PROGRESS_FILE;
516
517 //
518 // Check the static variable "startup" to determine if this function is
519 // called from the constructor of "CIMRepository" during startup.
520 // If it is true do not create the "rollback.progress" state file.
521 //
522
523 if (!startup)
524 {
525 // Create a state file for the rollback instance transaction in the same
526 // directory where the rollback files are created for
527 // index and data file.
528 // The CIMRepository checks if this file is present during
529 // its initialization.
530 // If it is present, it is assumed that the last rollback transaction
531 // was incomplete due to system failure. So it completes
532 // the rollback instance transaction and removes this state file
533
534 fstream fs;
535 karl 1.15.8.1
536 fs.open(stateFilePath.getCString(), ios::out PEGASUS_OR_IOS_BINARY);
537
538 if (!fs)
539 {
540 PEG_METHOD_EXIT();
541 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
542 MessageLoaderParms(
543 "Repository.CIMRepository.ROLLBACK_FAILED",
544 "The rollback operation failed."));
545 }
546
547 fs.close();
548 }
|
549 kumpf 1.1
550 if (!InstanceIndexFile::rollbackTransaction(indexFilePath))
551 {
|
552 karl 1.15.8.1 if(!startup)
553 {
554 // Remove the state file
555 FileSystem::removeFile(stateFilePath);
556 }
557
|
558 kumpf 1.1 PEG_METHOD_EXIT();
559 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
|
560 karl 1.15.8.1 MessageLoaderParms(
561 "Repository.CIMRepository.ROLLBACK_FAILED",
562 "The rollback operation failed."));
|
563 kumpf 1.1 }
564
565 if (!InstanceDataFile::rollbackTransaction(dataFilePath))
566 {
|
567 karl 1.15.8.1 if(!startup)
568 {
569 // Remove the state file
570 FileSystem::removeFile(stateFilePath);
571 }
572
|
573 kumpf 1.1 PEG_METHOD_EXIT();
574 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
575 MessageLoaderParms(
576 "Repository.CIMRepository.ROLLBACK_FAILED",
|
577 karl 1.15.8.1 "The rollback operation failed."));
578 }
579
580 if (!startup)
581 {
582 // Since both the rollback files are removed,
583 // rollback transaction is over.
584 // So remove the state file for the rollback transaction
585 FileSystem::removeFile(stateFilePath);
586 }
587
588 PEG_METHOD_EXIT();
589 }
590
591
592 ////////////////////////////////////////////////////////////////////////////////
593 //
594 // FileBasedStore::_completeTransactions()
595 //
596 // Searches for state file in the "instance" directory of all
597 // namespaces.
598 karl 1.15.8.1 // i) Removes the rollback files to void a begin operation.
599 // ii) Removes the rollback files to complete a commit operation.
600 // iii) Restores instance index and data files complete a rollback
601 // operation.
602 // If no state files are present, this method returns false
603 //
604 ////////////////////////////////////////////////////////////////////////////////
605
606 Boolean FileBasedStore::_completeTransactions()
607 {
608 PEG_METHOD_ENTER(TRC_REPOSITORY,
609 "FileBasedStore::_completeTransactions");
610
611 for (Dir dir(_repositoryPath); dir.more(); dir.next())
612 {
613 String nameSpaceDirName = dir.getName();
614 if ((nameSpaceDirName == "..") ||
615 (nameSpaceDirName == ".") ||
616 (nameSpaceDirName == _CONFIGFILE_NAME))
617 {
618 continue;
619 karl 1.15.8.1 }
620
621 String nameSpacePath = _repositoryPath + "/" + nameSpaceDirName;
622 String nameSpaceName = _dirNameToNamespaceName(nameSpaceDirName);
623
624 if (!FileSystem::isDirectory(nameSpacePath + _CLASSES_SUFFIX) ||
625 !FileSystem::isDirectory(nameSpacePath + _INSTANCES_SUFFIX) ||
626 !FileSystem::isDirectory(nameSpacePath + _QUALIFIERS_SUFFIX))
627 {
628 PEG_TRACE((TRC_REPOSITORY, Tracer::LEVEL2,
629 "Namespace: %s ignored -- "
630 "subdirectories are not correctly formed",
631 (const char*)nameSpaceDirName.getCString()));
632 continue;
633 }
634
635 //
636 // Get the instance directory path
637 //
638 String dirPath = nameSpacePath + _INSTANCES_SUFFIX;
639 String classesPath = nameSpacePath + _CLASSES_SUFFIX;
640 karl 1.15.8.1
641 //
642 // Get the paths of the state files
643 //
644 String beginFilePath=dirPath+"/"+REPOSITORY_BEGIN_PROGRESS_FILE;
645 String commitFilePath=dirPath+"/"+REPOSITORY_COMMIT_PROGRESS_FILE;
646 String rollbackfilePath=dirPath+"/"+REPOSITORY_ROLLBACK_PROGRESS_FILE;
647
648 Array<String> classNames;
649
650 for (Dir dir(classesPath); dir.more(); dir.next())
651 {
652 String fileName = dir.getName();
653 // Ignore the current and parent directories.
654 if (fileName == "." || fileName == "..")
655 continue;
656
657 Uint32 dot = fileName.find('.');
658
659 // Ignore files without dots in them:
660 if (dot == PEG_NOT_FOUND)
661 karl 1.15.8.1 {
662 continue;
663 }
664 String className =
665 _unescapeUtf8FileNameCharacters(fileName.subString(0, dot));
666 classNames.append(className);
667 }
668
669 if(FileSystem::exists(beginFilePath))
670 {
671 //
672 // Either the begin or the commit operation is left incomplete
673 // Begin -> Actual repository update operation is not started.
674 // Commit -> Actual repository update operation is complete.
675 //
676 for (Uint32 j = 0; j < classNames.size(); j++)
677 {
678 //
679 // Get paths of index and data files:
680 //
681
682 karl 1.15.8.1 String indexFilePath = _getInstanceIndexFilePath(
683 nameSpaceName, classNames[j]);
684
685 String dataFilePath = _getInstanceDataFilePath(
686 nameSpaceName, classNames[j]);
687
688 InstanceIndexFile::undoBeginTransaction(indexFilePath);
689 InstanceDataFile::undoBeginTransaction(dataFilePath);
690 }
691
692 FileSystem::removeFile(beginFilePath);
693
694 PEG_METHOD_EXIT();
695 return true;
696 }
697
698 if(FileSystem::exists(commitFilePath))
699 {
700 //
701 // Either the begin or the commit operation is left incomplete
702 // Begin -> Actual repository update operation is not started.
703 karl 1.15.8.1 // Commit -> Actual repository update operation is complete.
704 // In both cases, we can safely remove the rollback files
705 //
706
707 for (Uint32 j = 0; j < classNames.size(); j++)
708 {
709 //
710 // Get paths of index and data files:
711 //
712
713 String indexFilePath = _getInstanceIndexFilePath(
714 nameSpaceName, classNames[j]);
715
716 String dataFilePath = _getInstanceDataFilePath(
717 nameSpaceName, classNames[j]);
718
719 InstanceIndexFile::commitTransaction(indexFilePath);
720 InstanceDataFile::commitTransaction(dataFilePath);
721 }
722
723 FileSystem::removeFile(commitFilePath);
724 karl 1.15.8.1
725 PEG_METHOD_EXIT();
726 return true;
727 }
728
729 if(FileSystem::exists(rollbackfilePath))
730 {
731 // Rollback transaction is left incomplete
732 // Rollback -> Call rollback
733
734 for (Uint32 j = 0; j < classNames.size(); j++)
735 {
736 // Get paths of index and data files:
737 String indexFilePath = _getInstanceIndexFilePath(
738 nameSpaceName, classNames[j]);
739
740 String dataFilePath = _getInstanceDataFilePath(
741 nameSpaceName, classNames[j]);
742
743 _rollbackInstanceTransaction(indexFilePath, dataFilePath);
744 }
745 karl 1.15.8.1
746 FileSystem::removeFile(rollbackfilePath);
747
748 PEG_METHOD_EXIT();
749 return true;
750 }
|
751 kumpf 1.1 }
752
753 PEG_METHOD_EXIT();
|
754 karl 1.15.8.1 return false;
|
755 kumpf 1.1 }
756
757 ////////////////////////////////////////////////////////////////////////////////
758 //
759 // InstanceTransactionHandler
760 //
|
761 kumpf 1.8 // This class uses a simple recovery scheme to avoid corruption of the
762 // instance repository during a "write" operation. A transaction is
763 // started when the class is instantiated, committed when the complete()
764 // method is called, and rolled back if the destructor is called without
765 // a prior call to complete().
|
766 kumpf 1.1 //
767 // The appropriate repository write locks must be owned while an
768 // InstanceTransactionHandler instance exists.
769 //
|
770 kumpf 1.8 // This algorithm is used to allow recovery on an operation failure:
771 //
772 // 1. Check to see if any rollback files exist for instances of the
773 // given class. If so, perform rollback
774 // 2. Create a rollback file for the instance file. The rollback file
775 // contains the original size of the instance file.
776 // 3. Create a rollback file for the index file. The rollback file is a
777 // copy of the instance file.
778 // 4. Update the instance file to perform the operation.
779 // 5. Update the index file to perform the operation.
780 // 6. Increment the free count in the index file if necessary, and
781 // perform reorganization if the limit is reached.
782 // 7. Delete the rollback files.
783 //
784 // The recoverability algorithm itself works as follows:
785 //
786 // 1. Delete the index file.
787 // 2. Rename the index rollback file to have the same name as the
788 // index file.
789 // 3. Truncate the instance file to have the same number of bytes as
790 // indicated in the instance rollback file.
791 kumpf 1.8 // 4. Delete the rollback files.
792 //
|
793 kumpf 1.1 ////////////////////////////////////////////////////////////////////////////////
794
795 class InstanceTransactionHandler
796 {
797 public:
798 InstanceTransactionHandler(
799 const String& indexFilePath,
800 const String& dataFilePath)
801 : _indexFilePath(indexFilePath),
802 _dataFilePath(dataFilePath),
803 _isComplete(false)
804 {
805 _rollbackInstanceTransaction(_indexFilePath, _dataFilePath);
806 _beginInstanceTransaction(_indexFilePath, _dataFilePath);
807 }
808
809 ~InstanceTransactionHandler()
810 {
811 if (!_isComplete)
812 {
813 _rollbackInstanceTransaction(_indexFilePath, _dataFilePath);
814 kumpf 1.1 }
815 }
816
817 void complete()
818 {
819 _commitInstanceTransaction(_indexFilePath, _dataFilePath);
820 _isComplete = true;
821 }
822
823 private:
824 String _indexFilePath;
825 String _dataFilePath;
826 Boolean _isComplete;
827 };
828
829
830 ////////////////////////////////////////////////////////////////////////////////
831 //
832 // FileBasedStore
833 //
834 ////////////////////////////////////////////////////////////////////////////////
835 kumpf 1.1
|
836 kumpf 1.10 Boolean FileBasedStore::isExistingRepository(const String& repositoryRoot)
837 {
838 // If this is an existing FileBasedStore repository directory, a "root"
839 // subdirectory will exist.
840 return FileSystem::isDirectory(repositoryRoot + "/root");
841 }
842
|
843 kumpf 1.1 FileBasedStore::FileBasedStore(
844 const String& repositoryPath,
845 ObjectStreamer* streamer,
846 Boolean compressMode)
847 : _repositoryPath(repositoryPath),
848 _streamer(streamer),
849 _compressMode(compressMode)
850 {
851 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::FileBasedStore");
852
853 // Create the repository directory if it does not already exist.
854
855 if (!FileSystem::isDirectory(_repositoryPath))
856 {
857 if (!FileSystem::makeDirectory(_repositoryPath))
858 {
859 PEG_METHOD_EXIT();
860 throw CannotCreateDirectory(_repositoryPath);
861 }
862 }
863
|
864 kumpf 1.6 // Initialize the _storeCompleteClasses member based on the existing
865 // repository configuration (if it already exists) or the build option.
866
867 #ifdef PEGASUS_REPOSITORY_STORE_COMPLETE_CLASSES
868 _storeCompleteClasses = true;
869 #else
870 _storeCompleteClasses = false;
871 #endif
872
873 String configFilePath = _repositoryPath + "/" + _CONFIGFILE_NAME;
874
|
875 kumpf 1.10 if (!FileBasedStore::isExistingRepository(_repositoryPath))
|
876 kumpf 1.6 {
|
877 kumpf 1.10 // This is a new repository instance. Use the setting defined by
878 // the build option.
|
879 kumpf 1.6
880 #ifndef PEGASUS_REPOSITORY_STORE_COMPLETE_CLASSES
881 PEGASUS_STD(ofstream) os;
882 if (!OpenAppend(os, configFilePath))
883 {
884 PEG_METHOD_EXIT();
885 throw CannotOpenFile(configFilePath);
886 }
887 os << "storeCompleteClasses=false" << endl;
888 #endif
889 }
890 else
891 {
892 // Repository existed previously. Determine whether its classes are
893 // complete.
894
895 if (FileSystem::exists(configFilePath))
896 {
897 ifstream ifs(configFilePath.getCString());
898
899 if (!ifs)
900 kumpf 1.6 {
901 PEG_METHOD_EXIT();
902 throw CannotOpenFile(configFilePath);
903 }
904
905 // Config file exists. Read storeCompleteClasses property.
906 // For now, this is the only thing that may appear in the file,
907 // so the parsing is easy.
908 String line;
909 if (GetLine(ifs, line))
910 {
911 if (String::equal(line, "storeCompleteClasses=false"))
912 {
913 _storeCompleteClasses = false;
914 }
915 else
916 {
917 throw Exception(MessageLoaderParms(
918 "Repository.CIMRepository.INVALID_CONFIG_FILE_ENTRY",
919 "File $0 contains an invalid entry: \"$1\".",
920 (const char*)configFilePath.getCString(),
921 kumpf 1.6 (const char*)line.getCString()));
922 }
923 }
924 else
925 {
926 throw Exception(MessageLoaderParms(
927 "Repository.CIMRepository.EMPTY_CONFIG_FILE",
928 "File $0 is empty.",
929 (const char*)configFilePath.getCString()));
930 }
931 }
932 else
933 {
934 // An existing repository without a config file indicates the
935 // legacy behavior.
936 _storeCompleteClasses = true;
937 }
938 }
939
|
940 karl 1.15.8.1 //
941 // Check if any state files are present in the repository.
942 // and bring the repository to a consistent state based
943 // on the particular state file found.
944 //
945 if (!_completeTransactions())
946 {
947 //
948 // No state files are found in the repository. So, try to
949 // rollback any incomplete transactions in the repository
950 //
951 _rollbackIncompleteTransactions();
952 }
953
954 //
955 // Reset the variable "startup" to false to indicate the
956 // end of CIMRepository constructor
957 //
958 startup = false;
|
959 kumpf 1.1
960 PEG_METHOD_EXIT();
961 }
962
963 FileBasedStore::~FileBasedStore()
964 {
965 }
966
967 ////////////////////////////////////////////////////////////////////////////////
968 //
969 // FileBasedStore::_rollbackIncompleteTransactions()
970 //
971 // Searches for incomplete instance transactions for all classes in all
972 // namespaces. Restores instance index and data files to void an
973 // incomplete operation. If no incomplete instance transactions are
974 // outstanding, this method has no effect.
975 //
976 ////////////////////////////////////////////////////////////////////////////////
977
978 void FileBasedStore::_rollbackIncompleteTransactions()
979 {
980 kumpf 1.1 PEG_METHOD_ENTER(TRC_REPOSITORY,
981 "FileBasedStore::_rollbackIncompleteTransactions");
982
983 for (Dir dir(_repositoryPath); dir.more(); dir.next())
984 {
985 String nameSpaceDirName = dir.getName();
|
986 kumpf 1.6 if ((nameSpaceDirName == "..") ||
987 (nameSpaceDirName == ".") ||
988 (nameSpaceDirName == _CONFIGFILE_NAME))
|
989 kumpf 1.1 {
990 continue;
991 }
992
993 String instanceDirPath =
994 _repositoryPath + "/" + nameSpaceDirName + _INSTANCES_SUFFIX;
995
996 // Form a list of .rollback files.
997
998 Array<String> rollbackFiles;
999 FileSystem::glob(instanceDirPath, "*.rollback", rollbackFiles);
1000
1001 // Perform a rollback operation for each class for which a rollback
1002 // file was found. A rollback may be performed twice for the same
1003 // class if index and instance rollback files exist, but that will
1004 // not cause a problem.
1005
1006 for (Uint32 i = 0; i < rollbackFiles.size(); i++)
1007 {
1008 // Parse the class name out of the file name. (We know the
1009 // file name contains a '.', since it matched the pattern above.)
1010 kumpf 1.1 String className =
1011 rollbackFiles[i].subString(0, rollbackFiles[i].find('.'));
1012
1013 _rollbackInstanceTransaction(
1014 instanceDirPath + "/" + className + ".idx",
1015 instanceDirPath + "/" + className + ".instances");
1016 }
1017 }
1018
1019 PEG_METHOD_EXIT();
1020 }
1021
1022 // This function needs to be called from within a transaction scope for
1023 // proper error handling in compacting index and data files.
1024 static void _CompactInstanceRepository(
1025 const String& indexFilePath,
1026 const String& dataFilePath)
1027 {
1028 PEG_METHOD_ENTER(TRC_REPOSITORY,
1029 "FileBasedStore::_CompactInstanceRepository");
1030
1031 kumpf 1.1 //
1032 // Compact the data file first:
1033 //
1034
1035 Array<Uint32> freeFlags;
1036 Array<Uint32> indices;
1037 Array<Uint32> sizes;
1038 Array<CIMObjectPath> instanceNames;
1039
1040 if (!InstanceIndexFile::enumerateEntries(
1041 indexFilePath, freeFlags, indices, sizes, instanceNames, true))
1042 {
1043 PEG_METHOD_EXIT();
1044 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1045 MessageLoaderParms(
1046 "Repository.CIMRepository.INDEX_ENUM_ENTRIES_FAILED",
1047 "Failed to obtain the entries from the Repository Instance"
1048 " Index file."));
1049 }
1050
1051 if (!InstanceDataFile::compact(dataFilePath, freeFlags, indices, sizes))
1052 kumpf 1.1 {
1053 PEG_METHOD_EXIT();
1054 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1055 MessageLoaderParms(
1056 "Repository.CIMRepository.COMPACT_FAILED",
1057 "Failed to compact the Repository Instance Data file."));
1058 }
1059
1060 //
1061 // Now compact the index file:
1062 //
1063
1064 if (!InstanceIndexFile::compact(indexFilePath))
1065 {
1066 PEG_METHOD_EXIT();
1067 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1068 MessageLoaderParms(
1069 "Repository.CIMRepository.INDEX_COMPACT_FAILED",
1070 "Failed to compact the Repository Instance Index file."));
1071 }
1072
1073 kumpf 1.1 PEG_METHOD_EXIT();
1074 }
1075
1076 //----------------------------------------------------------------------
1077 //
1078 // _getNameSpaceDirPath()
1079 //
1080 // returns the path of a namespace directory.
1081 //
1082 //----------------------------------------------------------------------
1083
1084 String FileBasedStore::_getNameSpaceDirPath(
1085 const CIMNamespaceName& nameSpace) const
1086 {
1087 String path;
1088 Boolean found = _nameSpacePathTable.lookup(nameSpace.getString(), path);
1089 PEGASUS_ASSERT(found);
1090 return path;
1091 }
1092
1093 //----------------------------------------------------------------------
1094 kumpf 1.1 //
1095 // _getQualifierFilePath()
1096 //
1097 // returns the path of the qualifier file.
1098 //
1099 //----------------------------------------------------------------------
1100
1101 String FileBasedStore::_getQualifierFilePath(
1102 const CIMNamespaceName& nameSpace,
1103 const CIMName& qualifierName) const
1104 {
1105 String tmp = _getNameSpaceDirPath(nameSpace);
1106 tmp.append(_QUALIFIERS_SUFFIX);
1107 tmp.append('/');
1108 tmp.append(_escapeUtf8FileNameCharacters(qualifierName.getString()));
1109 return tmp;
1110 }
1111
1112 //----------------------------------------------------------------------
1113 //
1114 // _getClassFilePath()
1115 kumpf 1.1 //
1116 // returns the path of the class file.
1117 //
1118 //----------------------------------------------------------------------
1119
1120 String FileBasedStore::_getClassFilePath(
1121 const CIMNamespaceName& nameSpace,
1122 const CIMName& className,
1123 const CIMName& superClassName) const
1124 {
1125 String tmp = _getNameSpaceDirPath(nameSpace);
1126 tmp.append(_CLASSES_SUFFIX);
1127 tmp.append('/');
1128 tmp.append(_escapeUtf8FileNameCharacters(className.getString()));
1129
1130 if (superClassName.isNull())
1131 {
1132 tmp.append(".#");
1133 }
1134 else
1135 {
1136 kumpf 1.1 tmp.append('.');
1137 tmp.append(_escapeUtf8FileNameCharacters(superClassName.getString()));
1138 }
1139
1140 return tmp;
1141 }
1142
1143 //----------------------------------------------------------------------
1144 //
1145 // _getInstanceIndexFilePath()
1146 //
1147 // returns the path of the instance index file.
1148 //
1149 //----------------------------------------------------------------------
1150
1151 String FileBasedStore::_getInstanceIndexFilePath(
1152 const CIMNamespaceName& nameSpace,
1153 const CIMName& className) const
1154 {
1155 String tmp = _getNameSpaceDirPath(nameSpace);
1156 tmp.append(_INSTANCES_SUFFIX);
1157 kumpf 1.1 tmp.append('/');
1158 tmp.append(_escapeUtf8FileNameCharacters(className.getString()));
1159 tmp.append(".idx");
1160 return tmp;
1161 }
1162
1163 //----------------------------------------------------------------------
1164 //
1165 // _getInstanceDataFilePath()
1166 //
1167 // returns the path of the instance file.
1168 //
1169 //----------------------------------------------------------------------
1170
1171 String FileBasedStore::_getInstanceDataFilePath(
1172 const CIMNamespaceName& nameSpace,
1173 const CIMName& className) const
1174 {
1175 String tmp = _getNameSpaceDirPath(nameSpace);
1176 tmp.append(_INSTANCES_SUFFIX);
1177 tmp.append('/');
1178 kumpf 1.1 tmp.append(_escapeUtf8FileNameCharacters(className.getString()));
1179 tmp.append(".instances");
1180 return tmp;
1181 }
1182
1183 //----------------------------------------------------------------------
1184 //
1185 // _getAssocClassPath()
1186 //
1187 // returns the path of the class association file.
1188 //
1189 //----------------------------------------------------------------------
1190
1191 String FileBasedStore::_getAssocClassPath(
1192 const CIMNamespaceName& nameSpace) const
1193 {
1194 String tmp = _getNameSpaceDirPath(nameSpace);
1195 tmp.append(_CLASSES_SUFFIX);
1196 tmp.append(_ASSOCIATIONS_SUFFIX);
1197 return tmp;
1198 }
1199 kumpf 1.1
1200 //----------------------------------------------------------------------
1201 //
1202 // _getAssocInstPath()
1203 //
1204 // returns the path of the instance association file.
1205 //
1206 //----------------------------------------------------------------------
1207
1208 String FileBasedStore::_getAssocInstPath(
1209 const CIMNamespaceName& nameSpace) const
1210 {
1211 String tmp = _getNameSpaceDirPath(nameSpace);
1212 tmp.append(_INSTANCES_SUFFIX);
1213 tmp.append(_ASSOCIATIONS_SUFFIX);
1214 return tmp;
1215 }
1216
1217 Boolean FileBasedStore::_loadInstance(
1218 const String& path,
1219 CIMInstance& object,
1220 kumpf 1.1 Uint32 index,
1221 Uint32 size)
1222 {
1223 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::_loadInstance");
1224
1225 //
1226 // Load instance (in XML) from instance file into memory:
1227 //
1228
1229 Buffer data;
1230
1231 if (!InstanceDataFile::loadInstance(path, index, size, data))
1232 {
1233 PEG_METHOD_EXIT();
1234 return false;
1235 }
1236
1237 //
1238 // Convert XML into an actual object:
1239 //
1240
1241 kumpf 1.1 _streamer->decode(data, 0, object);
1242
1243 PEG_METHOD_EXIT();
1244 return true;
1245 }
1246
1247 Boolean FileBasedStore::_loadAllInstances(
1248 const CIMNamespaceName& nameSpace,
1249 const CIMName& className,
1250 Array<CIMInstance>& namedInstances)
1251 {
1252 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::_loadAllInstances");
1253
1254 Array<CIMObjectPath> instanceNames;
1255 Buffer data;
1256 Array<Uint32> indices;
1257 Array<Uint32> sizes;
1258
1259 //
1260 // Form the names of the instance index and data files
1261 //
1262 kumpf 1.1
1263 String indexFilePath = _getInstanceIndexFilePath(nameSpace, className);
1264 String dataFilePath = _getInstanceDataFilePath(nameSpace, className);
1265
1266 //
1267 // Enumerate the index file:
1268 //
1269
1270 Array<Uint32> freeFlags;
1271
1272 if (!InstanceIndexFile::enumerateEntries(
1273 indexFilePath, freeFlags, indices, sizes, instanceNames, true))
1274 {
1275 PEG_METHOD_EXIT();
1276 return false;
1277 }
1278
1279 //
1280 // Form the array of instances result:
1281 //
1282
1283 kumpf 1.1 if (instanceNames.size() > 0)
1284 {
1285 //
1286 // Load all instances from the data file:
1287 //
1288
1289 if (!InstanceDataFile::loadAllInstances(dataFilePath, data))
1290 {
1291 PEG_METHOD_EXIT();
1292 return false;
1293 }
1294
1295 //
1296 // for each instance loaded, call XML parser to parse the XML
1297 // data and create a CIMInstance object.
1298 //
1299
1300 CIMInstance tmpInstance;
1301
|
1302 kumpf 1.15 const char* buffer = data.getData();
|
1303 kumpf 1.1
1304 for (Uint32 i = 0; i < instanceNames.size(); i++)
1305 {
1306 if (!freeFlags[i])
1307 {
1308 Uint32 pos= (Uint32)((&(buffer[indices[i]]))-buffer);
1309 _streamer->decode(data, pos, tmpInstance);
1310
1311 tmpInstance.setPath(instanceNames[i]);
1312
1313 namedInstances.append(tmpInstance);
1314 }
1315 }
1316 }
1317
1318 PEG_METHOD_EXIT();
1319 return true;
1320 }
1321
1322 Array<NamespaceDefinition> FileBasedStore::enumerateNameSpaces()
1323 {
1324 kumpf 1.1 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::enumerateNameSpaces");
1325
1326 Array<NamespaceDefinition> nameSpaces;
1327
1328 for (Dir dir(_repositoryPath); dir.more(); dir.next())
1329 {
1330 String nameSpaceDirName = dir.getName();
|
1331 kumpf 1.6 if ((nameSpaceDirName == "..") ||
1332 (nameSpaceDirName == ".") ||
1333 (nameSpaceDirName == _CONFIGFILE_NAME))
|
1334 kumpf 1.1 {
1335 continue;
1336 }
1337
1338 String nameSpacePath = _repositoryPath + "/" + nameSpaceDirName;
1339
1340 if (!FileSystem::isDirectory(nameSpacePath + _CLASSES_SUFFIX) ||
1341 !FileSystem::isDirectory(nameSpacePath + _INSTANCES_SUFFIX) ||
1342 !FileSystem::isDirectory(nameSpacePath + _QUALIFIERS_SUFFIX))
1343 {
|
1344 thilo.boehm 1.5 PEG_TRACE((TRC_REPOSITORY, Tracer::LEVEL2,
1345 "Namespace: %s ignored -- "
1346 "subdirectories are not correctly formed",
1347 (const char*)nameSpaceDirName.getCString()));
|
1348 kumpf 1.1 continue;
1349 }
1350
1351 NamespaceDefinition nsdef(_dirNameToNamespaceName(nameSpaceDirName));
1352
1353 Boolean skipThisNamespace = false;
1354
1355 for (Dir subdir(nameSpacePath); subdir.more(); subdir.next())
1356 {
1357 String nameSpaceSubDirName = subdir.getName();
1358 if (nameSpaceSubDirName == ".." || nameSpaceSubDirName == ".")
1359 {
1360 continue;
1361 }
1362
1363 String tmp = nameSpaceSubDirName;
1364 tmp.toLower();
1365
1366 if (tmp[0] == 's')
1367 {
1368 if ((tmp[1]=='w' || tmp[1]=='r') &&
1369 kumpf 1.1 (tmp[2]=='f' || tmp[2]=='s'))
1370 {
1371 nsdef.shareable = tmp[2]=='s';
1372 nsdef.updatesAllowed = tmp[1]=='w';
1373 String parent = nameSpaceSubDirName.subString(3);
1374 if (parent.size())
1375 {
1376 nsdef.parentNameSpace = _dirNameToNamespaceName(parent);
1377 }
1378 }
1379 else
1380 {
|
1381 thilo.boehm 1.5 PEG_TRACE((TRC_REPOSITORY, Tracer::LEVEL2,
1382 "Namespace %s ignored - "
1383 "using incorrect parent namespace specification: %s",
1384 (const char*)nameSpaceDirName.getCString(),
1385 (const char*)nameSpaceSubDirName.getCString()));
1386
|
1387 kumpf 1.1 skipThisNamespace = true;
1388 }
1389 #ifndef PEGASUS_ENABLE_REMOTE_CMPI
1390 break;
1391 #endif
1392 }
1393 #ifdef PEGASUS_ENABLE_REMOTE_CMPI
1394 else if (tmp[0] == 'r')
1395 {
|
1396 kumpf 1.4 // remoteInfo format is "ridhost[@port]" where "id" is a lower
1397 // case two-character identifier
1398 nsdef.remoteInfo = nameSpaceSubDirName;
|
1399 kumpf 1.1
|
1400 thilo.boehm 1.5 PEG_TRACE((TRC_REPOSITORY, Tracer::LEVEL4,
1401 "Remote namespace: %s >%s",
1402 (const char*)nameSpaceDirName.getCString(),
1403 (const char*)nameSpaceSubDirName.getCString()));
|
1404 kumpf 1.1 }
1405 #endif
1406 }
1407
1408 if (!skipThisNamespace)
1409 {
1410 _nameSpacePathTable.insert(
1411 nsdef.name.getString(),
1412 _repositoryPath + "/" + nameSpaceDirName);
1413 nameSpaces.append(nsdef);
1414 }
1415 }
1416
1417 PEG_METHOD_EXIT();
1418 return nameSpaces;
1419 }
1420
1421 void FileBasedStore::createNameSpace(
1422 const CIMNamespaceName& nameSpace,
1423 Boolean shareable,
1424 Boolean updatesAllowed,
|
1425 venkat.puvvada 1.11 const String& parentNameSpace,
1426 const String& remoteInfo)
|
1427 kumpf 1.1 {
1428 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::createNameSpace");
1429
1430 #ifndef PEGASUS_SUPPORT_UTF8_FILENAME
1431 // Do not allow file names to contain characters outside of 7-bit ASCII.
1432 String nameSpaceNameString = nameSpace.getString();
1433 Uint32 len = nameSpaceNameString.size();
1434 for (Uint32 i = 0; i < len; ++i)
1435 {
1436 if ((Uint16)nameSpaceNameString[i] > 0x007F)
1437 {
1438 PEG_METHOD_EXIT();
1439 throw PEGASUS_CIM_EXCEPTION(
1440 CIM_ERR_INVALID_PARAMETER, nameSpaceNameString);
1441 }
1442 }
1443 #endif
1444
1445 // Attempt to create all the namespace directories:
1446
1447 String nameSpacePath =
1448 kumpf 1.1 _repositoryPath + "/" + _namespaceNameToDirName(nameSpace);
1449
1450 if (!FileSystem::makeDirectory(nameSpacePath))
1451 {
1452 throw CannotCreateDirectory(nameSpacePath);
1453 }
1454
1455 String classesPath = nameSpacePath + _CLASSES_SUFFIX;
1456 String instancesPath = nameSpacePath + _INSTANCES_SUFFIX;
1457 String qualifiersPath = nameSpacePath + _QUALIFIERS_SUFFIX;
1458
1459 if (!FileSystem::makeDirectory(classesPath))
1460 {
1461 throw CannotCreateDirectory(classesPath);
1462 }
1463
1464 if (!FileSystem::makeDirectory(instancesPath))
1465 {
1466 throw CannotCreateDirectory(instancesPath);
1467 }
1468
1469 kumpf 1.1 if (!FileSystem::makeDirectory(qualifiersPath))
1470 {
1471 throw CannotCreateDirectory(qualifiersPath);
1472 }
1473
1474 if (shareable || !updatesAllowed || parentNameSpace.size())
1475 {
1476 String path = nameSpacePath + "/S" + (updatesAllowed ? "W" : "R") +
1477 (shareable ? "S" : "F");
1478 if (parentNameSpace.size())
1479 {
1480 path.append(_namespaceNameToDirName(parentNameSpace));
1481 }
1482
1483 if (!FileSystem::makeDirectory(path))
1484 {
1485 throw CannotCreateDirectory(path);
1486 }
1487 }
1488
|
1489 venkat.puvvada 1.11 #ifdef PEGASUS_ENABLE_REMOTE_CMPI
1490 if (remoteInfo.size())
1491 {
1492 String remoteDir(nameSpacePath);
1493 remoteDir.append("/r10");
1494 remoteDir.append(remoteInfo);
1495 if (!FileSystem::makeDirectory(remoteDir))
1496 {
1497 throw CannotCreateDirectory(remoteDir);
1498 }
1499 }
1500 #endif
1501
|
1502 kumpf 1.1 _nameSpacePathTable.insert(nameSpace.getString(), nameSpacePath);
1503
1504 PEG_METHOD_EXIT();
1505 }
1506
1507 void FileBasedStore::modifyNameSpace(
1508 const CIMNamespaceName& nameSpace,
1509 Boolean shareable,
1510 Boolean updatesAllowed)
1511 {
1512 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::modifyNameSpace");
1513
1514 String nameSpacePath = _getNameSpaceDirPath(nameSpace);
1515 String oldSpecialDirName;
1516
1517 for (Dir subdir(nameSpacePath); subdir.more(); subdir.next())
1518 {
1519 String dirName = subdir.getName();
1520
1521 if ((dirName[0] == 's') || (dirName[0] == 'S'))
1522 {
1523 kumpf 1.1 oldSpecialDirName = dirName;
1524 break;
1525 }
1526 }
1527
1528 String newSpecialDirName = oldSpecialDirName;
1529
1530 if (newSpecialDirName.size() == 0)
1531 {
1532 newSpecialDirName = "SWF";
1533 }
1534
1535 newSpecialDirName[0] = 'S';
1536 newSpecialDirName[1] = updatesAllowed ? 'W' : 'R';
1537 newSpecialDirName[2] = shareable ? 'S' : 'F';
1538
1539 if (newSpecialDirName != oldSpecialDirName)
1540 {
1541 if (oldSpecialDirName.size())
1542 {
1543 FileSystem::removeDirectoryHier(
1544 kumpf 1.1 nameSpacePath + "/" + oldSpecialDirName);
1545 }
1546
1547 if (newSpecialDirName != "SWF")
1548 {
1549 String newPath = nameSpacePath + "/" + newSpecialDirName;
1550 if (!FileSystem::makeDirectory(newPath))
1551 {
1552 PEG_METHOD_EXIT();
1553 throw CannotCreateDirectory(newPath);
1554 }
1555 }
1556 }
1557
1558 PEG_METHOD_EXIT();
1559 }
1560
1561 void FileBasedStore::deleteNameSpace(const CIMNamespaceName& nameSpace)
1562 {
1563 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::deleteNameSpace");
1564
1565 kumpf 1.1 String nameSpacePath = _getNameSpaceDirPath(nameSpace);
1566
1567 if (!FileSystem::removeDirectoryHier(nameSpacePath))
1568 {
1569 PEG_METHOD_EXIT();
1570 throw CannotRemoveDirectory(nameSpacePath);
1571 }
1572
1573 _nameSpacePathTable.remove(nameSpace.getString());
1574
1575 PEG_METHOD_EXIT();
1576 }
1577
1578 Boolean FileBasedStore::isNameSpaceEmpty(const CIMNamespaceName& nameSpace)
1579 {
1580 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::isNameSpaceEmpty");
1581
1582 String nameSpacePath = _getNameSpaceDirPath(nameSpace);
1583
1584 for (Dir dir(nameSpacePath); dir.more(); dir.next())
1585 {
1586 kumpf 1.1 const char* name = dir.getName();
1587
1588 if (strcmp(name, ".") != 0 &&
1589 strcmp(name, "..") != 0 &&
1590 System::strcasecmp(name, _CLASSES_DIR) != 0 &&
1591 System::strcasecmp(name, _INSTANCES_DIR) != 0 &&
1592 System::strcasecmp(name, _QUALIFIERS_DIR) != 0)
1593 {
1594 // ATTN: Is it assumed that dependent namespaces are empty?
1595 return true;
1596 }
1597 }
1598
1599 String classesPath = nameSpacePath + _CLASSES_SUFFIX;
1600 String instancesPath = nameSpacePath + _INSTANCES_SUFFIX;
1601 String qualifiersPath = nameSpacePath + _QUALIFIERS_SUFFIX;
1602
1603 PEG_METHOD_EXIT();
1604 return
1605 FileSystem::isDirectoryEmpty(classesPath) &&
1606 FileSystem::isDirectoryEmpty(instancesPath) &&
1607 kumpf 1.1 FileSystem::isDirectoryEmpty(qualifiersPath);
1608 }
1609
1610 Array<CIMQualifierDecl> FileBasedStore::enumerateQualifiers(
1611 const CIMNamespaceName& nameSpace)
1612 {
1613 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::enumerateQualifiers");
1614
1615 String qualifiersRoot =
1616 _getNameSpaceDirPath(nameSpace) + _QUALIFIERS_SUFFIX;
1617
1618 Array<String> qualifierNames;
1619
1620 if (!FileSystem::getDirectoryContents(qualifiersRoot, qualifierNames))
1621 {
1622 PEG_METHOD_EXIT();
1623 String str ="enumerateQualifiers()";
1624 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1625 MessageLoaderParms("Repository.CIMRepository.INTERNAL_ERROR",
1626 "$0: internal error",
1627 str));
1628 kumpf 1.1 }
1629
1630 Array<CIMQualifierDecl> qualifiers;
1631
1632 for (Uint32 i = 0; i < qualifierNames.size(); i++)
1633 {
1634 CIMQualifierDecl qualifier = getQualifier(
1635 nameSpace, _unescapeUtf8FileNameCharacters(qualifierNames[i]));
1636 qualifiers.append(qualifier);
1637 }
1638
1639 PEG_METHOD_EXIT();
1640 return qualifiers;
1641 }
1642
1643 CIMQualifierDecl FileBasedStore::getQualifier(
1644 const CIMNamespaceName& nameSpace,
1645 const CIMName& qualifierName)
1646 {
1647 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::getQualifier");
1648
1649 kumpf 1.1 CIMQualifierDecl qualifierDecl;
1650
1651 //
1652 // Get path of qualifier file:
1653 //
1654
1655 String qualifierFilePath = _getQualifierFilePath(nameSpace, qualifierName);
1656
1657 try
1658 {
1659 _LoadObject(qualifierFilePath, qualifierDecl, _streamer);
1660 }
1661 catch (const CannotOpenFile&)
1662 {
1663 // Qualifier not found
1664 PEG_METHOD_EXIT();
1665 return CIMQualifierDecl();
1666 }
1667
1668 PEG_METHOD_EXIT();
1669 return qualifierDecl;
1670 kumpf 1.1 }
1671
1672 void FileBasedStore::setQualifier(
1673 const CIMNamespaceName& nameSpace,
1674 const CIMQualifierDecl& qualifierDecl)
1675 {
1676 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::setQualifier");
1677
1678 // -- Get path of qualifier file:
1679
1680 String qualifierFilePath =
1681 _getQualifierFilePath(nameSpace, qualifierDecl.getName());
1682
1683 // -- If qualifier already exists, throw exception:
1684
1685 if (FileSystem::existsNoCase(qualifierFilePath))
1686 {
1687 PEG_METHOD_EXIT();
1688 throw PEGASUS_CIM_EXCEPTION(
1689 CIM_ERR_NOT_SUPPORTED, qualifierDecl.getName().getString());
1690 }
1691 kumpf 1.1
1692 // -- Save qualifier:
1693
1694 Buffer qualifierDeclXml;
1695 _streamer->encode(qualifierDeclXml, qualifierDecl);
|
1696 kumpf 1.7 _SaveObject(qualifierFilePath, qualifierDeclXml, _streamer, _compressMode);
|
1697 kumpf 1.1
1698 PEG_METHOD_EXIT();
1699 }
1700
1701 void FileBasedStore::deleteQualifier(
1702 const CIMNamespaceName& nameSpace,
1703 const CIMName& qualifierName)
1704 {
1705 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::deleteQualifier");
1706
1707 // -- Get path of qualifier file:
1708
1709 String qualifierFilePath = _getQualifierFilePath(nameSpace, qualifierName);
1710
1711 // -- Delete qualifier:
1712
1713 if (!FileSystem::removeFileNoCase(qualifierFilePath))
1714 {
1715 PEG_METHOD_EXIT();
1716 throw PEGASUS_CIM_EXCEPTION(
1717 CIM_ERR_NOT_FOUND, qualifierName.getString());
1718 kumpf 1.1 }
1719
1720 PEG_METHOD_EXIT();
1721 }
1722
1723 Array<Pair<String, String> > FileBasedStore::enumerateClassNames(
1724 const CIMNamespaceName& nameSpace)
1725 {
1726 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::enumerateClassNames");
1727
1728 Array<Pair<String, String> > classList;
1729
1730 String classesPath = _getNameSpaceDirPath(nameSpace) + _CLASSES_SUFFIX;
1731
1732 for (Dir dir(classesPath); dir.more(); dir.next())
1733 {
1734 String fileName = dir.getName();
1735
1736 // Ignore the current and parent directories.
1737
1738 if (fileName == "." || fileName == "..")
1739 kumpf 1.1 continue;
1740
1741 Uint32 dot = fileName.find('.');
1742
1743 // Ignore files without dots in them:
1744
1745 if (dot == PEG_NOT_FOUND)
1746 continue;
1747
1748 String className =
1749 _unescapeUtf8FileNameCharacters(fileName.subString(0, dot));
1750 String superClassName =
1751 _unescapeUtf8FileNameCharacters(fileName.subString(dot + 1));
1752
1753 if (superClassName == "#")
1754 superClassName.clear();
1755
1756 classList.append(Pair<String, String>(className, superClassName));
1757 }
1758
1759 PEG_METHOD_EXIT();
1760 kumpf 1.1 return classList;
1761 }
1762
1763 CIMClass FileBasedStore::getClass(
1764 const CIMNamespaceName& nameSpace,
1765 const CIMName& className,
1766 const CIMName& superClassName)
1767 {
1768 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::getClass");
1769
1770 String classFilePath =
1771 _getClassFilePath(nameSpace, className, superClassName);
1772 CIMClass cimClass;
1773 _LoadObject(classFilePath, cimClass, _streamer);
1774
1775 PEG_METHOD_EXIT();
1776 return cimClass;
1777 }
1778
1779 void FileBasedStore::createClass(
1780 const CIMNamespaceName& nameSpace,
|
1781 kumpf 1.3 const CIMClass& newClass,
1782 const Array<ClassAssociation>& classAssocEntries)
|
1783 kumpf 1.1 {
1784 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::createClass");
1785
1786 #ifndef PEGASUS_SUPPORT_UTF8_FILENAME
1787 // Do not allow file names to contain characters outside of 7-bit ASCII.
1788 String classNameString = newClass.getClassName().getString();
1789 Uint32 len = classNameString.size();
1790 for (Uint32 i = 0; i < len; ++i)
1791 {
1792 if ((Uint16)classNameString[i] > 0x007F)
1793 {
1794 PEG_METHOD_EXIT();
1795 throw PEGASUS_CIM_EXCEPTION(
1796 CIM_ERR_INVALID_PARAMETER, classNameString);
1797 }
1798 }
1799 #endif
1800
1801 String classFilePath = _getClassFilePath(
1802 nameSpace, newClass.getClassName(), newClass.getSuperClassName());
1803 Buffer classXml;
1804 kumpf 1.1 _streamer->encode(classXml, newClass);
|
1805 kumpf 1.7 _SaveObject(classFilePath, classXml, _streamer, _compressMode);
|
1806 kumpf 1.1
|
1807 kumpf 1.3 if (classAssocEntries.size())
1808 {
1809 _addClassAssociationEntries(nameSpace, classAssocEntries);
1810 }
1811
|
1812 kumpf 1.1 PEG_METHOD_EXIT();
1813 }
1814
1815 void FileBasedStore::modifyClass(
1816 const CIMNamespaceName& nameSpace,
|
1817 kumpf 1.3 const CIMClass& modifiedClass,
|
1818 kumpf 1.6 const CIMName& oldSuperClassName,
|
1819 kumpf 1.3 Boolean isAssociation,
1820 const Array<ClassAssociation>& classAssocEntries)
|
1821 kumpf 1.1 {
1822 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::modifyClass");
1823
1824 String classFilePath = _getClassFilePath(
1825 nameSpace,
1826 modifiedClass.getClassName(),
1827 modifiedClass.getSuperClassName());
1828
|
1829 kumpf 1.6 String oldClassFilePath = _getClassFilePath(
1830 nameSpace,
1831 modifiedClass.getClassName(),
1832 oldSuperClassName);
1833
|
1834 kumpf 1.1 //
1835 // Delete the old file containing the class:
1836 //
1837
|
1838 kumpf 1.6 if (!FileSystem::removeFileNoCase(oldClassFilePath))
|
1839 kumpf 1.1 {
1840 PEG_METHOD_EXIT();
1841 // ATTN: Parameter should be file name, not method name.
1842 String str = "FileBasedStore::modifyClass()";
1843 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1844 MessageLoaderParms(
1845 "Repository.CIMRepository.FAILED_TO_REMOVE_FILE",
|
1846 kumpf 1.6 "failed to remove file in $0", classFilePath /*str*/));
|
1847 kumpf 1.1 }
1848
1849 //
1850 // Create new class file:
1851 //
1852
1853 Buffer classXml;
1854 _streamer->encode(classXml, modifiedClass);
|
1855 kumpf 1.7 _SaveObject(classFilePath, classXml, _streamer, _compressMode);
|
1856 kumpf 1.1
|
1857 kumpf 1.3 //
1858 // Update the association entries
1859 //
1860
1861 if (isAssociation)
1862 {
1863 _removeClassAssociationEntries(nameSpace, modifiedClass.getClassName());
1864 if (classAssocEntries.size())
1865 {
1866 _addClassAssociationEntries(nameSpace, classAssocEntries);
1867 }
1868 }
1869
|
1870 kumpf 1.1 PEG_METHOD_EXIT();
1871 }
1872
1873 void FileBasedStore::deleteClass(
1874 const CIMNamespaceName& nameSpace,
1875 const CIMName& className,
|
1876 kumpf 1.3 const CIMName& superClassName,
1877 Boolean isAssociation,
1878 const Array<CIMNamespaceName>& dependentNameSpaceNames)
|
1879 kumpf 1.1 {
1880 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::deleteClass");
1881
|
1882 kumpf 1.3 //
1883 // Clean up the instance files in this namespace and in all dependent
1884 // namespaces. (It was already checked that no instances exist.)
1885 //
1886
1887 for (Uint32 i = 0; i < dependentNameSpaceNames.size(); i++)
1888 {
1889 String indexFilePath =
1890 _getInstanceIndexFilePath(nameSpace, className);
1891 String dataFilePath =
1892 _getInstanceDataFilePath(nameSpace, className);
1893
1894 FileSystem::removeFileNoCase(indexFilePath);
1895 FileSystem::removeFileNoCase(dataFilePath);
1896 }
1897
|
1898 kumpf 1.1 // Remove class file
1899
1900 String classFilePath =
1901 _getClassFilePath(nameSpace, className, superClassName);
1902
1903 if (!FileSystem::removeFileNoCase(classFilePath))
1904 {
1905 PEG_METHOD_EXIT();
1906 throw CannotRemoveFile(classFilePath);
1907 }
1908
|
1909 kumpf 1.3 //
1910 // Remove association entries
1911 //
1912
1913 if (isAssociation)
1914 {
1915 _removeClassAssociationEntries(nameSpace, className);
1916 }
1917
|
1918 kumpf 1.1 PEG_METHOD_EXIT();
1919 }
1920
1921 Array<CIMObjectPath> FileBasedStore::enumerateInstanceNamesForClass(
1922 const CIMNamespaceName& nameSpace,
1923 const CIMName& className)
1924 {
1925 PEG_METHOD_ENTER(TRC_REPOSITORY,
1926 "FileBasedStore::enumerateInstanceNamesForClass");
1927
1928 //
1929 // Get instance names from the instance index file for the class:
1930 //
1931 Array<Uint32> indices;
1932 Array<Uint32> sizes;
1933
1934 //
1935 // Form the names of the instance index and data files
1936 //
1937
1938 String indexFilePath = _getInstanceIndexFilePath(nameSpace, className);
1939 kumpf 1.1 String dataFilePath = _getInstanceDataFilePath(nameSpace, className);
1940
1941 //
1942 // Get all instances for the class:
1943 //
1944
1945 Array<CIMObjectPath> instanceNames;
1946 Array<Uint32> freeFlags;
1947
1948 if (!InstanceIndexFile::enumerateEntries(
1949 indexFilePath, freeFlags, indices, sizes, instanceNames, false))
1950 {
1951 PEG_METHOD_EXIT();
1952 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1953 MessageLoaderParms(
1954 "Repository.CIMRepository.FAILED_TO_LOAD_INSTANCE_NAMES",
1955 "Failed to load instance names in class $0",
1956 className.getString()));
1957 }
1958
1959 PEG_METHOD_EXIT();
1960 kumpf 1.1 return instanceNames;
1961 }
1962
1963 Array<CIMInstance> FileBasedStore::enumerateInstancesForClass(
1964 const CIMNamespaceName& nameSpace,
1965 const CIMName& className)
1966 {
1967 PEG_METHOD_ENTER(TRC_REPOSITORY,
1968 "FileBasedStore::enumerateInstancesForClass");
1969
1970 Array<CIMInstance> cimInstances;
1971
1972 if (!_loadAllInstances(nameSpace, className, cimInstances))
1973 {
1974 PEG_METHOD_EXIT();
1975 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1976 MessageLoaderParms(
1977 "Repository.CIMRepository.FAILED_TO_LOAD_INSTANCES",
1978 "Failed to load instances in class $0",
1979 className.getString()));
1980 }
1981 kumpf 1.1
1982 PEG_METHOD_EXIT();
1983 return cimInstances;
1984 }
1985
1986 CIMInstance FileBasedStore::getInstance(
1987 const CIMNamespaceName& nameSpace,
1988 const CIMObjectPath& instanceName)
1989 {
1990 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::getInstance");
1991
1992 //
1993 // Get paths of index and data files:
1994 //
1995
1996 String indexFilePath = _getInstanceIndexFilePath(
1997 nameSpace, instanceName.getClassName());
1998
1999 String dataFilePath = _getInstanceDataFilePath(
2000 nameSpace, instanceName.getClassName());
2001
2002 kumpf 1.1 //
2003 // Get the index for this instance:
2004 //
2005
2006 Uint32 index;
2007 Uint32 size;
2008
2009 if (!InstanceIndexFile::lookupEntry(
2010 indexFilePath, instanceName, index, size))
2011 {
2012 PEG_METHOD_EXIT();
2013 throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, instanceName.toString());
2014 }
2015
2016 //
2017 // Load the instance from file:
2018 //
2019
2020 CIMInstance cimInstance;
2021
2022 if (!_loadInstance(dataFilePath, cimInstance, index, size))
2023 kumpf 1.1 {
2024 PEG_METHOD_EXIT();
2025 throw CannotOpenFile(dataFilePath);
2026 }
2027
2028 PEG_METHOD_EXIT();
2029 return cimInstance;
2030 }
2031
2032 void FileBasedStore::createInstance(
2033 const CIMNamespaceName& nameSpace,
2034 const CIMObjectPath& instanceName,
|
2035 kumpf 1.3 const CIMInstance& cimInstance,
2036 const Array<InstanceAssociation>& instAssocEntries)
|
2037 kumpf 1.1 {
2038 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::createInstance");
2039
2040 //
2041 // Get paths to data and index files:
2042 //
2043
2044 String indexFilePath = _getInstanceIndexFilePath(
2045 nameSpace, cimInstance.getClassName());
2046
2047 String dataFilePath = _getInstanceDataFilePath(
2048 nameSpace, cimInstance.getClassName());
2049
2050 //
2051 // Perform the operation in a transaction scope to enable rollback on
2052 // failure.
2053 //
2054
2055 InstanceTransactionHandler transaction(indexFilePath, dataFilePath);
2056
2057 //
2058 kumpf 1.1 // Save instance to file:
2059 //
2060
2061 Uint32 index;
2062 Uint32 size;
2063
2064 {
2065 Buffer data;
2066 _streamer->encode(data, cimInstance);
2067 size = data.size();
2068
2069 if (!InstanceDataFile::appendInstance(dataFilePath, data, index))
2070 {
2071 PEG_METHOD_EXIT();
2072 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
2073 MessageLoaderParms(
2074 "Repository.CIMRepository.FAILED_TO_CREATE_INSTANCE",
2075 "Failed to create instance: $0",
2076 instanceName.toString()));
2077 }
2078 }
2079 kumpf 1.1
2080 //
2081 // Create entry in index file:
2082 //
2083
2084 if (!InstanceIndexFile::createEntry(
2085 indexFilePath, instanceName, index, size))
2086 {
2087 PEG_METHOD_EXIT();
2088 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
2089 MessageLoaderParms(
2090 "Repository.CIMRepository.FAILED_TO_CREATE_INSTANCE",
2091 "Failed to create instance: $0",
2092 instanceName.toString()));
2093 }
2094
2095 transaction.complete();
2096
|
2097 kumpf 1.3 //
2098 // Create association entries if an association instance.
2099 //
2100
2101 if (instAssocEntries.size())
2102 {
2103 _addInstanceAssociationEntries(nameSpace, instAssocEntries);
2104 }
2105
|
2106 kumpf 1.1 PEG_METHOD_EXIT();
2107 }
2108
2109 void FileBasedStore::modifyInstance(
2110 const CIMNamespaceName& nameSpace,
2111 const CIMObjectPath& instanceName,
2112 const CIMInstance& cimInstance)
2113 {
2114 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::modifyInstance");
2115
2116 //
2117 // Get paths of index and data files:
2118 //
2119
2120 String indexFilePath = _getInstanceIndexFilePath(
2121 nameSpace, cimInstance.getClassName());
2122
2123 String dataFilePath = _getInstanceDataFilePath(
2124 nameSpace, cimInstance.getClassName());
2125
2126 //
2127 kumpf 1.1 // Look up the specified instance
2128 //
2129
2130 Uint32 oldSize;
2131 Uint32 oldIndex;
2132 Uint32 newSize;
2133 Uint32 newIndex;
2134
2135 if (!InstanceIndexFile::lookupEntry(
2136 indexFilePath, instanceName, oldIndex, oldSize))
2137 {
2138 PEG_METHOD_EXIT();
2139 throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, instanceName.toString());
2140 }
2141
2142 //
2143 // Perform the operation in a transaction scope to enable rollback on
2144 // failure.
2145 //
2146
2147 InstanceTransactionHandler transaction(indexFilePath, dataFilePath);
2148 kumpf 1.1
2149 //
2150 // Modify the data file:
2151 //
2152
2153 {
2154 Buffer out;
2155 _streamer->encode(out, cimInstance);
2156
2157 newSize = out.size();
2158
2159 if (!InstanceDataFile::appendInstance(dataFilePath, out, newIndex))
2160 {
2161 PEG_METHOD_EXIT();
2162 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
2163 MessageLoaderParms(
2164 "Repository.CIMRepository.FAILED_TO_MODIFY_INSTANCE",
2165 "Failed to modify instance $0",
2166 instanceName.toString()));
2167 }
2168 }
2169 kumpf 1.1
2170 //
2171 // Modify the index file:
2172 //
2173
2174 Uint32 freeCount;
2175
2176 if (!InstanceIndexFile::modifyEntry(indexFilePath, instanceName, newIndex,
2177 newSize, freeCount))
2178 {
2179 PEG_METHOD_EXIT();
2180 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
2181 MessageLoaderParms(
2182 "Repository.CIMRepository.FAILED_TO_MODIFY_INSTANCE",
2183 "Failed to modify instance $0",
2184 instanceName.toString()));
2185 }
2186
2187 //
2188 // Compact the index and data files if the free count max was
2189 // reached.
2190 kumpf 1.1 //
2191
2192 if (freeCount >= _MAX_FREE_COUNT)
2193 {
2194 _CompactInstanceRepository(indexFilePath, dataFilePath);
2195 }
2196
2197 transaction.complete();
2198
2199 PEG_METHOD_EXIT();
2200 }
2201
2202 void FileBasedStore::deleteInstance(
2203 const CIMNamespaceName& nameSpace,
2204 const CIMObjectPath& instanceName)
2205 {
2206 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::deleteInstance");
2207
2208 //
2209 // Get paths of index and data files:
2210 //
2211 kumpf 1.1
2212 String indexFilePath = _getInstanceIndexFilePath(
2213 nameSpace, instanceName.getClassName());
2214
2215 String dataFilePath = _getInstanceDataFilePath(
2216 nameSpace, instanceName.getClassName());
2217
2218 //
2219 // Perform the operation in a transaction scope to enable rollback on
2220 // failure.
2221 //
2222
2223 InstanceTransactionHandler transaction(indexFilePath, dataFilePath);
2224
2225 //
2226 // Lookup instance from the index file (raise error if not found).
2227 //
2228
2229 Uint32 index;
2230 Uint32 size;
2231
2232 kumpf 1.1 if (!InstanceIndexFile::lookupEntry(
2233 indexFilePath, instanceName, index, size))
2234 {
2235 PEG_METHOD_EXIT();
2236 throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, instanceName.toString());
2237 }
2238
2239 //
2240 // Remove entry from index file.
2241 //
2242
2243 Uint32 freeCount;
2244
2245 if (!InstanceIndexFile::deleteEntry(indexFilePath, instanceName, freeCount))
2246 {
2247 PEG_METHOD_EXIT();
2248 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
2249 MessageLoaderParms(
2250 "Repository.CIMRepository.FAILED_TO_DELETE_INSTANCE",
2251 "Failed to delete instance: $0",
2252 instanceName.toString()));
2253 kumpf 1.1 }
2254
2255 //
2256 // Compact the index and data files if the free count max was
2257 // reached.
2258 //
2259
2260 if (freeCount >= _MAX_FREE_COUNT)
2261 {
2262 _CompactInstanceRepository(indexFilePath, dataFilePath);
2263 }
2264
2265 transaction.complete();
2266
|
2267 kumpf 1.3 //
2268 // Delete from association table (if an association).
2269 //
|
2270 kumpf 1.1
|
2271 kumpf 1.3 _removeInstanceAssociationEntries(nameSpace, instanceName);
|
2272 kumpf 1.1
2273 PEG_METHOD_EXIT();
2274 }
2275
2276 Boolean FileBasedStore::instanceExists(
2277 const CIMNamespaceName& nameSpace,
2278 const CIMObjectPath& instanceName)
2279 {
2280 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::instanceExists");
2281
2282 String path =
2283 _getInstanceIndexFilePath(nameSpace, instanceName.getClassName());
2284
2285 Uint32 index;
2286 Uint32 size;
2287 if (InstanceIndexFile::lookupEntry(path, instanceName, index, size))
2288 {
2289 PEG_METHOD_EXIT();
2290 return true;
2291 }
2292
2293 kumpf 1.1 PEG_METHOD_EXIT();
2294 return false;
2295 }
2296
|
2297 kumpf 1.3 void FileBasedStore::_addClassAssociationEntries(
|
2298 kumpf 1.1 const CIMNamespaceName& nameSpace,
2299 const Array<ClassAssociation>& classAssocEntries)
2300 {
|
2301 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY,
2302 "FileBasedStore::_addClassAssociationEntries");
|
2303 kumpf 1.1
2304 String assocFileName = _getAssocClassPath(nameSpace);
2305 PEGASUS_STD(ofstream) os;
2306
2307 if (!OpenAppend(os, assocFileName))
2308 {
2309 PEG_METHOD_EXIT();
2310 throw CannotOpenFile(assocFileName);
2311 }
2312
2313 for (Uint32 i = 0; i < classAssocEntries.size(); i++)
2314 {
|
2315 kumpf 1.9 _assocClassTable.append(
|
2316 kumpf 1.1 os,
2317 assocFileName,
|
2318 kumpf 1.9 classAssocEntries[i]);
|
2319 kumpf 1.1 }
2320
2321 PEG_METHOD_EXIT();
2322 }
2323
|
2324 kumpf 1.3 void FileBasedStore::_removeClassAssociationEntries(
|
2325 kumpf 1.1 const CIMNamespaceName& nameSpace,
2326 const CIMName& assocClassName)
2327 {
|
2328 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY,
2329 "FileBasedStore::_removeClassAssociationEntries");
|
2330 kumpf 1.1
2331 String assocFileName = _getAssocClassPath(nameSpace);
|
2332 kumpf 1.9 _assocClassTable.deleteAssociation(assocFileName, assocClassName);
|
2333 kumpf 1.1
2334 PEG_METHOD_EXIT();
2335 }
2336
2337 void FileBasedStore::getClassAssociatorNames(
2338 const CIMNamespaceName& nameSpace,
2339 const Array<CIMName>& classList,
2340 const Array<CIMName>& assocClassList,
2341 const Array<CIMName>& resultClassList,
2342 const String& role,
2343 const String& resultRole,
2344 Array<String>& associatorNames)
2345 {
2346 PEG_METHOD_ENTER(TRC_REPOSITORY,
2347 "FileBasedStore::getClassAssociatorNames");
2348
2349 String assocFileName = _getAssocClassPath(nameSpace);
2350
|
2351 thilo.boehm 1.2 // ATTN: Return value is ignored
|
2352 kumpf 1.9 _assocClassTable.getAssociatorNames(
|
2353 thilo.boehm 1.2 assocFileName,
2354 classList,
2355 assocClassList,
2356 resultClassList,
2357 role,
2358 resultRole,
2359 associatorNames);
|
2360 kumpf 1.1
2361 PEG_METHOD_EXIT();
2362 }
2363
2364 void FileBasedStore::getClassReferenceNames(
2365 const CIMNamespaceName& nameSpace,
2366 const Array<CIMName>& classList,
2367 const Array<CIMName>& resultClassList,
2368 const String& role,
2369 Array<String>& referenceNames)
2370 {
2371 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::getClassReferenceNames");
2372
2373 String assocFileName = _getAssocClassPath(nameSpace);
2374
|
2375 thilo.boehm 1.2 // ATTN: Return value is ignored
|
2376 kumpf 1.9 _assocClassTable.getReferenceNames(
|
2377 thilo.boehm 1.2 assocFileName,
2378 classList,
2379 resultClassList,
2380 role,
2381 referenceNames);
|
2382 kumpf 1.1
2383 PEG_METHOD_EXIT();
2384 }
2385
|
2386 kumpf 1.3 void FileBasedStore::_addInstanceAssociationEntries(
|
2387 kumpf 1.1 const CIMNamespaceName& nameSpace,
2388 const Array<InstanceAssociation>& instanceAssocEntries)
2389 {
|
2390 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY,
2391 "FileBasedStore::_addInstanceAssociationEntries");
|
2392 kumpf 1.1
2393 String assocFileName = _getAssocInstPath(nameSpace);
2394 PEGASUS_STD(ofstream) os;
2395
2396 if (!OpenAppend(os, assocFileName))
2397 {
2398 PEG_METHOD_EXIT();
2399 throw CannotOpenFile(assocFileName);
2400 }
2401
2402 for (Uint32 i = 0; i < instanceAssocEntries.size(); i++)
2403 {
2404 AssocInstTable::append(
2405 os,
2406 instanceAssocEntries[i].assocInstanceName,
2407 instanceAssocEntries[i].assocClassName,
2408 instanceAssocEntries[i].fromInstanceName,
2409 instanceAssocEntries[i].fromClassName,
2410 instanceAssocEntries[i].fromPropertyName,
2411 instanceAssocEntries[i].toInstanceName,
2412 instanceAssocEntries[i].toClassName,
2413 kumpf 1.1 instanceAssocEntries[i].toPropertyName);
2414 }
2415
2416 PEG_METHOD_EXIT();
2417 }
2418
|
2419 kumpf 1.3 void FileBasedStore::_removeInstanceAssociationEntries(
|
2420 kumpf 1.1 const CIMNamespaceName& nameSpace,
2421 const CIMObjectPath& assocInstanceName)
2422 {
2423 PEG_METHOD_ENTER(TRC_REPOSITORY,
|
2424 kumpf 1.3 "FileBasedStore::_removeInstanceAssociationEntries");
|
2425 kumpf 1.1
2426 String assocFileName = _getAssocInstPath(nameSpace);
2427 AssocInstTable::deleteAssociation(assocFileName, assocInstanceName);
2428
2429 PEG_METHOD_EXIT();
2430 }
2431
2432 void FileBasedStore::getInstanceAssociatorNames(
2433 const CIMNamespaceName& nameSpace,
2434 const CIMObjectPath& instanceName,
2435 const Array<CIMName>& assocClassList,
2436 const Array<CIMName>& resultClassList,
2437 const String& role,
2438 const String& resultRole,
2439 Array<String>& associatorNames)
2440 {
2441 PEG_METHOD_ENTER(TRC_REPOSITORY,
2442 "FileBasedStore::getInstanceAssociatorNames");
2443
2444 String assocFileName = _getAssocInstPath(nameSpace);
2445
2446 kumpf 1.1 // ATTN: Return value is ignored.
2447 AssocInstTable::getAssociatorNames(
2448 assocFileName,
2449 instanceName,
2450 assocClassList,
2451 resultClassList,
2452 role,
2453 resultRole,
2454 associatorNames);
2455
2456 PEG_METHOD_EXIT();
2457 }
2458
2459 void FileBasedStore::getInstanceReferenceNames(
2460 const CIMNamespaceName& nameSpace,
2461 const CIMObjectPath& instanceName,
2462 const Array<CIMName>& resultClassList,
2463 const String& role,
2464 Array<String>& referenceNames)
2465 {
2466 PEG_METHOD_ENTER(TRC_REPOSITORY,
2467 kumpf 1.1 "FileBasedStore::getInstanceReferenceNames");
2468
2469 String assocFileName = _getAssocInstPath(nameSpace);
2470
2471 // ATTN: Return value is ignored.
2472 AssocInstTable::getReferenceNames(
2473 assocFileName,
2474 instanceName,
2475 resultClassList,
2476 role,
2477 referenceNames);
2478
2479 PEG_METHOD_EXIT();
2480 }
2481
2482 PEGASUS_NAMESPACE_END
|