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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2