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 marek 1.19 PEGASUS_FCT_EXECUTE_AND_ASSERT(
1034 true,
1035 _nameSpacePathTable.lookup(nameSpace.getString(), path));
1036
|
1037 kumpf 1.1 return path;
1038 }
1039
1040 //----------------------------------------------------------------------
1041 //
1042 // _getQualifierFilePath()
1043 //
1044 // returns the path of the qualifier file.
1045 //
1046 //----------------------------------------------------------------------
1047
1048 String FileBasedStore::_getQualifierFilePath(
1049 const CIMNamespaceName& nameSpace,
1050 const CIMName& qualifierName) const
1051 {
1052 String tmp = _getNameSpaceDirPath(nameSpace);
1053 tmp.append(_QUALIFIERS_SUFFIX);
1054 tmp.append('/');
1055 tmp.append(_escapeUtf8FileNameCharacters(qualifierName.getString()));
1056 return tmp;
1057 }
1058 kumpf 1.1
1059 //----------------------------------------------------------------------
1060 //
1061 // _getClassFilePath()
1062 //
1063 // returns the path of the class file.
1064 //
1065 //----------------------------------------------------------------------
1066
1067 String FileBasedStore::_getClassFilePath(
1068 const CIMNamespaceName& nameSpace,
1069 const CIMName& className,
1070 const CIMName& superClassName) const
1071 {
1072 String tmp = _getNameSpaceDirPath(nameSpace);
1073 tmp.append(_CLASSES_SUFFIX);
1074 tmp.append('/');
1075 tmp.append(_escapeUtf8FileNameCharacters(className.getString()));
1076
1077 if (superClassName.isNull())
1078 {
1079 kumpf 1.1 tmp.append(".#");
1080 }
1081 else
1082 {
1083 tmp.append('.');
1084 tmp.append(_escapeUtf8FileNameCharacters(superClassName.getString()));
1085 }
1086
1087 return tmp;
1088 }
1089
1090 //----------------------------------------------------------------------
1091 //
1092 // _getInstanceIndexFilePath()
1093 //
1094 // returns the path of the instance index file.
1095 //
1096 //----------------------------------------------------------------------
1097
1098 String FileBasedStore::_getInstanceIndexFilePath(
1099 const CIMNamespaceName& nameSpace,
1100 kumpf 1.1 const CIMName& className) const
1101 {
1102 String tmp = _getNameSpaceDirPath(nameSpace);
1103 tmp.append(_INSTANCES_SUFFIX);
1104 tmp.append('/');
1105 tmp.append(_escapeUtf8FileNameCharacters(className.getString()));
1106 tmp.append(".idx");
1107 return tmp;
1108 }
1109
1110 //----------------------------------------------------------------------
1111 //
1112 // _getInstanceDataFilePath()
1113 //
1114 // returns the path of the instance file.
1115 //
1116 //----------------------------------------------------------------------
1117
1118 String FileBasedStore::_getInstanceDataFilePath(
1119 const CIMNamespaceName& nameSpace,
1120 const CIMName& className) const
1121 kumpf 1.1 {
1122 String tmp = _getNameSpaceDirPath(nameSpace);
1123 tmp.append(_INSTANCES_SUFFIX);
1124 tmp.append('/');
1125 tmp.append(_escapeUtf8FileNameCharacters(className.getString()));
1126 tmp.append(".instances");
1127 return tmp;
1128 }
1129
1130 //----------------------------------------------------------------------
1131 //
1132 // _getAssocClassPath()
1133 //
1134 // returns the path of the class association file.
1135 //
1136 //----------------------------------------------------------------------
1137
1138 String FileBasedStore::_getAssocClassPath(
1139 const CIMNamespaceName& nameSpace) const
1140 {
1141 String tmp = _getNameSpaceDirPath(nameSpace);
1142 kumpf 1.1 tmp.append(_CLASSES_SUFFIX);
1143 tmp.append(_ASSOCIATIONS_SUFFIX);
1144 return tmp;
1145 }
1146
1147 //----------------------------------------------------------------------
1148 //
1149 // _getAssocInstPath()
1150 //
1151 // returns the path of the instance association file.
1152 //
1153 //----------------------------------------------------------------------
1154
1155 String FileBasedStore::_getAssocInstPath(
1156 const CIMNamespaceName& nameSpace) const
1157 {
1158 String tmp = _getNameSpaceDirPath(nameSpace);
1159 tmp.append(_INSTANCES_SUFFIX);
1160 tmp.append(_ASSOCIATIONS_SUFFIX);
1161 return tmp;
1162 }
1163 kumpf 1.1
1164 Boolean FileBasedStore::_loadInstance(
1165 const String& path,
1166 CIMInstance& object,
1167 Uint32 index,
1168 Uint32 size)
1169 {
1170 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::_loadInstance");
1171
1172 //
1173 // Load instance (in XML) from instance file into memory:
1174 //
1175
1176 Buffer data;
1177
1178 if (!InstanceDataFile::loadInstance(path, index, size, data))
1179 {
1180 PEG_METHOD_EXIT();
1181 return false;
1182 }
1183
1184 kumpf 1.1 //
1185 // Convert XML into an actual object:
1186 //
1187
1188 _streamer->decode(data, 0, object);
1189
1190 PEG_METHOD_EXIT();
1191 return true;
1192 }
1193
1194 Boolean FileBasedStore::_loadAllInstances(
1195 const CIMNamespaceName& nameSpace,
1196 const CIMName& className,
1197 Array<CIMInstance>& namedInstances)
1198 {
1199 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::_loadAllInstances");
1200
1201 Array<CIMObjectPath> instanceNames;
1202 Buffer data;
1203 Array<Uint32> indices;
1204 Array<Uint32> sizes;
1205 kumpf 1.1
1206 //
1207 // Form the names of the instance index and data files
1208 //
1209
1210 String indexFilePath = _getInstanceIndexFilePath(nameSpace, className);
1211 String dataFilePath = _getInstanceDataFilePath(nameSpace, className);
1212
1213 //
1214 // Enumerate the index file:
1215 //
1216
1217 Array<Uint32> freeFlags;
1218
1219 if (!InstanceIndexFile::enumerateEntries(
1220 indexFilePath, freeFlags, indices, sizes, instanceNames, true))
1221 {
1222 PEG_METHOD_EXIT();
1223 return false;
1224 }
1225
1226 kumpf 1.1 //
1227 // Form the array of instances result:
1228 //
1229
1230 if (instanceNames.size() > 0)
1231 {
1232 //
1233 // Load all instances from the data file:
1234 //
1235
1236 if (!InstanceDataFile::loadAllInstances(dataFilePath, data))
1237 {
1238 PEG_METHOD_EXIT();
1239 return false;
1240 }
1241
1242 //
1243 // for each instance loaded, call XML parser to parse the XML
1244 // data and create a CIMInstance object.
1245 //
1246
1247 kumpf 1.1 CIMInstance tmpInstance;
1248
|
1249 kumpf 1.15 const char* buffer = data.getData();
|
1250 kumpf 1.1
1251 for (Uint32 i = 0; i < instanceNames.size(); i++)
1252 {
1253 if (!freeFlags[i])
1254 {
1255 Uint32 pos= (Uint32)((&(buffer[indices[i]]))-buffer);
1256 _streamer->decode(data, pos, tmpInstance);
1257
1258 tmpInstance.setPath(instanceNames[i]);
1259
1260 namedInstances.append(tmpInstance);
1261 }
1262 }
1263 }
1264
1265 PEG_METHOD_EXIT();
1266 return true;
1267 }
1268
1269 Array<NamespaceDefinition> FileBasedStore::enumerateNameSpaces()
1270 {
1271 kumpf 1.1 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::enumerateNameSpaces");
1272
1273 Array<NamespaceDefinition> nameSpaces;
1274
1275 for (Dir dir(_repositoryPath); dir.more(); dir.next())
1276 {
1277 String nameSpaceDirName = dir.getName();
|
1278 kumpf 1.6 if ((nameSpaceDirName == "..") ||
1279 (nameSpaceDirName == ".") ||
1280 (nameSpaceDirName == _CONFIGFILE_NAME))
|
1281 kumpf 1.1 {
1282 continue;
1283 }
1284
1285 String nameSpacePath = _repositoryPath + "/" + nameSpaceDirName;
1286
1287 if (!FileSystem::isDirectory(nameSpacePath + _CLASSES_SUFFIX) ||
1288 !FileSystem::isDirectory(nameSpacePath + _INSTANCES_SUFFIX) ||
1289 !FileSystem::isDirectory(nameSpacePath + _QUALIFIERS_SUFFIX))
1290 {
|
1291 thilo.boehm 1.5 PEG_TRACE((TRC_REPOSITORY, Tracer::LEVEL2,
1292 "Namespace: %s ignored -- "
1293 "subdirectories are not correctly formed",
1294 (const char*)nameSpaceDirName.getCString()));
|
1295 kumpf 1.1 continue;
1296 }
1297
1298 NamespaceDefinition nsdef(_dirNameToNamespaceName(nameSpaceDirName));
1299
1300 Boolean skipThisNamespace = false;
1301
1302 for (Dir subdir(nameSpacePath); subdir.more(); subdir.next())
1303 {
1304 String nameSpaceSubDirName = subdir.getName();
1305 if (nameSpaceSubDirName == ".." || nameSpaceSubDirName == ".")
1306 {
1307 continue;
1308 }
1309
1310 String tmp = nameSpaceSubDirName;
1311 tmp.toLower();
1312
1313 if (tmp[0] == 's')
1314 {
1315 if ((tmp[1]=='w' || tmp[1]=='r') &&
1316 kumpf 1.1 (tmp[2]=='f' || tmp[2]=='s'))
1317 {
1318 nsdef.shareable = tmp[2]=='s';
1319 nsdef.updatesAllowed = tmp[1]=='w';
1320 String parent = nameSpaceSubDirName.subString(3);
1321 if (parent.size())
1322 {
1323 nsdef.parentNameSpace = _dirNameToNamespaceName(parent);
1324 }
1325 }
1326 else
1327 {
|
1328 thilo.boehm 1.5 PEG_TRACE((TRC_REPOSITORY, Tracer::LEVEL2,
1329 "Namespace %s ignored - "
1330 "using incorrect parent namespace specification: %s",
1331 (const char*)nameSpaceDirName.getCString(),
1332 (const char*)nameSpaceSubDirName.getCString()));
1333
|
1334 kumpf 1.1 skipThisNamespace = true;
1335 }
1336 #ifndef PEGASUS_ENABLE_REMOTE_CMPI
1337 break;
1338 #endif
1339 }
1340 #ifdef PEGASUS_ENABLE_REMOTE_CMPI
1341 else if (tmp[0] == 'r')
1342 {
|
1343 kumpf 1.4 // remoteInfo format is "ridhost[@port]" where "id" is a lower
1344 // case two-character identifier
1345 nsdef.remoteInfo = nameSpaceSubDirName;
|
1346 kumpf 1.1
|
1347 thilo.boehm 1.5 PEG_TRACE((TRC_REPOSITORY, Tracer::LEVEL4,
1348 "Remote namespace: %s >%s",
1349 (const char*)nameSpaceDirName.getCString(),
1350 (const char*)nameSpaceSubDirName.getCString()));
|
1351 kumpf 1.1 }
1352 #endif
1353 }
1354
1355 if (!skipThisNamespace)
1356 {
1357 _nameSpacePathTable.insert(
1358 nsdef.name.getString(),
1359 _repositoryPath + "/" + nameSpaceDirName);
1360 nameSpaces.append(nsdef);
1361 }
1362 }
1363
1364 PEG_METHOD_EXIT();
1365 return nameSpaces;
1366 }
1367
1368 void FileBasedStore::createNameSpace(
1369 const CIMNamespaceName& nameSpace,
1370 Boolean shareable,
1371 Boolean updatesAllowed,
|
1372 venkat.puvvada 1.11 const String& parentNameSpace,
1373 const String& remoteInfo)
|
1374 kumpf 1.1 {
1375 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::createNameSpace");
1376
1377 #ifndef PEGASUS_SUPPORT_UTF8_FILENAME
1378 // Do not allow file names to contain characters outside of 7-bit ASCII.
1379 String nameSpaceNameString = nameSpace.getString();
1380 Uint32 len = nameSpaceNameString.size();
1381 for (Uint32 i = 0; i < len; ++i)
1382 {
1383 if ((Uint16)nameSpaceNameString[i] > 0x007F)
1384 {
1385 PEG_METHOD_EXIT();
1386 throw PEGASUS_CIM_EXCEPTION(
1387 CIM_ERR_INVALID_PARAMETER, nameSpaceNameString);
1388 }
1389 }
1390 #endif
1391
1392 // Attempt to create all the namespace directories:
1393
1394 String nameSpacePath =
1395 kumpf 1.1 _repositoryPath + "/" + _namespaceNameToDirName(nameSpace);
1396
1397 if (!FileSystem::makeDirectory(nameSpacePath))
1398 {
1399 throw CannotCreateDirectory(nameSpacePath);
1400 }
1401
1402 String classesPath = nameSpacePath + _CLASSES_SUFFIX;
1403 String instancesPath = nameSpacePath + _INSTANCES_SUFFIX;
1404 String qualifiersPath = nameSpacePath + _QUALIFIERS_SUFFIX;
1405
1406 if (!FileSystem::makeDirectory(classesPath))
1407 {
1408 throw CannotCreateDirectory(classesPath);
1409 }
1410
1411 if (!FileSystem::makeDirectory(instancesPath))
1412 {
1413 throw CannotCreateDirectory(instancesPath);
1414 }
1415
1416 kumpf 1.1 if (!FileSystem::makeDirectory(qualifiersPath))
1417 {
1418 throw CannotCreateDirectory(qualifiersPath);
1419 }
1420
1421 if (shareable || !updatesAllowed || parentNameSpace.size())
1422 {
1423 String path = nameSpacePath + "/S" + (updatesAllowed ? "W" : "R") +
1424 (shareable ? "S" : "F");
1425 if (parentNameSpace.size())
1426 {
1427 path.append(_namespaceNameToDirName(parentNameSpace));
1428 }
1429
1430 if (!FileSystem::makeDirectory(path))
1431 {
1432 throw CannotCreateDirectory(path);
1433 }
1434 }
1435
|
1436 venkat.puvvada 1.11 #ifdef PEGASUS_ENABLE_REMOTE_CMPI
1437 if (remoteInfo.size())
1438 {
1439 String remoteDir(nameSpacePath);
1440 remoteDir.append("/r10");
1441 remoteDir.append(remoteInfo);
1442 if (!FileSystem::makeDirectory(remoteDir))
1443 {
1444 throw CannotCreateDirectory(remoteDir);
1445 }
1446 }
|
1447 karl 1.17 #else
1448 // use unused parameter
1449 remoteInfo.size();
|
1450 venkat.puvvada 1.11 #endif
1451
|
1452 kumpf 1.1 _nameSpacePathTable.insert(nameSpace.getString(), nameSpacePath);
1453
1454 PEG_METHOD_EXIT();
1455 }
1456
1457 void FileBasedStore::modifyNameSpace(
1458 const CIMNamespaceName& nameSpace,
1459 Boolean shareable,
1460 Boolean updatesAllowed)
1461 {
1462 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::modifyNameSpace");
1463
1464 String nameSpacePath = _getNameSpaceDirPath(nameSpace);
1465 String oldSpecialDirName;
1466
1467 for (Dir subdir(nameSpacePath); subdir.more(); subdir.next())
1468 {
1469 String dirName = subdir.getName();
1470
1471 if ((dirName[0] == 's') || (dirName[0] == 'S'))
1472 {
1473 kumpf 1.1 oldSpecialDirName = dirName;
1474 break;
1475 }
1476 }
1477
1478 String newSpecialDirName = oldSpecialDirName;
1479
1480 if (newSpecialDirName.size() == 0)
1481 {
1482 newSpecialDirName = "SWF";
1483 }
1484
1485 newSpecialDirName[0] = 'S';
1486 newSpecialDirName[1] = updatesAllowed ? 'W' : 'R';
1487 newSpecialDirName[2] = shareable ? 'S' : 'F';
1488
1489 if (newSpecialDirName != oldSpecialDirName)
1490 {
1491 if (oldSpecialDirName.size())
1492 {
1493 FileSystem::removeDirectoryHier(
1494 kumpf 1.1 nameSpacePath + "/" + oldSpecialDirName);
1495 }
1496
1497 if (newSpecialDirName != "SWF")
1498 {
1499 String newPath = nameSpacePath + "/" + newSpecialDirName;
1500 if (!FileSystem::makeDirectory(newPath))
1501 {
1502 PEG_METHOD_EXIT();
1503 throw CannotCreateDirectory(newPath);
1504 }
1505 }
1506 }
1507
1508 PEG_METHOD_EXIT();
1509 }
1510
|
1511 rohini.deshpande 1.20 void FileBasedStore::modifyNameSpaceName(
1512 const CIMNamespaceName& nameSpace,
1513 const CIMNamespaceName& newNameSpaceName)
1514 {
1515 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::modifyNameSpaceName");
1516
1517 String nameSpacePath = _getNameSpaceDirPath(nameSpace);
1518 String repositoryPath = nameSpacePath;
1519 Uint32 pos = repositoryPath.reverseFind('/');
1520 repositoryPath.remove(pos+1);
1521 repositoryPath.append(_namespaceNameToDirName(newNameSpaceName));
1522 if (!FileSystem::renameFile(nameSpacePath, repositoryPath))
1523 {
1524 PEG_METHOD_EXIT();
1525 throw CannotRenameFile(nameSpacePath);
1526 }
1527 PEG_METHOD_EXIT();
1528 }
1529
|
1530 kumpf 1.1 void FileBasedStore::deleteNameSpace(const CIMNamespaceName& nameSpace)
1531 {
1532 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::deleteNameSpace");
1533
1534 String nameSpacePath = _getNameSpaceDirPath(nameSpace);
1535
1536 if (!FileSystem::removeDirectoryHier(nameSpacePath))
1537 {
1538 PEG_METHOD_EXIT();
1539 throw CannotRemoveDirectory(nameSpacePath);
1540 }
1541
1542 _nameSpacePathTable.remove(nameSpace.getString());
1543
1544 PEG_METHOD_EXIT();
1545 }
1546
1547 Boolean FileBasedStore::isNameSpaceEmpty(const CIMNamespaceName& nameSpace)
1548 {
1549 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::isNameSpaceEmpty");
1550
1551 kumpf 1.1 String nameSpacePath = _getNameSpaceDirPath(nameSpace);
1552
1553 for (Dir dir(nameSpacePath); dir.more(); dir.next())
1554 {
1555 const char* name = dir.getName();
1556
1557 if (strcmp(name, ".") != 0 &&
1558 strcmp(name, "..") != 0 &&
1559 System::strcasecmp(name, _CLASSES_DIR) != 0 &&
1560 System::strcasecmp(name, _INSTANCES_DIR) != 0 &&
1561 System::strcasecmp(name, _QUALIFIERS_DIR) != 0)
1562 {
1563 // ATTN: Is it assumed that dependent namespaces are empty?
1564 return true;
1565 }
1566 }
1567
1568 String classesPath = nameSpacePath + _CLASSES_SUFFIX;
1569 String instancesPath = nameSpacePath + _INSTANCES_SUFFIX;
1570 String qualifiersPath = nameSpacePath + _QUALIFIERS_SUFFIX;
1571
1572 kumpf 1.1 PEG_METHOD_EXIT();
1573 return
1574 FileSystem::isDirectoryEmpty(classesPath) &&
1575 FileSystem::isDirectoryEmpty(instancesPath) &&
1576 FileSystem::isDirectoryEmpty(qualifiersPath);
1577 }
1578
1579 Array<CIMQualifierDecl> FileBasedStore::enumerateQualifiers(
1580 const CIMNamespaceName& nameSpace)
1581 {
1582 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::enumerateQualifiers");
1583
1584 String qualifiersRoot =
1585 _getNameSpaceDirPath(nameSpace) + _QUALIFIERS_SUFFIX;
1586
1587 Array<String> qualifierNames;
1588
1589 if (!FileSystem::getDirectoryContents(qualifiersRoot, qualifierNames))
1590 {
1591 PEG_METHOD_EXIT();
1592 String str ="enumerateQualifiers()";
1593 kumpf 1.1 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1594 MessageLoaderParms("Repository.CIMRepository.INTERNAL_ERROR",
1595 "$0: internal error",
1596 str));
1597 }
1598
1599 Array<CIMQualifierDecl> qualifiers;
1600
1601 for (Uint32 i = 0; i < qualifierNames.size(); i++)
1602 {
1603 CIMQualifierDecl qualifier = getQualifier(
1604 nameSpace, _unescapeUtf8FileNameCharacters(qualifierNames[i]));
1605 qualifiers.append(qualifier);
1606 }
1607
1608 PEG_METHOD_EXIT();
1609 return qualifiers;
1610 }
1611
1612 CIMQualifierDecl FileBasedStore::getQualifier(
1613 const CIMNamespaceName& nameSpace,
1614 kumpf 1.1 const CIMName& qualifierName)
1615 {
1616 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::getQualifier");
1617
1618 CIMQualifierDecl qualifierDecl;
1619
1620 //
1621 // Get path of qualifier file:
1622 //
1623
1624 String qualifierFilePath = _getQualifierFilePath(nameSpace, qualifierName);
1625
1626 try
1627 {
1628 _LoadObject(qualifierFilePath, qualifierDecl, _streamer);
1629 }
1630 catch (const CannotOpenFile&)
1631 {
1632 // Qualifier not found
1633 PEG_METHOD_EXIT();
1634 return CIMQualifierDecl();
1635 kumpf 1.1 }
1636
1637 PEG_METHOD_EXIT();
1638 return qualifierDecl;
1639 }
1640
1641 void FileBasedStore::setQualifier(
1642 const CIMNamespaceName& nameSpace,
1643 const CIMQualifierDecl& qualifierDecl)
1644 {
1645 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::setQualifier");
1646
1647 // -- Get path of qualifier file:
1648
1649 String qualifierFilePath =
1650 _getQualifierFilePath(nameSpace, qualifierDecl.getName());
1651
1652 // -- If qualifier already exists, throw exception:
1653
1654 if (FileSystem::existsNoCase(qualifierFilePath))
1655 {
1656 kumpf 1.1 PEG_METHOD_EXIT();
1657 throw PEGASUS_CIM_EXCEPTION(
1658 CIM_ERR_NOT_SUPPORTED, qualifierDecl.getName().getString());
1659 }
1660
1661 // -- Save qualifier:
1662
1663 Buffer qualifierDeclXml;
1664 _streamer->encode(qualifierDeclXml, qualifierDecl);
|
1665 karl 1.17 _SaveObject(qualifierFilePath, qualifierDeclXml);
|
1666 kumpf 1.1
1667 PEG_METHOD_EXIT();
1668 }
1669
1670 void FileBasedStore::deleteQualifier(
1671 const CIMNamespaceName& nameSpace,
1672 const CIMName& qualifierName)
1673 {
1674 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::deleteQualifier");
1675
1676 // -- Get path of qualifier file:
1677
1678 String qualifierFilePath = _getQualifierFilePath(nameSpace, qualifierName);
1679
1680 // -- Delete qualifier:
1681
1682 if (!FileSystem::removeFileNoCase(qualifierFilePath))
1683 {
1684 PEG_METHOD_EXIT();
1685 throw PEGASUS_CIM_EXCEPTION(
1686 CIM_ERR_NOT_FOUND, qualifierName.getString());
1687 kumpf 1.1 }
1688
1689 PEG_METHOD_EXIT();
1690 }
1691
1692 Array<Pair<String, String> > FileBasedStore::enumerateClassNames(
1693 const CIMNamespaceName& nameSpace)
1694 {
1695 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::enumerateClassNames");
1696
1697 Array<Pair<String, String> > classList;
1698
1699 String classesPath = _getNameSpaceDirPath(nameSpace) + _CLASSES_SUFFIX;
1700
1701 for (Dir dir(classesPath); dir.more(); dir.next())
1702 {
1703 String fileName = dir.getName();
1704
1705 // Ignore the current and parent directories.
1706
1707 if (fileName == "." || fileName == "..")
1708 kumpf 1.1 continue;
1709
1710 Uint32 dot = fileName.find('.');
1711
1712 // Ignore files without dots in them:
1713
1714 if (dot == PEG_NOT_FOUND)
1715 continue;
1716
1717 String className =
1718 _unescapeUtf8FileNameCharacters(fileName.subString(0, dot));
1719 String superClassName =
1720 _unescapeUtf8FileNameCharacters(fileName.subString(dot + 1));
1721
1722 if (superClassName == "#")
1723 superClassName.clear();
1724
1725 classList.append(Pair<String, String>(className, superClassName));
1726 }
1727
1728 PEG_METHOD_EXIT();
1729 kumpf 1.1 return classList;
1730 }
1731
1732 CIMClass FileBasedStore::getClass(
1733 const CIMNamespaceName& nameSpace,
1734 const CIMName& className,
1735 const CIMName& superClassName)
1736 {
1737 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::getClass");
1738
1739 String classFilePath =
1740 _getClassFilePath(nameSpace, className, superClassName);
1741 CIMClass cimClass;
1742 _LoadObject(classFilePath, cimClass, _streamer);
1743
1744 PEG_METHOD_EXIT();
1745 return cimClass;
1746 }
1747
1748 void FileBasedStore::createClass(
1749 const CIMNamespaceName& nameSpace,
|
1750 kumpf 1.3 const CIMClass& newClass,
1751 const Array<ClassAssociation>& classAssocEntries)
|
1752 kumpf 1.1 {
1753 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::createClass");
1754
1755 #ifndef PEGASUS_SUPPORT_UTF8_FILENAME
1756 // Do not allow file names to contain characters outside of 7-bit ASCII.
1757 String classNameString = newClass.getClassName().getString();
1758 Uint32 len = classNameString.size();
1759 for (Uint32 i = 0; i < len; ++i)
1760 {
1761 if ((Uint16)classNameString[i] > 0x007F)
1762 {
1763 PEG_METHOD_EXIT();
1764 throw PEGASUS_CIM_EXCEPTION(
1765 CIM_ERR_INVALID_PARAMETER, classNameString);
1766 }
1767 }
1768 #endif
1769
1770 String classFilePath = _getClassFilePath(
1771 nameSpace, newClass.getClassName(), newClass.getSuperClassName());
1772 Buffer classXml;
1773 kumpf 1.1 _streamer->encode(classXml, newClass);
|
1774 karl 1.17 _SaveObject(classFilePath, classXml);
|
1775 kumpf 1.1
|
1776 kumpf 1.3 if (classAssocEntries.size())
1777 {
1778 _addClassAssociationEntries(nameSpace, classAssocEntries);
1779 }
1780
|
1781 kumpf 1.1 PEG_METHOD_EXIT();
1782 }
1783
1784 void FileBasedStore::modifyClass(
1785 const CIMNamespaceName& nameSpace,
|
1786 kumpf 1.3 const CIMClass& modifiedClass,
|
1787 kumpf 1.6 const CIMName& oldSuperClassName,
|
1788 kumpf 1.3 Boolean isAssociation,
1789 const Array<ClassAssociation>& classAssocEntries)
|
1790 kumpf 1.1 {
1791 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::modifyClass");
1792
1793 String classFilePath = _getClassFilePath(
1794 nameSpace,
1795 modifiedClass.getClassName(),
1796 modifiedClass.getSuperClassName());
1797
|
1798 kumpf 1.6 String oldClassFilePath = _getClassFilePath(
1799 nameSpace,
1800 modifiedClass.getClassName(),
1801 oldSuperClassName);
1802
|
1803 kumpf 1.1 //
1804 // Delete the old file containing the class:
1805 //
1806
|
1807 kumpf 1.6 if (!FileSystem::removeFileNoCase(oldClassFilePath))
|
1808 kumpf 1.1 {
1809 PEG_METHOD_EXIT();
1810 // ATTN: Parameter should be file name, not method name.
1811 String str = "FileBasedStore::modifyClass()";
1812 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1813 MessageLoaderParms(
1814 "Repository.CIMRepository.FAILED_TO_REMOVE_FILE",
|
1815 kumpf 1.6 "failed to remove file in $0", classFilePath /*str*/));
|
1816 kumpf 1.1 }
1817
1818 //
1819 // Create new class file:
1820 //
1821
1822 Buffer classXml;
1823 _streamer->encode(classXml, modifiedClass);
|
1824 karl 1.17 _SaveObject(classFilePath, classXml);
|
1825 kumpf 1.1
|
1826 kumpf 1.3 //
1827 // Update the association entries
1828 //
1829
1830 if (isAssociation)
1831 {
1832 _removeClassAssociationEntries(nameSpace, modifiedClass.getClassName());
1833 if (classAssocEntries.size())
1834 {
1835 _addClassAssociationEntries(nameSpace, classAssocEntries);
1836 }
1837 }
1838
|
1839 kumpf 1.1 PEG_METHOD_EXIT();
1840 }
1841
1842 void FileBasedStore::deleteClass(
1843 const CIMNamespaceName& nameSpace,
1844 const CIMName& className,
|
1845 kumpf 1.3 const CIMName& superClassName,
1846 Boolean isAssociation,
1847 const Array<CIMNamespaceName>& dependentNameSpaceNames)
|
1848 kumpf 1.1 {
1849 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::deleteClass");
1850
|
1851 kumpf 1.3 //
1852 // Clean up the instance files in this namespace and in all dependent
1853 // namespaces. (It was already checked that no instances exist.)
1854 //
1855
1856 for (Uint32 i = 0; i < dependentNameSpaceNames.size(); i++)
1857 {
1858 String indexFilePath =
1859 _getInstanceIndexFilePath(nameSpace, className);
1860 String dataFilePath =
1861 _getInstanceDataFilePath(nameSpace, className);
1862
1863 FileSystem::removeFileNoCase(indexFilePath);
1864 FileSystem::removeFileNoCase(dataFilePath);
1865 }
1866
|
1867 kumpf 1.1 // Remove class file
1868
1869 String classFilePath =
1870 _getClassFilePath(nameSpace, className, superClassName);
1871
1872 if (!FileSystem::removeFileNoCase(classFilePath))
1873 {
1874 PEG_METHOD_EXIT();
1875 throw CannotRemoveFile(classFilePath);
1876 }
1877
|
1878 kumpf 1.3 //
1879 // Remove association entries
1880 //
1881
1882 if (isAssociation)
1883 {
1884 _removeClassAssociationEntries(nameSpace, className);
1885 }
1886
|
1887 kumpf 1.1 PEG_METHOD_EXIT();
1888 }
1889
1890 Array<CIMObjectPath> FileBasedStore::enumerateInstanceNamesForClass(
1891 const CIMNamespaceName& nameSpace,
1892 const CIMName& className)
1893 {
1894 PEG_METHOD_ENTER(TRC_REPOSITORY,
1895 "FileBasedStore::enumerateInstanceNamesForClass");
1896
1897 //
1898 // Get instance names from the instance index file for the class:
1899 //
1900 Array<Uint32> indices;
1901 Array<Uint32> sizes;
1902
1903 //
1904 // Form the names of the instance index and data files
1905 //
1906
1907 String indexFilePath = _getInstanceIndexFilePath(nameSpace, className);
1908 kumpf 1.1 String dataFilePath = _getInstanceDataFilePath(nameSpace, className);
1909
1910 //
1911 // Get all instances for the class:
1912 //
1913
1914 Array<CIMObjectPath> instanceNames;
1915 Array<Uint32> freeFlags;
1916
1917 if (!InstanceIndexFile::enumerateEntries(
1918 indexFilePath, freeFlags, indices, sizes, instanceNames, false))
1919 {
1920 PEG_METHOD_EXIT();
1921 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1922 MessageLoaderParms(
1923 "Repository.CIMRepository.FAILED_TO_LOAD_INSTANCE_NAMES",
1924 "Failed to load instance names in class $0",
1925 className.getString()));
1926 }
1927
1928 PEG_METHOD_EXIT();
1929 kumpf 1.1 return instanceNames;
1930 }
1931
1932 Array<CIMInstance> FileBasedStore::enumerateInstancesForClass(
1933 const CIMNamespaceName& nameSpace,
1934 const CIMName& className)
1935 {
1936 PEG_METHOD_ENTER(TRC_REPOSITORY,
1937 "FileBasedStore::enumerateInstancesForClass");
1938
1939 Array<CIMInstance> cimInstances;
1940
1941 if (!_loadAllInstances(nameSpace, className, cimInstances))
1942 {
1943 PEG_METHOD_EXIT();
1944 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1945 MessageLoaderParms(
1946 "Repository.CIMRepository.FAILED_TO_LOAD_INSTANCES",
1947 "Failed to load instances in class $0",
1948 className.getString()));
1949 }
1950 kumpf 1.1
1951 PEG_METHOD_EXIT();
1952 return cimInstances;
1953 }
1954
1955 CIMInstance FileBasedStore::getInstance(
1956 const CIMNamespaceName& nameSpace,
1957 const CIMObjectPath& instanceName)
1958 {
1959 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::getInstance");
1960
1961 //
1962 // Get paths of index and data files:
1963 //
1964
1965 String indexFilePath = _getInstanceIndexFilePath(
1966 nameSpace, instanceName.getClassName());
1967
1968 String dataFilePath = _getInstanceDataFilePath(
1969 nameSpace, instanceName.getClassName());
1970
1971 kumpf 1.1 //
1972 // Get the index for this instance:
1973 //
1974
1975 Uint32 index;
1976 Uint32 size;
1977
1978 if (!InstanceIndexFile::lookupEntry(
1979 indexFilePath, instanceName, index, size))
1980 {
1981 PEG_METHOD_EXIT();
1982 throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, instanceName.toString());
1983 }
1984
1985 //
1986 // Load the instance from file:
1987 //
1988
1989 CIMInstance cimInstance;
1990
1991 if (!_loadInstance(dataFilePath, cimInstance, index, size))
1992 kumpf 1.1 {
1993 PEG_METHOD_EXIT();
1994 throw CannotOpenFile(dataFilePath);
1995 }
1996
1997 PEG_METHOD_EXIT();
1998 return cimInstance;
1999 }
2000
2001 void FileBasedStore::createInstance(
2002 const CIMNamespaceName& nameSpace,
2003 const CIMObjectPath& instanceName,
|
2004 kumpf 1.3 const CIMInstance& cimInstance,
2005 const Array<InstanceAssociation>& instAssocEntries)
|
2006 kumpf 1.1 {
2007 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::createInstance");
2008
2009 //
2010 // Get paths to data and index files:
2011 //
2012
2013 String indexFilePath = _getInstanceIndexFilePath(
2014 nameSpace, cimInstance.getClassName());
2015
2016 String dataFilePath = _getInstanceDataFilePath(
2017 nameSpace, cimInstance.getClassName());
2018
2019 //
2020 // Perform the operation in a transaction scope to enable rollback on
2021 // failure.
2022 //
2023
2024 InstanceTransactionHandler transaction(indexFilePath, dataFilePath);
2025
2026 //
2027 kumpf 1.1 // Save instance to file:
2028 //
2029
2030 Uint32 index;
2031 Uint32 size;
2032
2033 {
2034 Buffer data;
2035 _streamer->encode(data, cimInstance);
2036 size = data.size();
2037
2038 if (!InstanceDataFile::appendInstance(dataFilePath, data, index))
2039 {
2040 PEG_METHOD_EXIT();
2041 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
2042 MessageLoaderParms(
2043 "Repository.CIMRepository.FAILED_TO_CREATE_INSTANCE",
2044 "Failed to create instance: $0",
2045 instanceName.toString()));
2046 }
2047 }
2048 kumpf 1.1
2049 //
2050 // Create entry in index file:
2051 //
2052
2053 if (!InstanceIndexFile::createEntry(
2054 indexFilePath, instanceName, index, size))
2055 {
2056 PEG_METHOD_EXIT();
2057 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
2058 MessageLoaderParms(
2059 "Repository.CIMRepository.FAILED_TO_CREATE_INSTANCE",
2060 "Failed to create instance: $0",
2061 instanceName.toString()));
2062 }
2063
2064 transaction.complete();
2065
|
2066 kumpf 1.3 //
2067 // Create association entries if an association instance.
2068 //
2069
2070 if (instAssocEntries.size())
2071 {
2072 _addInstanceAssociationEntries(nameSpace, instAssocEntries);
2073 }
2074
|
2075 kumpf 1.1 PEG_METHOD_EXIT();
2076 }
2077
2078 void FileBasedStore::modifyInstance(
2079 const CIMNamespaceName& nameSpace,
2080 const CIMObjectPath& instanceName,
2081 const CIMInstance& cimInstance)
2082 {
2083 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::modifyInstance");
2084
2085 //
2086 // Get paths of index and data files:
2087 //
2088
2089 String indexFilePath = _getInstanceIndexFilePath(
2090 nameSpace, cimInstance.getClassName());
2091
2092 String dataFilePath = _getInstanceDataFilePath(
2093 nameSpace, cimInstance.getClassName());
2094
2095 //
2096 kumpf 1.1 // Look up the specified instance
2097 //
2098
2099 Uint32 oldSize;
2100 Uint32 oldIndex;
2101 Uint32 newSize;
2102 Uint32 newIndex;
2103
2104 if (!InstanceIndexFile::lookupEntry(
2105 indexFilePath, instanceName, oldIndex, oldSize))
2106 {
2107 PEG_METHOD_EXIT();
2108 throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, instanceName.toString());
2109 }
2110
2111 //
2112 // Perform the operation in a transaction scope to enable rollback on
2113 // failure.
2114 //
2115
2116 InstanceTransactionHandler transaction(indexFilePath, dataFilePath);
2117 kumpf 1.1
2118 //
2119 // Modify the data file:
2120 //
2121
2122 {
2123 Buffer out;
2124 _streamer->encode(out, cimInstance);
2125
2126 newSize = out.size();
2127
2128 if (!InstanceDataFile::appendInstance(dataFilePath, out, newIndex))
2129 {
2130 PEG_METHOD_EXIT();
2131 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
2132 MessageLoaderParms(
2133 "Repository.CIMRepository.FAILED_TO_MODIFY_INSTANCE",
2134 "Failed to modify instance $0",
2135 instanceName.toString()));
2136 }
2137 }
2138 kumpf 1.1
2139 //
2140 // Modify the index file:
2141 //
2142
2143 Uint32 freeCount;
2144
2145 if (!InstanceIndexFile::modifyEntry(indexFilePath, instanceName, newIndex,
2146 newSize, freeCount))
2147 {
2148 PEG_METHOD_EXIT();
2149 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
2150 MessageLoaderParms(
2151 "Repository.CIMRepository.FAILED_TO_MODIFY_INSTANCE",
2152 "Failed to modify instance $0",
2153 instanceName.toString()));
2154 }
2155
2156 //
2157 // Compact the index and data files if the free count max was
2158 // reached.
2159 kumpf 1.1 //
2160
2161 if (freeCount >= _MAX_FREE_COUNT)
2162 {
2163 _CompactInstanceRepository(indexFilePath, dataFilePath);
2164 }
2165
2166 transaction.complete();
2167
2168 PEG_METHOD_EXIT();
2169 }
2170
2171 void FileBasedStore::deleteInstance(
2172 const CIMNamespaceName& nameSpace,
2173 const CIMObjectPath& instanceName)
2174 {
2175 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::deleteInstance");
2176
2177 //
2178 // Get paths of index and data files:
2179 //
2180 kumpf 1.1
2181 String indexFilePath = _getInstanceIndexFilePath(
2182 nameSpace, instanceName.getClassName());
2183
2184 String dataFilePath = _getInstanceDataFilePath(
2185 nameSpace, instanceName.getClassName());
2186
2187 //
2188 // Perform the operation in a transaction scope to enable rollback on
2189 // failure.
2190 //
2191
2192 InstanceTransactionHandler transaction(indexFilePath, dataFilePath);
2193
2194 //
2195 // Lookup instance from the index file (raise error if not found).
2196 //
2197
2198 Uint32 index;
2199 Uint32 size;
2200
2201 kumpf 1.1 if (!InstanceIndexFile::lookupEntry(
2202 indexFilePath, instanceName, index, size))
2203 {
2204 PEG_METHOD_EXIT();
2205 throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, instanceName.toString());
2206 }
2207
2208 //
2209 // Remove entry from index file.
2210 //
2211
2212 Uint32 freeCount;
2213
2214 if (!InstanceIndexFile::deleteEntry(indexFilePath, instanceName, freeCount))
2215 {
2216 PEG_METHOD_EXIT();
2217 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
2218 MessageLoaderParms(
2219 "Repository.CIMRepository.FAILED_TO_DELETE_INSTANCE",
2220 "Failed to delete instance: $0",
2221 instanceName.toString()));
2222 kumpf 1.1 }
2223
2224 //
2225 // Compact the index and data files if the free count max was
2226 // reached.
2227 //
2228
2229 if (freeCount >= _MAX_FREE_COUNT)
2230 {
2231 _CompactInstanceRepository(indexFilePath, dataFilePath);
2232 }
2233
2234 transaction.complete();
2235
|
2236 kumpf 1.3 //
2237 // Delete from association table (if an association).
2238 //
|
2239 kumpf 1.1
|
2240 kumpf 1.3 _removeInstanceAssociationEntries(nameSpace, instanceName);
|
2241 kumpf 1.1
2242 PEG_METHOD_EXIT();
2243 }
2244
2245 Boolean FileBasedStore::instanceExists(
2246 const CIMNamespaceName& nameSpace,
2247 const CIMObjectPath& instanceName)
2248 {
2249 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::instanceExists");
2250
2251 String path =
2252 _getInstanceIndexFilePath(nameSpace, instanceName.getClassName());
2253
2254 Uint32 index;
2255 Uint32 size;
2256 if (InstanceIndexFile::lookupEntry(path, instanceName, index, size))
2257 {
2258 PEG_METHOD_EXIT();
2259 return true;
2260 }
2261
2262 kumpf 1.1 PEG_METHOD_EXIT();
2263 return false;
2264 }
2265
|
2266 kumpf 1.3 void FileBasedStore::_addClassAssociationEntries(
|
2267 kumpf 1.1 const CIMNamespaceName& nameSpace,
2268 const Array<ClassAssociation>& classAssocEntries)
2269 {
|
2270 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY,
2271 "FileBasedStore::_addClassAssociationEntries");
|
2272 kumpf 1.1
2273 String assocFileName = _getAssocClassPath(nameSpace);
2274 PEGASUS_STD(ofstream) os;
2275
2276 if (!OpenAppend(os, assocFileName))
2277 {
2278 PEG_METHOD_EXIT();
2279 throw CannotOpenFile(assocFileName);
2280 }
2281
2282 for (Uint32 i = 0; i < classAssocEntries.size(); i++)
2283 {
|
2284 kumpf 1.9 _assocClassTable.append(
|
2285 kumpf 1.1 os,
2286 assocFileName,
|
2287 kumpf 1.9 classAssocEntries[i]);
|
2288 kumpf 1.1 }
2289
2290 PEG_METHOD_EXIT();
2291 }
2292
|
2293 kumpf 1.3 void FileBasedStore::_removeClassAssociationEntries(
|
2294 kumpf 1.1 const CIMNamespaceName& nameSpace,
2295 const CIMName& assocClassName)
2296 {
|
2297 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY,
2298 "FileBasedStore::_removeClassAssociationEntries");
|
2299 kumpf 1.1
2300 String assocFileName = _getAssocClassPath(nameSpace);
|
2301 kumpf 1.9 _assocClassTable.deleteAssociation(assocFileName, assocClassName);
|
2302 kumpf 1.1
2303 PEG_METHOD_EXIT();
2304 }
2305
2306 void FileBasedStore::getClassAssociatorNames(
2307 const CIMNamespaceName& nameSpace,
2308 const Array<CIMName>& classList,
2309 const Array<CIMName>& assocClassList,
2310 const Array<CIMName>& resultClassList,
2311 const String& role,
2312 const String& resultRole,
2313 Array<String>& associatorNames)
2314 {
2315 PEG_METHOD_ENTER(TRC_REPOSITORY,
2316 "FileBasedStore::getClassAssociatorNames");
2317
2318 String assocFileName = _getAssocClassPath(nameSpace);
2319
|
2320 thilo.boehm 1.2 // ATTN: Return value is ignored
|
2321 kumpf 1.9 _assocClassTable.getAssociatorNames(
|
2322 thilo.boehm 1.2 assocFileName,
2323 classList,
2324 assocClassList,
2325 resultClassList,
2326 role,
2327 resultRole,
2328 associatorNames);
|
2329 kumpf 1.1
2330 PEG_METHOD_EXIT();
2331 }
2332
2333 void FileBasedStore::getClassReferenceNames(
2334 const CIMNamespaceName& nameSpace,
2335 const Array<CIMName>& classList,
2336 const Array<CIMName>& resultClassList,
2337 const String& role,
2338 Array<String>& referenceNames)
2339 {
2340 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::getClassReferenceNames");
2341
2342 String assocFileName = _getAssocClassPath(nameSpace);
2343
|
2344 thilo.boehm 1.2 // ATTN: Return value is ignored
|
2345 kumpf 1.9 _assocClassTable.getReferenceNames(
|
2346 thilo.boehm 1.2 assocFileName,
2347 classList,
2348 resultClassList,
2349 role,
2350 referenceNames);
|
2351 kumpf 1.1
2352 PEG_METHOD_EXIT();
2353 }
2354
|
2355 kumpf 1.3 void FileBasedStore::_addInstanceAssociationEntries(
|
2356 kumpf 1.1 const CIMNamespaceName& nameSpace,
2357 const Array<InstanceAssociation>& instanceAssocEntries)
2358 {
|
2359 kumpf 1.3 PEG_METHOD_ENTER(TRC_REPOSITORY,
2360 "FileBasedStore::_addInstanceAssociationEntries");
|
2361 kumpf 1.1
2362 String assocFileName = _getAssocInstPath(nameSpace);
2363 PEGASUS_STD(ofstream) os;
2364
2365 if (!OpenAppend(os, assocFileName))
2366 {
2367 PEG_METHOD_EXIT();
2368 throw CannotOpenFile(assocFileName);
2369 }
2370
2371 for (Uint32 i = 0; i < instanceAssocEntries.size(); i++)
2372 {
2373 AssocInstTable::append(
2374 os,
2375 instanceAssocEntries[i].assocInstanceName,
2376 instanceAssocEntries[i].assocClassName,
2377 instanceAssocEntries[i].fromInstanceName,
2378 instanceAssocEntries[i].fromClassName,
2379 instanceAssocEntries[i].fromPropertyName,
2380 instanceAssocEntries[i].toInstanceName,
2381 instanceAssocEntries[i].toClassName,
2382 kumpf 1.1 instanceAssocEntries[i].toPropertyName);
2383 }
2384
2385 PEG_METHOD_EXIT();
2386 }
2387
|
2388 kumpf 1.3 void FileBasedStore::_removeInstanceAssociationEntries(
|
2389 kumpf 1.1 const CIMNamespaceName& nameSpace,
2390 const CIMObjectPath& assocInstanceName)
2391 {
2392 PEG_METHOD_ENTER(TRC_REPOSITORY,
|
2393 kumpf 1.3 "FileBasedStore::_removeInstanceAssociationEntries");
|
2394 kumpf 1.1
2395 String assocFileName = _getAssocInstPath(nameSpace);
2396 AssocInstTable::deleteAssociation(assocFileName, assocInstanceName);
2397
2398 PEG_METHOD_EXIT();
2399 }
2400
2401 void FileBasedStore::getInstanceAssociatorNames(
2402 const CIMNamespaceName& nameSpace,
2403 const CIMObjectPath& instanceName,
2404 const Array<CIMName>& assocClassList,
2405 const Array<CIMName>& resultClassList,
2406 const String& role,
2407 const String& resultRole,
2408 Array<String>& associatorNames)
2409 {
2410 PEG_METHOD_ENTER(TRC_REPOSITORY,
2411 "FileBasedStore::getInstanceAssociatorNames");
2412
2413 String assocFileName = _getAssocInstPath(nameSpace);
2414
2415 kumpf 1.1 // ATTN: Return value is ignored.
2416 AssocInstTable::getAssociatorNames(
2417 assocFileName,
2418 instanceName,
2419 assocClassList,
2420 resultClassList,
2421 role,
2422 resultRole,
2423 associatorNames);
2424
2425 PEG_METHOD_EXIT();
2426 }
2427
2428 void FileBasedStore::getInstanceReferenceNames(
2429 const CIMNamespaceName& nameSpace,
2430 const CIMObjectPath& instanceName,
2431 const Array<CIMName>& resultClassList,
2432 const String& role,
2433 Array<String>& referenceNames)
2434 {
2435 PEG_METHOD_ENTER(TRC_REPOSITORY,
2436 kumpf 1.1 "FileBasedStore::getInstanceReferenceNames");
2437
2438 String assocFileName = _getAssocInstPath(nameSpace);
2439
2440 // ATTN: Return value is ignored.
2441 AssocInstTable::getReferenceNames(
2442 assocFileName,
2443 instanceName,
2444 resultClassList,
2445 role,
2446 referenceNames);
2447
2448 PEG_METHOD_EXIT();
2449 }
2450
|
2451 karl 1.17 ////////////////////////////////////////////////////////////////////////////////
2452 //
2453 // _SaveObject()
2454 //
2455 // Saves objects (classes and qualifiers) from memory to
2456 // disk files.
2457 //
2458 ////////////////////////////////////////////////////////////////////////////////
2459
2460 void FileBasedStore::_SaveObject(
2461 const String& path,
2462 Buffer& objectXml)
2463 {
2464 PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::_SaveObject");
2465
2466 #ifdef PEGASUS_ENABLE_COMPRESSED_REPOSITORY
2467 if (_compressMode) // PEP214
2468 {
2469 PEGASUS_STD(ostringstream) os;
2470 _streamer->write(os, objectXml);
2471 string str = os.str();
2472 karl 1.17
2473 gzFile fp = gzopen(path.getCString(), "wb");
2474
2475 if (fp == NULL)
2476 throw CannotOpenFile(path);
2477
2478 const char* ptr = str.data();
2479 size_t rem = str.size();
2480 int n;
2481
2482 while (rem > 0 && (n = gzwrite(fp, (char*)ptr, rem)) > 0)
2483 {
2484 ptr += n;
2485 rem -= n;
2486 }
2487
2488 gzclose(fp);
2489 }
2490 else
2491 #endif /* PEGASUS_ENABLE_COMPRESSED_REPOSITORY */
2492 {
2493 karl 1.17 PEGASUS_STD(ofstream) os(path.getCString() PEGASUS_IOS_BINARY);
2494
2495 if (!os)
2496 {
2497 PEG_METHOD_EXIT();
2498 throw CannotOpenFile(path);
2499 }
2500
2501 _streamer->write(os, objectXml);
2502 }
2503 PEG_METHOD_EXIT();
2504 }
2505
|
2506 kumpf 1.1 PEGASUS_NAMESPACE_END
|