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