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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2