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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2