(file) Return to FileBasedStore.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Repository

   1 kumpf 1.1 //%2006////////////////////////////////////////////////////////////////////////
   2           //
   3           // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
   4           // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
   5           // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
   6           // IBM Corp.; EMC Corporation, The Open Group.
   7           // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
   8           // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
   9           // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
  10           // EMC Corporation; VERITAS Software Corporation; The Open Group.
  11           // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
  12           // EMC Corporation; Symantec Corporation; The Open Group.
  13           //
  14           // Permission is hereby granted, free of charge, to any person obtaining a copy
  15           // of this software and associated documentation files (the "Software"), to
  16           // deal in the Software without restriction, including without limitation the
  17           // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  18           // sell copies of the Software, and to permit persons to whom the Software is
  19           // furnished to do so, subject to the following conditions:
  20           //
  21           // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
  22 kumpf 1.1 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
  23           // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
  24           // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  25           // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  26           // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  27           // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28           // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29           //
  30           //==============================================================================
  31           //
  32           //%/////////////////////////////////////////////////////////////////////////////
  33           
  34           #include <Pegasus/Common/Config.h>
  35           #include <cctype>
  36           #include <cstdio>
  37           #include <fstream>
  38           
  39           #include <Pegasus/Common/InternalException.h>
  40           #include <Pegasus/Common/DeclContext.h>
  41           #include <Pegasus/Common/Resolver.h>
  42           #include <Pegasus/Common/System.h>
  43 kumpf 1.1 #include <Pegasus/Common/Tracer.h>
  44           #include <Pegasus/Common/MessageLoader.h>
  45           #include <Pegasus/Common/FileSystem.h>
  46           #include <Pegasus/Common/Dir.h>
  47           #include <Pegasus/Common/CommonUTF.h>
  48           #include "InstanceIndexFile.h"
  49           #include "InstanceDataFile.h"
  50           #include "AssocInstTable.h"
  51           #include "AssocClassTable.h"
  52           #include "FileBasedStore.h"
  53           
  54           #ifdef PEGASUS_ENABLE_COMPRESSED_REPOSITORY
  55           // #define win32
  56           # include <zlib.h>
  57           # include <sstream>
  58           #endif
  59           
  60           PEGASUS_NAMESPACE_BEGIN
  61           
  62           static const char _CLASSES_DIR[] = "classes";
  63           static const char _INSTANCES_DIR[] = "instances";
  64 kumpf 1.1 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           static const Uint32 _MAX_FREE_COUNT = 16;
  72           
  73           static inline String _escapeUtf8FileNameCharacters(const String& fileName)
  74           {
  75           #ifdef PEGASUS_REPOSITORY_ESCAPE_UTF8
  76               // All chars above 0x7F will be escape.
  77               return escapeStringEncoder(fileName);
  78           #else
  79               return fileName;
  80           #endif
  81           }
  82           
  83           static inline String _unescapeUtf8FileNameCharacters(const String& fileName)
  84           {
  85 kumpf 1.1 #ifdef PEGASUS_REPOSITORY_ESCAPE_UTF8
  86               return escapeStringDecoder(fileName);
  87           #else
  88               return fileName;
  89           #endif
  90           }
  91           
  92           ////////////////////////////////////////////////////////////////////////////////
  93           //
  94           // _namespaceNameToDirName()
  95           //
  96           ////////////////////////////////////////////////////////////////////////////////
  97           
  98           static String _namespaceNameToDirName(const CIMNamespaceName& namespaceName)
  99           {
 100               String nameSpaceDirName = namespaceName.getString();
 101           
 102               for (Uint32 i = 0; i < nameSpaceDirName.size(); i++)
 103               {
 104                   if (nameSpaceDirName[i] == '/')
 105                   {
 106 kumpf 1.1             nameSpaceDirName[i] = '#';
 107                   }
 108               }
 109           
 110               return _escapeUtf8FileNameCharacters(nameSpaceDirName);
 111           }
 112           
 113           ////////////////////////////////////////////////////////////////////////////////
 114           //
 115           // _dirNameToNamespaceName()
 116           //
 117           ////////////////////////////////////////////////////////////////////////////////
 118           
 119           static String _dirNameToNamespaceName(const String& nameSpaceDirName)
 120           {
 121               String namespaceName = nameSpaceDirName;
 122           
 123               for (Uint32 i = 0; i < namespaceName.size(); i++)
 124               {
 125                   if (namespaceName[i] == '#')
 126                   {
 127 kumpf 1.1             namespaceName[i] = '/';
 128                   }
 129               }
 130           #ifdef PEGASUS_REPOSITORY_ESCAPE_UTF8
 131               // All chars above 0x7F will be escape.
 132               return escapeStringDecoder(namespaceName);
 133           #else
 134               return namespaceName;
 135           #endif
 136           }
 137           
 138           ////////////////////////////////////////////////////////////////////////////////
 139           //
 140           // _LoadFileToMemory()  PEP214
 141           //
 142           // The gzxxxx functions read both compresed and non-compresed files.
 143           //
 144           // There is no conditional flag on reading of files since gzread()
 145           // (from zlib) is capable of reading compressed and non-compressed
 146           // files (so it contains the logic that examines the header
 147           // and magic number). Everything will work properly if the repository
 148 kumpf 1.1 // has some compressed and some non-compressed files.
 149           //
 150           //
 151           ////////////////////////////////////////////////////////////////////////////////
 152           
 153           static void _LoadFileToMemory(Buffer& data, const String& path)
 154           {
 155           
 156           #ifdef PEGASUS_ENABLE_COMPRESSED_REPOSITORY
 157           
 158               Uint32 fileSize;
 159           
 160               if (!FileSystem::getFileSize(path, fileSize))
 161                   throw CannotOpenFile(path);
 162           
 163               gzFile fp = gzopen(path.getCString(), "rb");
 164           
 165               if (fp == NULL)
 166                   throw CannotOpenFile(path);
 167           
 168               data.reserveCapacity(fileSize);
 169 kumpf 1.1     char buffer[4096];
 170               int n;
 171           
 172               while ((n = gzread(fp, buffer, sizeof(buffer))) > 0)
 173                   data.append(buffer, n);
 174           
 175               gzclose(fp);
 176           
 177           #else
 178           
 179               FileSystem::loadFileToMemory(data, path);
 180           
 181           #endif /* PEGASUS_ENABLE_COMPRESSED_REPOSITORY */
 182           }
 183           
 184           ////////////////////////////////////////////////////////////////////////////////
 185           //
 186           // _LoadObject()
 187           //
 188           //      Loads objects (classes and qualifiers) from disk to
 189           //      memory objects.
 190 kumpf 1.1 //
 191           ////////////////////////////////////////////////////////////////////////////////
 192           
 193           template<class Object>
 194           void _LoadObject(
 195               const String& path,
 196               Object& object,
 197               ObjectStreamer* streamer)
 198           {
 199               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::_LoadObject");
 200           
 201               // Get the real path of the file:
 202           
 203               String realPath;
 204           
 205               if (!FileSystem::existsNoCase(path, realPath))
 206               {
 207                   PEG_TRACE_STRING(TRC_REPOSITORY, Tracer::LEVEL1,
 208                       path + " does not exist.");
 209                   PEG_METHOD_EXIT();
 210                   throw CannotOpenFile(path);
 211 kumpf 1.1     }
 212           
 213               PEG_TRACE_STRING(TRC_REPOSITORY, Tracer::LEVEL4, "realpath = " + realPath);
 214           
 215               // Load file into memory:
 216           
 217               Buffer data;
 218           
 219               _LoadFileToMemory(data, realPath);
 220           
 221               streamer->decode(data, 0, object);
 222           
 223               PEG_METHOD_EXIT();
 224           }
 225           
 226           ////////////////////////////////////////////////////////////////////////////////
 227           //
 228           // _SaveObject()
 229           //
 230           //      Saves objects (classes and qualifiers) from memory to
 231           //      disk files.
 232 kumpf 1.1 //
 233           ////////////////////////////////////////////////////////////////////////////////
 234           
 235           static void _SaveObject(
 236               const String& path,
 237               Buffer& objectXml,
 238               ObjectStreamer* streamer)
 239           {
 240               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::_SaveObject");
 241           
 242           #ifdef PEGASUS_ENABLE_COMPRESSED_REPOSITORY
 243               if (_compressMode)            // PEP214
 244               {
 245                   PEGASUS_STD(ostringstream) os;
 246                   streamer->write(os, objectXml);
 247                   string str = os.str();
 248           
 249                   gzFile fp = gzopen(path.getCString(), "wb");
 250           
 251                   if (fp == NULL)
 252                     throw CannotOpenFile(path);
 253 kumpf 1.1 
 254                   const char* ptr = str.data();
 255                   size_t rem = str.size();
 256                   int n;
 257           
 258                   while (rem > 0 && (n = gzwrite(fp, (char*)ptr, rem)) > 0)
 259                   {
 260                       ptr += n;
 261                       rem -= n;
 262                   }
 263           
 264                   gzclose(fp);
 265               }
 266               else
 267           #endif /* PEGASUS_ENABLE_COMPRESSED_REPOSITORY */
 268               {
 269                   PEGASUS_STD(ofstream) os(path.getCString() PEGASUS_IOS_BINARY);
 270           
 271                   if (!os)
 272                   {
 273                       PEG_METHOD_EXIT();
 274 kumpf 1.1             throw CannotOpenFile(path);
 275                   }
 276           
 277                   streamer->write(os, objectXml);
 278               }
 279               PEG_METHOD_EXIT();
 280           }
 281           
 282           ////////////////////////////////////////////////////////////////////////////////
 283           //
 284           // _beginInstanceTransaction()
 285           //
 286           //      Creates rollback files to allow an incomplete transaction to be voided.
 287           //
 288           ////////////////////////////////////////////////////////////////////////////////
 289           
 290           static void _beginInstanceTransaction(
 291               const String& indexFilePath,
 292               const String& dataFilePath)
 293           {
 294               PEG_METHOD_ENTER(TRC_REPOSITORY, "_beginInstanceTransaction");
 295 kumpf 1.1 
 296               //
 297               // Begin the transaction (an incomplete transaction will cause
 298               // a rollback the next time an instance-oriented routine is invoked).
 299               //
 300           
 301               if (!InstanceIndexFile::beginTransaction(indexFilePath))
 302               {
 303                   PEG_METHOD_EXIT();
 304                   throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
 305                       MessageLoaderParms("Repository.CIMRepository.BEGIN_FAILED",
 306                           "begin failed"));
 307               }
 308           
 309               if (!InstanceDataFile::beginTransaction(dataFilePath))
 310               {
 311                   PEG_METHOD_EXIT();
 312                   throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
 313                       MessageLoaderParms("Repository.CIMRepository.BEGIN_FAILED",
 314                           "begin failed"));
 315               }
 316 kumpf 1.1 
 317               PEG_METHOD_EXIT();
 318           }
 319           
 320           ////////////////////////////////////////////////////////////////////////////////
 321           //
 322           // _commitInstanceTransaction()
 323           //
 324           //      Removes the rollback files to complete the transaction.
 325           //
 326           ////////////////////////////////////////////////////////////////////////////////
 327           
 328           static void _commitInstanceTransaction(
 329               const String& indexFilePath,
 330               const String& dataFilePath)
 331           {
 332               PEG_METHOD_ENTER(TRC_REPOSITORY, "_commitInstanceTransaction");
 333           
 334               //
 335               // Commit the transaction by removing the rollback files.
 336               //
 337 kumpf 1.1 
 338               if (!InstanceIndexFile::commitTransaction(indexFilePath))
 339               {
 340                   PEG_METHOD_EXIT();
 341                   throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
 342                       MessageLoaderParms("Repository.CIMRepository.COMMIT_FAILED",
 343                           "commit failed"));
 344               }
 345           
 346               if (!InstanceDataFile::commitTransaction(dataFilePath))
 347               {
 348                   PEG_METHOD_EXIT();
 349                   throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
 350                       MessageLoaderParms("Repository.CIMRepository.COMMIT_FAILED",
 351                           "commit failed"));
 352               }
 353           
 354               PEG_METHOD_EXIT();
 355           }
 356           
 357           ////////////////////////////////////////////////////////////////////////////////
 358 kumpf 1.1 //
 359           // _rollbackInstanceTransaction()
 360           //
 361           //      Restores instance index and data files to void an incomplete operation.
 362           //      If there are no rollback files, this method has no effect.
 363           //
 364           ////////////////////////////////////////////////////////////////////////////////
 365           
 366           static String _dirName(const String& path)
 367           {
 368               Uint32 n = path.size();
 369           
 370               for (Uint32 i = n; i != 0; )
 371               {
 372                   if (path[--i] == '/')
 373                       return path.subString(0, i);
 374               }
 375           
 376               return String(".");
 377           }
 378           
 379 kumpf 1.1 static void _rollbackInstanceTransaction(
 380               const String& indexFilePath,
 381               const String& dataFilePath)
 382           {
 383               PEG_METHOD_ENTER(TRC_REPOSITORY, "_rollbackInstanceTransaction");
 384           
 385               // Avoid rollback logic if directory has no .rollback files.
 386           
 387               String path = _dirName(indexFilePath);
 388               Array<String> rollbackFiles;
 389           
 390               if (FileSystem::glob(path, "*.rollback", rollbackFiles))
 391               {
 392                   if (rollbackFiles.size() == 0)
 393                       return;
 394               }
 395           
 396               // Proceed to rollback logic.
 397           
 398               if (!InstanceIndexFile::rollbackTransaction(indexFilePath))
 399               {
 400 kumpf 1.1         PEG_METHOD_EXIT();
 401                   throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
 402                       MessageLoaderParms("Repository.CIMRepository.ROLLBACK_FAILED",
 403                           "rollback failed"));
 404               }
 405           
 406               if (!InstanceDataFile::rollbackTransaction(dataFilePath))
 407               {
 408                   PEG_METHOD_EXIT();
 409                   throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
 410                       MessageLoaderParms(
 411                           "Repository.CIMRepository.ROLLBACK_FAILED",
 412                           "rollback failed"));
 413               }
 414           
 415               PEG_METHOD_EXIT();
 416           }
 417           
 418           ////////////////////////////////////////////////////////////////////////////////
 419           //
 420           // InstanceTransactionHandler
 421 kumpf 1.1 //
 422           //      This class is used to manage a repository instance transaction.  The
 423           //      transaction is started when the class is instantiated, committed when
 424           //      the complete() method is called, and rolled back if the destructor is
 425           //      called without a prior call to complete().
 426           //
 427           //      The appropriate repository write locks must be owned while an
 428           //      InstanceTransactionHandler instance exists.
 429           //
 430           ////////////////////////////////////////////////////////////////////////////////
 431           
 432           class InstanceTransactionHandler
 433           {
 434           public:
 435               InstanceTransactionHandler(
 436                   const String& indexFilePath,
 437                   const String& dataFilePath)
 438               : _indexFilePath(indexFilePath),
 439                 _dataFilePath(dataFilePath),
 440                 _isComplete(false)
 441               {
 442 kumpf 1.1         _rollbackInstanceTransaction(_indexFilePath, _dataFilePath);
 443                   _beginInstanceTransaction(_indexFilePath, _dataFilePath);
 444               }
 445           
 446               ~InstanceTransactionHandler()
 447               {
 448                   if (!_isComplete)
 449                   {
 450                       _rollbackInstanceTransaction(_indexFilePath, _dataFilePath);
 451                   }
 452               }
 453           
 454               void complete()
 455               {
 456                   _commitInstanceTransaction(_indexFilePath, _dataFilePath);
 457                   _isComplete = true;
 458               }
 459           
 460           private:
 461               String _indexFilePath;
 462               String _dataFilePath;
 463 kumpf 1.1     Boolean _isComplete;
 464           };
 465           
 466           
 467           ////////////////////////////////////////////////////////////////////////////////
 468           //
 469           // FileBasedStore
 470           //
 471           ////////////////////////////////////////////////////////////////////////////////
 472           
 473           FileBasedStore::FileBasedStore(
 474               const String& repositoryPath,
 475               ObjectStreamer* streamer,
 476               Boolean compressMode)
 477               : _repositoryPath(repositoryPath),
 478                 _streamer(streamer),
 479                 _compressMode(compressMode)
 480           {
 481               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::FileBasedStore");
 482           
 483               // Create the repository directory if it does not already exist.
 484 kumpf 1.1 
 485               if (!FileSystem::isDirectory(_repositoryPath))
 486               {
 487                   if (!FileSystem::makeDirectory(_repositoryPath))
 488                   {
 489                       PEG_METHOD_EXIT();
 490                       throw CannotCreateDirectory(_repositoryPath);
 491                   }
 492               }
 493           
 494               _rollbackIncompleteTransactions();
 495           
 496               PEG_METHOD_EXIT();
 497           }
 498           
 499           FileBasedStore::~FileBasedStore()
 500           {
 501               AssocClassTable::removeCaches();
 502           }
 503           
 504           ////////////////////////////////////////////////////////////////////////////////
 505 kumpf 1.1 //
 506           // FileBasedStore::_rollbackIncompleteTransactions()
 507           //
 508           //      Searches for incomplete instance transactions for all classes in all
 509           //      namespaces.  Restores instance index and data files to void an
 510           //      incomplete operation.  If no incomplete instance transactions are
 511           //      outstanding, this method has no effect.
 512           //
 513           ////////////////////////////////////////////////////////////////////////////////
 514           
 515           static Boolean _containsNoCase(const Array<String>& array, const String& str)
 516           {
 517               for (Uint32 i = 0; i < array.size(); i++)
 518               {
 519                   if (String::equalNoCase(array[i], str))
 520                       return true;
 521               }
 522           
 523               return false;
 524           }
 525           
 526 kumpf 1.1 void FileBasedStore::_rollbackIncompleteTransactions()
 527           {
 528               PEG_METHOD_ENTER(TRC_REPOSITORY,
 529                   "FileBasedStore::_rollbackIncompleteTransactions");
 530           
 531               for (Dir dir(_repositoryPath); dir.more(); dir.next())
 532               {
 533                   String nameSpaceDirName = dir.getName();
 534                   if (nameSpaceDirName == ".." || nameSpaceDirName == ".")
 535                   {
 536                       continue;
 537                   }
 538           
 539                   String instanceDirPath =
 540                       _repositoryPath + "/" + nameSpaceDirName + _INSTANCES_SUFFIX;
 541           
 542                   // Form a list of .rollback files.
 543           
 544                   Array<String> rollbackFiles;
 545                   FileSystem::glob(instanceDirPath, "*.rollback", rollbackFiles);
 546           
 547 kumpf 1.1         // Perform a rollback operation for each class for which a rollback
 548                   // file was found.  A rollback may be performed twice for the same
 549                   // class if index and instance rollback files exist, but that will
 550                   // not cause a problem.
 551           
 552                   for (Uint32 i = 0; i < rollbackFiles.size(); i++)
 553                   {
 554                       // Parse the class name out of the file name.  (We know the
 555                       // file name contains a '.', since it matched the pattern above.)
 556                       String className =
 557                           rollbackFiles[i].subString(0, rollbackFiles[i].find('.'));
 558           
 559                       _rollbackInstanceTransaction(
 560                           instanceDirPath + "/" + className + ".idx",
 561                           instanceDirPath + "/" + className + ".instances");
 562                   }
 563               }
 564           
 565               PEG_METHOD_EXIT();
 566           }
 567           
 568 kumpf 1.1 // This function needs to be called from within a transaction scope for
 569           // proper error handling in compacting index and data files.
 570           static void _CompactInstanceRepository(
 571               const String& indexFilePath,
 572               const String& dataFilePath)
 573           {
 574               PEG_METHOD_ENTER(TRC_REPOSITORY,
 575                   "FileBasedStore::_CompactInstanceRepository");
 576           
 577               //
 578               // Compact the data file first:
 579               //
 580           
 581               Array<Uint32> freeFlags;
 582               Array<Uint32> indices;
 583               Array<Uint32> sizes;
 584               Array<CIMObjectPath> instanceNames;
 585           
 586               if (!InstanceIndexFile::enumerateEntries(
 587                       indexFilePath, freeFlags, indices, sizes, instanceNames, true))
 588               {
 589 kumpf 1.1         PEG_METHOD_EXIT();
 590                   throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
 591                       MessageLoaderParms(
 592                           "Repository.CIMRepository.INDEX_ENUM_ENTRIES_FAILED",
 593                           "Failed to obtain the entries from the Repository Instance"
 594                           " Index file."));
 595               }
 596           
 597               if (!InstanceDataFile::compact(dataFilePath, freeFlags, indices, sizes))
 598               {
 599                   PEG_METHOD_EXIT();
 600                   throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
 601                       MessageLoaderParms(
 602                           "Repository.CIMRepository.COMPACT_FAILED",
 603                           "Failed to compact the Repository Instance Data file."));
 604               }
 605           
 606               //
 607               // Now compact the index file:
 608               //
 609           
 610 kumpf 1.1     if (!InstanceIndexFile::compact(indexFilePath))
 611               {
 612                   PEG_METHOD_EXIT();
 613                   throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
 614                       MessageLoaderParms(
 615                           "Repository.CIMRepository.INDEX_COMPACT_FAILED",
 616                           "Failed to compact the Repository Instance Index file."));
 617               }
 618           
 619               PEG_METHOD_EXIT();
 620           }
 621           
 622           //----------------------------------------------------------------------
 623           //
 624           // _getNameSpaceDirPath()
 625           //
 626           //      returns the path of a namespace directory.
 627           //
 628           //----------------------------------------------------------------------
 629           
 630           String FileBasedStore::_getNameSpaceDirPath(
 631 kumpf 1.1     const CIMNamespaceName& nameSpace) const
 632           {
 633               String path;
 634               Boolean found = _nameSpacePathTable.lookup(nameSpace.getString(), path);
 635               PEGASUS_ASSERT(found);
 636               return path;
 637           }
 638           
 639           //----------------------------------------------------------------------
 640           //
 641           // _getQualifierFilePath()
 642           //
 643           //      returns the path of the qualifier file.
 644           //
 645           //----------------------------------------------------------------------
 646           
 647           String FileBasedStore::_getQualifierFilePath(
 648               const CIMNamespaceName& nameSpace,
 649               const CIMName& qualifierName) const
 650           {
 651               String tmp = _getNameSpaceDirPath(nameSpace);
 652 kumpf 1.1     tmp.append(_QUALIFIERS_SUFFIX);
 653               tmp.append('/');
 654               tmp.append(_escapeUtf8FileNameCharacters(qualifierName.getString()));
 655               return tmp;
 656           }
 657           
 658           //----------------------------------------------------------------------
 659           //
 660           // _getClassFilePath()
 661           //
 662           //      returns the path of the class file.
 663           //
 664           //----------------------------------------------------------------------
 665           
 666           String FileBasedStore::_getClassFilePath(
 667               const CIMNamespaceName& nameSpace,
 668               const CIMName& className,
 669               const CIMName& superClassName) const
 670           {
 671               String tmp = _getNameSpaceDirPath(nameSpace);
 672               tmp.append(_CLASSES_SUFFIX);
 673 kumpf 1.1     tmp.append('/');
 674               tmp.append(_escapeUtf8FileNameCharacters(className.getString()));
 675           
 676               if (superClassName.isNull())
 677               {
 678                   tmp.append(".#");
 679               }
 680               else
 681               {
 682                   tmp.append('.');
 683                   tmp.append(_escapeUtf8FileNameCharacters(superClassName.getString()));
 684               }
 685           
 686               return tmp;
 687           }
 688           
 689           //----------------------------------------------------------------------
 690           //
 691           // _getInstanceIndexFilePath()
 692           //
 693           //      returns the path of the instance index file.
 694 kumpf 1.1 //
 695           //----------------------------------------------------------------------
 696           
 697           String FileBasedStore::_getInstanceIndexFilePath(
 698               const CIMNamespaceName& nameSpace,
 699               const CIMName& className) const
 700           {
 701               String tmp = _getNameSpaceDirPath(nameSpace);
 702               tmp.append(_INSTANCES_SUFFIX);
 703               tmp.append('/');
 704               tmp.append(_escapeUtf8FileNameCharacters(className.getString()));
 705               tmp.append(".idx");
 706               return tmp;
 707           }
 708           
 709           //----------------------------------------------------------------------
 710           //
 711           // _getInstanceDataFilePath()
 712           //
 713           //      returns the path of the instance file.
 714           //
 715 kumpf 1.1 //----------------------------------------------------------------------
 716           
 717           String FileBasedStore::_getInstanceDataFilePath(
 718               const CIMNamespaceName& nameSpace,
 719               const CIMName& className) const
 720           {
 721               String tmp = _getNameSpaceDirPath(nameSpace);
 722               tmp.append(_INSTANCES_SUFFIX);
 723               tmp.append('/');
 724               tmp.append(_escapeUtf8FileNameCharacters(className.getString()));
 725               tmp.append(".instances");
 726               return tmp;
 727           }
 728           
 729           //----------------------------------------------------------------------
 730           //
 731           // _getAssocClassPath()
 732           //
 733           //      returns the path of the class association file.
 734           //
 735           //----------------------------------------------------------------------
 736 kumpf 1.1 
 737           String FileBasedStore::_getAssocClassPath(
 738               const CIMNamespaceName& nameSpace) const
 739           {
 740               String tmp = _getNameSpaceDirPath(nameSpace);
 741               tmp.append(_CLASSES_SUFFIX);
 742               tmp.append(_ASSOCIATIONS_SUFFIX);
 743               return tmp;
 744           }
 745           
 746           //----------------------------------------------------------------------
 747           //
 748           // _getAssocInstPath()
 749           //
 750           //      returns the path of the instance association file.
 751           //
 752           //----------------------------------------------------------------------
 753           
 754           String FileBasedStore::_getAssocInstPath(
 755               const CIMNamespaceName& nameSpace) const
 756           {
 757 kumpf 1.1     String tmp = _getNameSpaceDirPath(nameSpace);
 758               tmp.append(_INSTANCES_SUFFIX);
 759               tmp.append(_ASSOCIATIONS_SUFFIX);
 760               return tmp;
 761           }
 762           
 763           Boolean FileBasedStore::_loadInstance(
 764               const String& path,
 765               CIMInstance& object,
 766               Uint32 index,
 767               Uint32 size)
 768           {
 769               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::_loadInstance");
 770           
 771               //
 772               // Load instance (in XML) from instance file into memory:
 773               //
 774           
 775               Buffer data;
 776           
 777               if (!InstanceDataFile::loadInstance(path, index, size, data))
 778 kumpf 1.1     {
 779                   PEG_METHOD_EXIT();
 780                   return false;
 781               }
 782           
 783               //
 784               // Convert XML into an actual object:
 785               //
 786           
 787               _streamer->decode(data, 0, object);
 788           
 789               PEG_METHOD_EXIT();
 790               return true;
 791           }
 792           
 793           Boolean FileBasedStore::_loadAllInstances(
 794               const CIMNamespaceName& nameSpace,
 795               const CIMName& className,
 796               Array<CIMInstance>& namedInstances)
 797           {
 798               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::_loadAllInstances");
 799 kumpf 1.1 
 800               Array<CIMObjectPath> instanceNames;
 801               Buffer data;
 802               Array<Uint32> indices;
 803               Array<Uint32> sizes;
 804           
 805               //
 806               // Form the names of the instance index and data files
 807               //
 808           
 809               String indexFilePath = _getInstanceIndexFilePath(nameSpace, className);
 810               String dataFilePath = _getInstanceDataFilePath(nameSpace, className);
 811           
 812               //
 813               // Enumerate the index file:
 814               //
 815           
 816               Array<Uint32> freeFlags;
 817           
 818               if (!InstanceIndexFile::enumerateEntries(
 819                       indexFilePath, freeFlags, indices, sizes, instanceNames, true))
 820 kumpf 1.1     {
 821                   PEG_METHOD_EXIT();
 822                   return false;
 823               }
 824           
 825               //
 826               // Form the array of instances result:
 827               //
 828           
 829               if (instanceNames.size() > 0)
 830               {
 831                   //
 832                   // Load all instances from the data file:
 833                   //
 834           
 835                   if (!InstanceDataFile::loadAllInstances(dataFilePath, data))
 836                   {
 837                       PEG_METHOD_EXIT();
 838                       return false;
 839                   }
 840           
 841 kumpf 1.1         //
 842                   // for each instance loaded, call XML parser to parse the XML
 843                   // data and create a CIMInstance object.
 844                   //
 845           
 846                   CIMInstance tmpInstance;
 847           
 848                   char* buffer = (char*)data.getData();
 849           
 850                   for (Uint32 i = 0; i < instanceNames.size(); i++)
 851                   {
 852                       if (!freeFlags[i])
 853                       {
 854                           Uint32 pos= (Uint32)((&(buffer[indices[i]]))-buffer);
 855                           _streamer->decode(data, pos, tmpInstance);
 856           
 857                           tmpInstance.setPath(instanceNames[i]);
 858           
 859                           namedInstances.append(tmpInstance);
 860                       }
 861                   }
 862 kumpf 1.1     }
 863           
 864               PEG_METHOD_EXIT();
 865               return true;
 866           }
 867           
 868           Array<NamespaceDefinition> FileBasedStore::enumerateNameSpaces()
 869           {
 870               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::enumerateNameSpaces");
 871           
 872               Array<NamespaceDefinition> nameSpaces;
 873           
 874               for (Dir dir(_repositoryPath); dir.more(); dir.next())
 875               {
 876                   String nameSpaceDirName = dir.getName();
 877                   if (nameSpaceDirName == ".." || nameSpaceDirName == ".")
 878                   {
 879                       continue;
 880                   }
 881           
 882                   String nameSpacePath = _repositoryPath + "/" + nameSpaceDirName;
 883 kumpf 1.1 
 884                   if (!FileSystem::isDirectory(nameSpacePath + _CLASSES_SUFFIX) ||
 885                       !FileSystem::isDirectory(nameSpacePath + _INSTANCES_SUFFIX) ||
 886                       !FileSystem::isDirectory(nameSpacePath + _QUALIFIERS_SUFFIX))
 887                   {
 888                       PEG_TRACE_STRING(TRC_REPOSITORY, Tracer::LEVEL2,
 889                           "Namespace: " + nameSpaceDirName +
 890                               " ignored -- subdirectories are not correctly formed");
 891                       continue;
 892                   }
 893           
 894                   NamespaceDefinition nsdef(_dirNameToNamespaceName(nameSpaceDirName));
 895           
 896                   Boolean skipThisNamespace = false;
 897           
 898                   for (Dir subdir(nameSpacePath); subdir.more(); subdir.next())
 899                   {
 900                       String nameSpaceSubDirName = subdir.getName();
 901                       if (nameSpaceSubDirName == ".." || nameSpaceSubDirName == ".")
 902                       {
 903                           continue;
 904 kumpf 1.1             }
 905           
 906                       String tmp = nameSpaceSubDirName;
 907                       tmp.toLower();
 908           
 909                       if (tmp[0] == 's')
 910                       {
 911                           if ((tmp[1]=='w' || tmp[1]=='r') &&
 912                               (tmp[2]=='f' || tmp[2]=='s'))
 913                           {
 914                               nsdef.shareable = tmp[2]=='s';
 915                               nsdef.updatesAllowed = tmp[1]=='w';
 916                               String parent = nameSpaceSubDirName.subString(3);
 917                               if (parent.size())
 918                               {
 919                                   nsdef.parentNameSpace = _dirNameToNamespaceName(parent);
 920                               }
 921           
 922           #ifdef PEGASUS_ENABLE_REMOTE_CMPI
 923                               nsdef.shared = true;
 924           #endif
 925 kumpf 1.1                 }
 926                           else
 927                           {
 928                               PEG_TRACE_STRING(TRC_REPOSITORY, Tracer::LEVEL2,
 929                                   "Namespace " + nameSpaceDirName +
 930                                   " ignored - using incorrect parent namespace "
 931                                       "specification: " +
 932                                   nameSpaceSubDirName);
 933                               skipThisNamespace = true;
 934                           }
 935           #ifndef PEGASUS_ENABLE_REMOTE_CMPI
 936                           break;
 937           #endif
 938                       }
 939           #ifdef PEGASUS_ENABLE_REMOTE_CMPI
 940                       else if (tmp[0] == 'r')
 941                       {
 942                           nsdef.remote = true;
 943                           nsdef.remoteId = tmp.subString(1, 2);
 944           
 945                           Uint32 pos = nameSpaceSubDirName.find('@');
 946 kumpf 1.1                 if (pos != PEG_NOT_FOUND)
 947                           {
 948                               nsdef.remoteHost = nameSpaceSubDirName.subString(3, pos-3);
 949                               nsdef.remotePort = nameSpaceSubDirName.subString(pos+1);
 950                           }
 951                           else
 952                           {
 953                               nsdef.remoteHost = nameSpaceSubDirName.subString(3);
 954                           }
 955           
 956                           nsdef.remoteInfo = nameSpaceSubDirName;
 957                           PEG_TRACE_STRING(TRC_REPOSITORY, Tracer::LEVEL4,
 958                               "Remote namespace: " + nameSpaceDirName + " >" +
 959                                   nameSpaceSubDirName);
 960                       }
 961           #endif
 962                   }
 963           
 964                   if (!skipThisNamespace)
 965                   {
 966                       _nameSpacePathTable.insert(
 967 kumpf 1.1                 nsdef.name.getString(),
 968                           _repositoryPath + "/" + nameSpaceDirName);
 969                       nameSpaces.append(nsdef);
 970                   }
 971               }
 972           
 973               PEG_METHOD_EXIT();
 974               return nameSpaces;
 975           }
 976           
 977           void FileBasedStore::createNameSpace(
 978               const CIMNamespaceName& nameSpace,
 979               Boolean shareable,
 980               Boolean updatesAllowed,
 981               const String& parentNameSpace)
 982           {
 983               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::createNameSpace");
 984           
 985           #ifndef PEGASUS_SUPPORT_UTF8_FILENAME
 986               // Do not allow file names to contain characters outside of 7-bit ASCII.
 987               String nameSpaceNameString = nameSpace.getString();
 988 kumpf 1.1     Uint32 len = nameSpaceNameString.size();
 989               for (Uint32 i = 0; i < len; ++i)
 990               {
 991                   if ((Uint16)nameSpaceNameString[i] > 0x007F)
 992                   {
 993                       PEG_METHOD_EXIT();
 994                       throw PEGASUS_CIM_EXCEPTION(
 995                           CIM_ERR_INVALID_PARAMETER, nameSpaceNameString);
 996                   }
 997               }
 998           #endif
 999           
1000               // Attempt to create all the namespace directories:
1001           
1002               String nameSpacePath =
1003                   _repositoryPath + "/" + _namespaceNameToDirName(nameSpace);
1004           
1005               if (!FileSystem::makeDirectory(nameSpacePath))
1006               {
1007                   throw CannotCreateDirectory(nameSpacePath);
1008               }
1009 kumpf 1.1 
1010               String classesPath = nameSpacePath + _CLASSES_SUFFIX;
1011               String instancesPath = nameSpacePath + _INSTANCES_SUFFIX;
1012               String qualifiersPath = nameSpacePath + _QUALIFIERS_SUFFIX;
1013           
1014               if (!FileSystem::makeDirectory(classesPath))
1015               {
1016                   throw CannotCreateDirectory(classesPath);
1017               }
1018           
1019               if (!FileSystem::makeDirectory(instancesPath))
1020               {
1021                   throw CannotCreateDirectory(instancesPath);
1022               }
1023           
1024               if (!FileSystem::makeDirectory(qualifiersPath))
1025               {
1026                   throw CannotCreateDirectory(qualifiersPath);
1027               }
1028           
1029               if (shareable || !updatesAllowed || parentNameSpace.size())
1030 kumpf 1.1     {
1031                   String path = nameSpacePath + "/S" + (updatesAllowed ? "W" : "R") +
1032                       (shareable ? "S" : "F");
1033                   if (parentNameSpace.size())
1034                   {
1035                       path.append(_namespaceNameToDirName(parentNameSpace));
1036                   }
1037           
1038                   if (!FileSystem::makeDirectory(path))
1039                   {
1040                       throw CannotCreateDirectory(path);
1041                   }
1042               }
1043           
1044               _nameSpacePathTable.insert(nameSpace.getString(), nameSpacePath);
1045           
1046               PEG_METHOD_EXIT();
1047           }
1048           
1049           void FileBasedStore::modifyNameSpace(
1050               const CIMNamespaceName& nameSpace,
1051 kumpf 1.1     Boolean shareable,
1052               Boolean updatesAllowed)
1053           {
1054               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::modifyNameSpace");
1055           
1056               String nameSpacePath = _getNameSpaceDirPath(nameSpace);
1057               String oldSpecialDirName;
1058           
1059               for (Dir subdir(nameSpacePath); subdir.more(); subdir.next())
1060               {
1061                   String dirName = subdir.getName();
1062           
1063                   if ((dirName[0] == 's') || (dirName[0] == 'S'))
1064                   {
1065                       oldSpecialDirName = dirName;
1066                       break;
1067                   }
1068               }
1069           
1070               String newSpecialDirName = oldSpecialDirName;
1071           
1072 kumpf 1.1     if (newSpecialDirName.size() == 0)
1073               {
1074                   newSpecialDirName = "SWF";
1075               }
1076           
1077               newSpecialDirName[0] = 'S';
1078               newSpecialDirName[1] = updatesAllowed ? 'W' : 'R';
1079               newSpecialDirName[2] = shareable ? 'S' : 'F';
1080           
1081               if (newSpecialDirName != oldSpecialDirName)
1082               {
1083                   if (oldSpecialDirName.size())
1084                   {
1085                       FileSystem::removeDirectoryHier(
1086                           nameSpacePath + "/" + oldSpecialDirName);
1087                   }
1088           
1089                   if (newSpecialDirName != "SWF")
1090                   {
1091                       String newPath = nameSpacePath + "/" + newSpecialDirName;
1092                       if (!FileSystem::makeDirectory(newPath))
1093 kumpf 1.1             {
1094                           PEG_METHOD_EXIT();
1095                           throw CannotCreateDirectory(newPath);
1096                       }
1097                   }
1098               }
1099           
1100               PEG_METHOD_EXIT();
1101           }
1102           
1103           void FileBasedStore::deleteNameSpace(const CIMNamespaceName& nameSpace)
1104           {
1105               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::deleteNameSpace");
1106           
1107               String nameSpacePath = _getNameSpaceDirPath(nameSpace);
1108           
1109               if (!FileSystem::removeDirectoryHier(nameSpacePath))
1110               {
1111                   PEG_METHOD_EXIT();
1112                   throw CannotRemoveDirectory(nameSpacePath);
1113               }
1114 kumpf 1.1 
1115               _nameSpacePathTable.remove(nameSpace.getString());
1116           
1117               PEG_METHOD_EXIT();
1118           }
1119           
1120           Boolean FileBasedStore::isNameSpaceEmpty(const CIMNamespaceName& nameSpace)
1121           {
1122               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::isNameSpaceEmpty");
1123           
1124               String nameSpacePath = _getNameSpaceDirPath(nameSpace);
1125           
1126               for (Dir dir(nameSpacePath); dir.more(); dir.next())
1127               {
1128                   const char* name = dir.getName();
1129           
1130                   if (strcmp(name, ".") != 0 &&
1131                       strcmp(name, "..") != 0 &&
1132                       System::strcasecmp(name, _CLASSES_DIR) != 0 &&
1133                       System::strcasecmp(name, _INSTANCES_DIR) != 0 &&
1134                       System::strcasecmp(name, _QUALIFIERS_DIR) != 0)
1135 kumpf 1.1         {
1136                       // ATTN: Is it assumed that dependent namespaces are empty?
1137                       return true;
1138                   }
1139               }
1140           
1141               String classesPath = nameSpacePath + _CLASSES_SUFFIX;
1142               String instancesPath = nameSpacePath + _INSTANCES_SUFFIX;
1143               String qualifiersPath = nameSpacePath + _QUALIFIERS_SUFFIX;
1144           
1145               PEG_METHOD_EXIT();
1146               return
1147                   FileSystem::isDirectoryEmpty(classesPath) &&
1148                   FileSystem::isDirectoryEmpty(instancesPath) &&
1149                   FileSystem::isDirectoryEmpty(qualifiersPath);
1150           }
1151           
1152           Array<CIMQualifierDecl> FileBasedStore::enumerateQualifiers(
1153               const CIMNamespaceName& nameSpace)
1154           {
1155               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::enumerateQualifiers");
1156 kumpf 1.1 
1157               String qualifiersRoot =
1158                   _getNameSpaceDirPath(nameSpace) + _QUALIFIERS_SUFFIX;
1159           
1160               Array<String> qualifierNames;
1161           
1162               if (!FileSystem::getDirectoryContents(qualifiersRoot, qualifierNames))
1163               {
1164                   PEG_METHOD_EXIT();
1165                   String str ="enumerateQualifiers()";
1166                   throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1167                       MessageLoaderParms("Repository.CIMRepository.INTERNAL_ERROR",
1168                           "$0: internal error",
1169                           str));
1170               }
1171           
1172               Array<CIMQualifierDecl> qualifiers;
1173           
1174               for (Uint32 i = 0; i < qualifierNames.size(); i++)
1175               {
1176                   CIMQualifierDecl qualifier = getQualifier(
1177 kumpf 1.1             nameSpace, _unescapeUtf8FileNameCharacters(qualifierNames[i]));
1178                   qualifiers.append(qualifier);
1179               }
1180           
1181               PEG_METHOD_EXIT();
1182               return qualifiers;
1183           }
1184           
1185           CIMQualifierDecl FileBasedStore::getQualifier(
1186               const CIMNamespaceName& nameSpace,
1187               const CIMName& qualifierName)
1188           {
1189               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::getQualifier");
1190           
1191               CIMQualifierDecl qualifierDecl;
1192           
1193               //
1194               // Get path of qualifier file:
1195               //
1196           
1197               String qualifierFilePath = _getQualifierFilePath(nameSpace, qualifierName);
1198 kumpf 1.1 
1199               try
1200               {
1201                   _LoadObject(qualifierFilePath, qualifierDecl, _streamer);
1202               }
1203               catch (const CannotOpenFile&)
1204               {
1205                   // Qualifier not found
1206                   PEG_METHOD_EXIT();
1207                   return CIMQualifierDecl();
1208               }
1209           
1210               PEG_METHOD_EXIT();
1211               return qualifierDecl;
1212           }
1213           
1214           void FileBasedStore::setQualifier(
1215               const CIMNamespaceName& nameSpace,
1216               const CIMQualifierDecl& qualifierDecl)
1217           {
1218               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::setQualifier");
1219 kumpf 1.1 
1220               // -- Get path of qualifier file:
1221           
1222               String qualifierFilePath =
1223                   _getQualifierFilePath(nameSpace, qualifierDecl.getName());
1224           
1225               // -- If qualifier already exists, throw exception:
1226           
1227               if (FileSystem::existsNoCase(qualifierFilePath))
1228               {
1229                   PEG_METHOD_EXIT();
1230                   throw PEGASUS_CIM_EXCEPTION(
1231                       CIM_ERR_NOT_SUPPORTED, qualifierDecl.getName().getString());
1232               }
1233           
1234               // -- Save qualifier:
1235           
1236               Buffer qualifierDeclXml;
1237               _streamer->encode(qualifierDeclXml, qualifierDecl);
1238               _SaveObject(qualifierFilePath, qualifierDeclXml, _streamer);
1239           
1240 kumpf 1.1     PEG_METHOD_EXIT();
1241           }
1242           
1243           void FileBasedStore::deleteQualifier(
1244               const CIMNamespaceName& nameSpace,
1245               const CIMName& qualifierName)
1246           {
1247               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::deleteQualifier");
1248           
1249               // -- Get path of qualifier file:
1250           
1251               String qualifierFilePath = _getQualifierFilePath(nameSpace, qualifierName);
1252           
1253               // -- Delete qualifier:
1254           
1255               if (!FileSystem::removeFileNoCase(qualifierFilePath))
1256               {
1257                   PEG_METHOD_EXIT();
1258                   throw PEGASUS_CIM_EXCEPTION(
1259                       CIM_ERR_NOT_FOUND, qualifierName.getString());
1260               }
1261 kumpf 1.1 
1262               PEG_METHOD_EXIT();
1263           }
1264           
1265           Array<Pair<String, String> > FileBasedStore::enumerateClassNames(
1266               const CIMNamespaceName& nameSpace)
1267           {
1268               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::enumerateClassNames");
1269           
1270               Array<Pair<String, String> > classList;
1271           
1272               String classesPath = _getNameSpaceDirPath(nameSpace) + _CLASSES_SUFFIX;
1273           
1274               for (Dir dir(classesPath); dir.more(); dir.next())
1275               {
1276                   String fileName = dir.getName();
1277           
1278                   // Ignore the current and parent directories.
1279           
1280                   if (fileName == "." || fileName == "..")
1281                       continue;
1282 kumpf 1.1 
1283                   Uint32 dot = fileName.find('.');
1284           
1285                   // Ignore files without dots in them:
1286           
1287                   if (dot == PEG_NOT_FOUND)
1288                       continue;
1289           
1290                   String className =
1291                       _unescapeUtf8FileNameCharacters(fileName.subString(0, dot));
1292                   String superClassName =
1293                       _unescapeUtf8FileNameCharacters(fileName.subString(dot + 1));
1294           
1295                   if (superClassName == "#")
1296                       superClassName.clear();
1297           
1298                   classList.append(Pair<String, String>(className, superClassName));
1299               }
1300           
1301               PEG_METHOD_EXIT();
1302               return classList;
1303 kumpf 1.1 }
1304           
1305           CIMClass FileBasedStore::getClass(
1306               const CIMNamespaceName& nameSpace,
1307               const CIMName& className,
1308               const CIMName& superClassName)
1309           {
1310               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::getClass");
1311           
1312               String classFilePath =
1313                   _getClassFilePath(nameSpace, className, superClassName);
1314               CIMClass cimClass;
1315               _LoadObject(classFilePath, cimClass, _streamer);
1316           
1317               PEG_METHOD_EXIT();
1318               return cimClass;
1319           }
1320           
1321           void FileBasedStore::createClass(
1322               const CIMNamespaceName& nameSpace,
1323               const CIMClass& newClass)
1324 kumpf 1.1 {
1325               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::createClass");
1326           
1327           #ifndef PEGASUS_SUPPORT_UTF8_FILENAME
1328               // Do not allow file names to contain characters outside of 7-bit ASCII.
1329               String classNameString = newClass.getClassName().getString();
1330               Uint32 len = classNameString.size();
1331               for (Uint32 i = 0; i < len; ++i)
1332               {
1333                   if ((Uint16)classNameString[i] > 0x007F)
1334                   {
1335                       PEG_METHOD_EXIT();
1336                       throw PEGASUS_CIM_EXCEPTION(
1337                           CIM_ERR_INVALID_PARAMETER, classNameString);
1338                   }
1339               }
1340           #endif
1341           
1342               String classFilePath = _getClassFilePath(
1343                   nameSpace, newClass.getClassName(), newClass.getSuperClassName());
1344               Buffer classXml;
1345 kumpf 1.1     _streamer->encode(classXml, newClass);
1346               _SaveObject(classFilePath, classXml, _streamer);
1347           
1348               PEG_METHOD_EXIT();
1349           }
1350           
1351           void FileBasedStore::modifyClass(
1352               const CIMNamespaceName& nameSpace,
1353               const CIMClass& modifiedClass)
1354           {
1355               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::modifyClass");
1356           
1357               String classFilePath = _getClassFilePath(
1358                   nameSpace,
1359                   modifiedClass.getClassName(),
1360                   modifiedClass.getSuperClassName());
1361           
1362               //
1363               // Delete the old file containing the class:
1364               //
1365           
1366 kumpf 1.1     if (!FileSystem::removeFileNoCase(classFilePath))
1367               {
1368                   PEG_METHOD_EXIT();
1369                   // ATTN: Parameter should be file name, not method name.
1370                   String str = "FileBasedStore::modifyClass()";
1371                   throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1372                       MessageLoaderParms(
1373                           "Repository.CIMRepository.FAILED_TO_REMOVE_FILE",
1374                           "failed to remove file in $0", str));
1375               }
1376           
1377               //
1378               // Create new class file:
1379               //
1380           
1381               Buffer classXml;
1382               _streamer->encode(classXml, modifiedClass);
1383               _SaveObject(classFilePath, classXml, _streamer);
1384           
1385               PEG_METHOD_EXIT();
1386           }
1387 kumpf 1.1 
1388           void FileBasedStore::deleteClass(
1389               const CIMNamespaceName& nameSpace,
1390               const CIMName& className,
1391               const CIMName& superClassName)
1392           {
1393               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::deleteClass");
1394           
1395               // Remove class file
1396           
1397               String classFilePath =
1398                   _getClassFilePath(nameSpace, className, superClassName);
1399           
1400               if (!FileSystem::removeFileNoCase(classFilePath))
1401               {
1402                   PEG_METHOD_EXIT();
1403                   throw CannotRemoveFile(classFilePath);
1404               }
1405           
1406               PEG_METHOD_EXIT();
1407           }
1408 kumpf 1.1 
1409           Array<CIMObjectPath> FileBasedStore::enumerateInstanceNamesForClass(
1410               const CIMNamespaceName& nameSpace,
1411               const CIMName& className)
1412           {
1413               PEG_METHOD_ENTER(TRC_REPOSITORY,
1414                   "FileBasedStore::enumerateInstanceNamesForClass");
1415           
1416               //
1417               // Get instance names from the instance index file for the class:
1418               //
1419               Array<Uint32> indices;
1420               Array<Uint32> sizes;
1421           
1422               //
1423               // Form the names of the instance index and data files
1424               //
1425           
1426               String indexFilePath = _getInstanceIndexFilePath(nameSpace, className);
1427               String dataFilePath = _getInstanceDataFilePath(nameSpace, className);
1428           
1429 kumpf 1.1     //
1430               // Get all instances for the class:
1431               //
1432           
1433               Array<CIMObjectPath> instanceNames;
1434               Array<Uint32> freeFlags;
1435           
1436               if (!InstanceIndexFile::enumerateEntries(
1437                       indexFilePath, freeFlags, indices, sizes, instanceNames, false))
1438               {
1439                   PEG_METHOD_EXIT();
1440                   throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1441                       MessageLoaderParms(
1442                           "Repository.CIMRepository.FAILED_TO_LOAD_INSTANCE_NAMES",
1443                           "Failed to load instance names in class $0",
1444                           className.getString()));
1445               }
1446           
1447               PEG_METHOD_EXIT();
1448               return instanceNames;
1449           }
1450 kumpf 1.1 
1451           Array<CIMInstance> FileBasedStore::enumerateInstancesForClass(
1452               const CIMNamespaceName& nameSpace,
1453               const CIMName& className)
1454           {
1455               PEG_METHOD_ENTER(TRC_REPOSITORY,
1456                   "FileBasedStore::enumerateInstancesForClass");
1457           
1458               Array<CIMInstance> cimInstances;
1459           
1460               if (!_loadAllInstances(nameSpace, className, cimInstances))
1461               {
1462                   PEG_METHOD_EXIT();
1463                   throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1464                       MessageLoaderParms(
1465                           "Repository.CIMRepository.FAILED_TO_LOAD_INSTANCES",
1466                           "Failed to load instances in class $0",
1467                           className.getString()));
1468               }
1469           
1470               PEG_METHOD_EXIT();
1471 kumpf 1.1     return cimInstances;
1472           }
1473           
1474           CIMInstance FileBasedStore::getInstance(
1475               const CIMNamespaceName& nameSpace,
1476               const CIMObjectPath& instanceName)
1477           {
1478               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::getInstance");
1479           
1480               //
1481               // Get paths of index and data files:
1482               //
1483           
1484               String indexFilePath = _getInstanceIndexFilePath(
1485                   nameSpace, instanceName.getClassName());
1486           
1487               String dataFilePath = _getInstanceDataFilePath(
1488                   nameSpace, instanceName.getClassName());
1489           
1490               //
1491               // Get the index for this instance:
1492 kumpf 1.1     //
1493           
1494               Uint32 index;
1495               Uint32 size;
1496           
1497               if (!InstanceIndexFile::lookupEntry(
1498                       indexFilePath, instanceName, index, size))
1499               {
1500                   PEG_METHOD_EXIT();
1501                   throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, instanceName.toString());
1502               }
1503           
1504               //
1505               // Load the instance from file:
1506               //
1507           
1508               CIMInstance cimInstance;
1509           
1510               if (!_loadInstance(dataFilePath, cimInstance, index, size))
1511               {
1512                   PEG_METHOD_EXIT();
1513 kumpf 1.1         throw CannotOpenFile(dataFilePath);
1514               }
1515           
1516               PEG_METHOD_EXIT();
1517               return cimInstance;
1518           }
1519           
1520           void FileBasedStore::createInstance(
1521               const CIMNamespaceName& nameSpace,
1522               const CIMObjectPath& instanceName,
1523               const CIMInstance& cimInstance)
1524           {
1525               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::createInstance");
1526           
1527               //
1528               // Get paths to data and index files:
1529               //
1530           
1531               String indexFilePath = _getInstanceIndexFilePath(
1532                   nameSpace, cimInstance.getClassName());
1533           
1534 kumpf 1.1     String dataFilePath = _getInstanceDataFilePath(
1535                   nameSpace, cimInstance.getClassName());
1536           
1537               //
1538               // Perform the operation in a transaction scope to enable rollback on
1539               // failure.
1540               //
1541           
1542               InstanceTransactionHandler transaction(indexFilePath, dataFilePath);
1543           
1544               //
1545               // Save instance to file:
1546               //
1547           
1548               Uint32 index;
1549               Uint32 size;
1550           
1551               {
1552                   Buffer data;
1553                   _streamer->encode(data, cimInstance);
1554                   size = data.size();
1555 kumpf 1.1 
1556                   if (!InstanceDataFile::appendInstance(dataFilePath, data, index))
1557                   {
1558                       PEG_METHOD_EXIT();
1559                       throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1560                           MessageLoaderParms(
1561                               "Repository.CIMRepository.FAILED_TO_CREATE_INSTANCE",
1562                               "Failed to create instance: $0",
1563                               instanceName.toString()));
1564                   }
1565               }
1566           
1567               //
1568               // Create entry in index file:
1569               //
1570           
1571               if (!InstanceIndexFile::createEntry(
1572                       indexFilePath, instanceName, index, size))
1573               {
1574                   PEG_METHOD_EXIT();
1575                   throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1576 kumpf 1.1             MessageLoaderParms(
1577                           "Repository.CIMRepository.FAILED_TO_CREATE_INSTANCE",
1578                           "Failed to create instance: $0",
1579                           instanceName.toString()));
1580               }
1581           
1582               transaction.complete();
1583           
1584               PEG_METHOD_EXIT();
1585           }
1586           
1587           void FileBasedStore::modifyInstance(
1588               const CIMNamespaceName& nameSpace,
1589               const CIMObjectPath& instanceName,
1590               const CIMInstance& cimInstance)
1591           {
1592               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::modifyInstance");
1593           
1594               //
1595               // Get paths of index and data files:
1596               //
1597 kumpf 1.1 
1598               String indexFilePath = _getInstanceIndexFilePath(
1599                   nameSpace, cimInstance.getClassName());
1600           
1601               String dataFilePath = _getInstanceDataFilePath(
1602                   nameSpace, cimInstance.getClassName());
1603           
1604               //
1605               // Look up the specified instance
1606               //
1607           
1608               Uint32 oldSize;
1609               Uint32 oldIndex;
1610               Uint32 newSize;
1611               Uint32 newIndex;
1612           
1613               if (!InstanceIndexFile::lookupEntry(
1614                       indexFilePath, instanceName, oldIndex, oldSize))
1615               {
1616                   PEG_METHOD_EXIT();
1617                   throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, instanceName.toString());
1618 kumpf 1.1     }
1619           
1620               //
1621               // Perform the operation in a transaction scope to enable rollback on
1622               // failure.
1623               //
1624           
1625               InstanceTransactionHandler transaction(indexFilePath, dataFilePath);
1626           
1627               //
1628               // Modify the data file:
1629               //
1630           
1631               {
1632                   Buffer out;
1633                   _streamer->encode(out, cimInstance);
1634           
1635                   newSize = out.size();
1636           
1637                   if (!InstanceDataFile::appendInstance(dataFilePath, out, newIndex))
1638                   {
1639 kumpf 1.1             PEG_METHOD_EXIT();
1640                       throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1641                           MessageLoaderParms(
1642                               "Repository.CIMRepository.FAILED_TO_MODIFY_INSTANCE",
1643                               "Failed to modify instance $0",
1644                               instanceName.toString()));
1645                   }
1646               }
1647           
1648               //
1649               // Modify the index file:
1650               //
1651           
1652               Uint32 freeCount;
1653           
1654               if (!InstanceIndexFile::modifyEntry(indexFilePath, instanceName, newIndex,
1655                   newSize, freeCount))
1656               {
1657                   PEG_METHOD_EXIT();
1658                   throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1659                       MessageLoaderParms(
1660 kumpf 1.1                 "Repository.CIMRepository.FAILED_TO_MODIFY_INSTANCE",
1661                           "Failed to modify instance $0",
1662                           instanceName.toString()));
1663               }
1664           
1665               //
1666               // Compact the index and data files if the free count max was
1667               // reached.
1668               //
1669           
1670               if (freeCount >= _MAX_FREE_COUNT)
1671               {
1672                   _CompactInstanceRepository(indexFilePath, dataFilePath);
1673               }
1674           
1675               transaction.complete();
1676           
1677               PEG_METHOD_EXIT();
1678           }
1679           
1680           void FileBasedStore::deleteInstance(
1681 kumpf 1.1     const CIMNamespaceName& nameSpace,
1682               const CIMObjectPath& instanceName)
1683           {
1684               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::deleteInstance");
1685           
1686               //
1687               // Get paths of index and data files:
1688               //
1689           
1690               String indexFilePath = _getInstanceIndexFilePath(
1691                   nameSpace, instanceName.getClassName());
1692           
1693               String dataFilePath = _getInstanceDataFilePath(
1694                   nameSpace, instanceName.getClassName());
1695           
1696               //
1697               // Perform the operation in a transaction scope to enable rollback on
1698               // failure.
1699               //
1700           
1701               InstanceTransactionHandler transaction(indexFilePath, dataFilePath);
1702 kumpf 1.1 
1703               //
1704               // Lookup instance from the index file (raise error if not found).
1705               //
1706           
1707               Uint32 index;
1708               Uint32 size;
1709           
1710               if (!InstanceIndexFile::lookupEntry(
1711                       indexFilePath, instanceName, index, size))
1712               {
1713                   PEG_METHOD_EXIT();
1714                   throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, instanceName.toString());
1715               }
1716           
1717               //
1718               // Remove entry from index file.
1719               //
1720           
1721               Uint32 freeCount;
1722           
1723 kumpf 1.1     if (!InstanceIndexFile::deleteEntry(indexFilePath, instanceName, freeCount))
1724               {
1725                   PEG_METHOD_EXIT();
1726                   throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1727                       MessageLoaderParms(
1728                           "Repository.CIMRepository.FAILED_TO_DELETE_INSTANCE",
1729                           "Failed to delete instance: $0",
1730                           instanceName.toString()));
1731               }
1732           
1733               //
1734               // Compact the index and data files if the free count max was
1735               // reached.
1736               //
1737           
1738               if (freeCount >= _MAX_FREE_COUNT)
1739               {
1740                   _CompactInstanceRepository(indexFilePath, dataFilePath);
1741               }
1742           
1743               transaction.complete();
1744 kumpf 1.1 
1745               PEG_METHOD_EXIT();
1746           }
1747           
1748           void FileBasedStore::deleteAllInstances(
1749               const CIMNamespaceName& nameSpace,
1750               const CIMName& className)
1751           {
1752               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::deleteAllInstances");
1753           
1754               String indexFilePath =
1755                   _getInstanceIndexFilePath(nameSpace, className);
1756               String dataFilePath =
1757                   _getInstanceDataFilePath(nameSpace, className);
1758           
1759               FileSystem::removeFileNoCase(indexFilePath);
1760               FileSystem::removeFileNoCase(dataFilePath);
1761           
1762               PEG_METHOD_EXIT();
1763           }
1764           
1765 kumpf 1.1 Boolean FileBasedStore::instanceExists(
1766               const CIMNamespaceName& nameSpace,
1767               const CIMObjectPath& instanceName)
1768           {
1769               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::instanceExists");
1770           
1771               String path =
1772                   _getInstanceIndexFilePath(nameSpace, instanceName.getClassName());
1773           
1774               Uint32 index;
1775               Uint32 size;
1776               if (InstanceIndexFile::lookupEntry(path, instanceName, index, size))
1777               {
1778                   PEG_METHOD_EXIT();
1779                   return true;
1780               }
1781           
1782               PEG_METHOD_EXIT();
1783               return false;
1784           }
1785           
1786 kumpf 1.1 void FileBasedStore::addClassAssociations(
1787               const CIMNamespaceName& nameSpace,
1788               const Array<ClassAssociation>& classAssocEntries)
1789           {
1790               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::addClassAssociations");
1791           
1792               String assocFileName = _getAssocClassPath(nameSpace);
1793               PEGASUS_STD(ofstream) os;
1794           
1795               if (!OpenAppend(os, assocFileName))
1796               {
1797                   PEG_METHOD_EXIT();
1798                   throw CannotOpenFile(assocFileName);
1799               }
1800           
1801               for (Uint32 i = 0; i < classAssocEntries.size(); i++)
1802               {
1803                   AssocClassTable::append(
1804                       os,
1805                       assocFileName,
1806                       classAssocEntries[i].assocClassName,
1807 kumpf 1.1             classAssocEntries[i].fromClassName,
1808                       classAssocEntries[i].fromPropertyName,
1809                       classAssocEntries[i].toClassName,
1810                       classAssocEntries[i].toPropertyName);
1811               }
1812           
1813               PEG_METHOD_EXIT();
1814           }
1815           
1816           Boolean FileBasedStore::removeClassAssociation(
1817               const CIMNamespaceName& nameSpace,
1818               const CIMName& assocClassName)
1819           {
1820               PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::removeClassAssociation");
1821           
1822               String assocFileName = _getAssocClassPath(nameSpace);
1823           
1824               Boolean returnStatus =
1825                   AssocClassTable::deleteAssociation(assocFileName, assocClassName);
1826           
1827               PEG_METHOD_EXIT();
1828 kumpf 1.1     return returnStatus;
1829           }
1830           
1831           void FileBasedStore::getClassAssociatorNames(
1832               const CIMNamespaceName& nameSpace,
1833               const Array<CIMName>& classList,
1834               const Array<CIMName>& assocClassList,
1835               const Array<CIMName>& resultClassList,
1836               const String& role,
1837               const String& resultRole,
1838               Array<String>& associatorNames)
1839           {
1840               PEG_METHOD_ENTER(TRC_REPOSITORY,
1841                   "FileBasedStore::getClassAssociatorNames");
1842           
1843               String assocFileName = _getAssocClassPath(nameSpace);
1844           
1845 thilo.boehm 1.2     // ATTN: Return value is ignored
1846                     AssocClassTable::getAssociatorNames(
1847                         assocFileName,
1848                         classList,
1849                         assocClassList,
1850                         resultClassList,
1851                         role,
1852                         resultRole,
1853                         associatorNames);
1854 kumpf       1.1 
1855                     PEG_METHOD_EXIT();
1856                 }
1857                 
1858                 void FileBasedStore::getClassReferenceNames(
1859                     const CIMNamespaceName& nameSpace,
1860                     const Array<CIMName>& classList,
1861                     const Array<CIMName>& resultClassList,
1862                     const String& role,
1863                     Array<String>& referenceNames)
1864                 {
1865                     PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::getClassReferenceNames");
1866                 
1867                     String assocFileName = _getAssocClassPath(nameSpace);
1868                 
1869 thilo.boehm 1.2     // ATTN: Return value is ignored
1870                     AssocClassTable::getReferenceNames(
1871                          assocFileName,
1872                          classList,
1873                          resultClassList,
1874                          role,
1875                          referenceNames);
1876 kumpf       1.1 
1877                     PEG_METHOD_EXIT();
1878                 }
1879                 
1880                 void FileBasedStore::addInstanceAssociations(
1881                     const CIMNamespaceName& nameSpace,
1882                     const Array<InstanceAssociation>& instanceAssocEntries)
1883                 {
1884                     PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::addInstanceAssociations");
1885                 
1886                     String assocFileName = _getAssocInstPath(nameSpace);
1887                     PEGASUS_STD(ofstream) os;
1888                 
1889                     if (!OpenAppend(os, assocFileName))
1890                     {
1891                         PEG_METHOD_EXIT();
1892                         throw CannotOpenFile(assocFileName);
1893                     }
1894                 
1895                     for (Uint32 i = 0; i < instanceAssocEntries.size(); i++)
1896                     {
1897 kumpf       1.1         AssocInstTable::append(
1898                             os,
1899                             instanceAssocEntries[i].assocInstanceName,
1900                             instanceAssocEntries[i].assocClassName,
1901                             instanceAssocEntries[i].fromInstanceName,
1902                             instanceAssocEntries[i].fromClassName,
1903                             instanceAssocEntries[i].fromPropertyName,
1904                             instanceAssocEntries[i].toInstanceName,
1905                             instanceAssocEntries[i].toClassName,
1906                             instanceAssocEntries[i].toPropertyName);
1907                     }
1908                 
1909                     PEG_METHOD_EXIT();
1910                 }
1911                 
1912                 void FileBasedStore::removeInstanceAssociation(
1913                     const CIMNamespaceName& nameSpace,
1914                     const CIMObjectPath& assocInstanceName)
1915                 {
1916                     PEG_METHOD_ENTER(TRC_REPOSITORY,
1917                         "FileBasedStore::removeInstanceAssociation");
1918 kumpf       1.1 
1919                     String assocFileName = _getAssocInstPath(nameSpace);
1920                     AssocInstTable::deleteAssociation(assocFileName, assocInstanceName);
1921                 
1922                     PEG_METHOD_EXIT();
1923                 }
1924                 
1925                 void FileBasedStore::getInstanceAssociatorNames(
1926                     const CIMNamespaceName& nameSpace,
1927                     const CIMObjectPath& instanceName,
1928                     const Array<CIMName>& assocClassList,
1929                     const Array<CIMName>& resultClassList,
1930                     const String& role,
1931                     const String& resultRole,
1932                     Array<String>& associatorNames)
1933                 {
1934                     PEG_METHOD_ENTER(TRC_REPOSITORY,
1935                         "FileBasedStore::getInstanceAssociatorNames");
1936                 
1937                     String assocFileName = _getAssocInstPath(nameSpace);
1938                 
1939 kumpf       1.1     // ATTN: Return value is ignored.
1940                     AssocInstTable::getAssociatorNames(
1941                         assocFileName,
1942                         instanceName,
1943                         assocClassList,
1944                         resultClassList,
1945                         role,
1946                         resultRole,
1947                         associatorNames);
1948                 
1949                     PEG_METHOD_EXIT();
1950                 }
1951                 
1952                 void FileBasedStore::getInstanceReferenceNames(
1953                     const CIMNamespaceName& nameSpace,
1954                     const CIMObjectPath& instanceName,
1955                     const Array<CIMName>& resultClassList,
1956                     const String& role,
1957                     Array<String>& referenceNames)
1958                 {
1959                     PEG_METHOD_ENTER(TRC_REPOSITORY,
1960 kumpf       1.1         "FileBasedStore::getInstanceReferenceNames");
1961                 
1962                     String assocFileName = _getAssocInstPath(nameSpace);
1963                 
1964                     // ATTN: Return value is ignored.
1965                     AssocInstTable::getReferenceNames(
1966                         assocFileName,
1967                         instanceName,
1968                         resultClassList,
1969                         role,
1970                         referenceNames);
1971                 
1972                     PEG_METHOD_EXIT();
1973                 }
1974                 
1975                 PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2