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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2