(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                      Boolean found = _nameSpacePathTable.lookup(nameSpace.getString(), path);
1034                      PEGASUS_ASSERT(found);
1035                      return path;
1036                  }
1037                  
1038                  //----------------------------------------------------------------------
1039 kumpf       1.1  //
1040                  // _getQualifierFilePath()
1041                  //
1042                  //      returns the path of the qualifier file.
1043                  //
1044                  //----------------------------------------------------------------------
1045                  
1046                  String FileBasedStore::_getQualifierFilePath(
1047                      const CIMNamespaceName& nameSpace,
1048                      const CIMName& qualifierName) const
1049                  {
1050                      String tmp = _getNameSpaceDirPath(nameSpace);
1051                      tmp.append(_QUALIFIERS_SUFFIX);
1052                      tmp.append('/');
1053                      tmp.append(_escapeUtf8FileNameCharacters(qualifierName.getString()));
1054                      return tmp;
1055                  }
1056                  
1057                  //----------------------------------------------------------------------
1058                  //
1059                  // _getClassFilePath()
1060 kumpf       1.1  //
1061                  //      returns the path of the class file.
1062                  //
1063                  //----------------------------------------------------------------------
1064                  
1065                  String FileBasedStore::_getClassFilePath(
1066                      const CIMNamespaceName& nameSpace,
1067                      const CIMName& className,
1068                      const CIMName& superClassName) const
1069                  {
1070                      String tmp = _getNameSpaceDirPath(nameSpace);
1071                      tmp.append(_CLASSES_SUFFIX);
1072                      tmp.append('/');
1073                      tmp.append(_escapeUtf8FileNameCharacters(className.getString()));
1074                  
1075                      if (superClassName.isNull())
1076                      {
1077                          tmp.append(".#");
1078                      }
1079                      else
1080                      {
1081 kumpf       1.1          tmp.append('.');
1082                          tmp.append(_escapeUtf8FileNameCharacters(superClassName.getString()));
1083                      }
1084                  
1085                      return tmp;
1086                  }
1087                  
1088                  //----------------------------------------------------------------------
1089                  //
1090                  // _getInstanceIndexFilePath()
1091                  //
1092                  //      returns the path of the instance index file.
1093                  //
1094                  //----------------------------------------------------------------------
1095                  
1096                  String FileBasedStore::_getInstanceIndexFilePath(
1097                      const CIMNamespaceName& nameSpace,
1098                      const CIMName& className) const
1099                  {
1100                      String tmp = _getNameSpaceDirPath(nameSpace);
1101                      tmp.append(_INSTANCES_SUFFIX);
1102 kumpf       1.1      tmp.append('/');
1103                      tmp.append(_escapeUtf8FileNameCharacters(className.getString()));
1104                      tmp.append(".idx");
1105                      return tmp;
1106                  }
1107                  
1108                  //----------------------------------------------------------------------
1109                  //
1110                  // _getInstanceDataFilePath()
1111                  //
1112                  //      returns the path of the instance file.
1113                  //
1114                  //----------------------------------------------------------------------
1115                  
1116                  String FileBasedStore::_getInstanceDataFilePath(
1117                      const CIMNamespaceName& nameSpace,
1118                      const CIMName& className) const
1119                  {
1120                      String tmp = _getNameSpaceDirPath(nameSpace);
1121                      tmp.append(_INSTANCES_SUFFIX);
1122                      tmp.append('/');
1123 kumpf       1.1      tmp.append(_escapeUtf8FileNameCharacters(className.getString()));
1124                      tmp.append(".instances");
1125                      return tmp;
1126                  }
1127                  
1128                  //----------------------------------------------------------------------
1129                  //
1130                  // _getAssocClassPath()
1131                  //
1132                  //      returns the path of the class association file.
1133                  //
1134                  //----------------------------------------------------------------------
1135                  
1136                  String FileBasedStore::_getAssocClassPath(
1137                      const CIMNamespaceName& nameSpace) const
1138                  {
1139                      String tmp = _getNameSpaceDirPath(nameSpace);
1140                      tmp.append(_CLASSES_SUFFIX);
1141                      tmp.append(_ASSOCIATIONS_SUFFIX);
1142                      return tmp;
1143                  }
1144 kumpf       1.1  
1145                  //----------------------------------------------------------------------
1146                  //
1147                  // _getAssocInstPath()
1148                  //
1149                  //      returns the path of the instance association file.
1150                  //
1151                  //----------------------------------------------------------------------
1152                  
1153                  String FileBasedStore::_getAssocInstPath(
1154                      const CIMNamespaceName& nameSpace) const
1155                  {
1156                      String tmp = _getNameSpaceDirPath(nameSpace);
1157                      tmp.append(_INSTANCES_SUFFIX);
1158                      tmp.append(_ASSOCIATIONS_SUFFIX);
1159                      return tmp;
1160                  }
1161                  
1162                  Boolean FileBasedStore::_loadInstance(
1163                      const String& path,
1164                      CIMInstance& object,
1165 kumpf       1.1      Uint32 index,
1166                      Uint32 size)
1167                  {
1168                      PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::_loadInstance");
1169                  
1170                      //
1171                      // Load instance (in XML) from instance file into memory:
1172                      //
1173                  
1174                      Buffer data;
1175                  
1176                      if (!InstanceDataFile::loadInstance(path, index, size, data))
1177                      {
1178                          PEG_METHOD_EXIT();
1179                          return false;
1180                      }
1181                  
1182                      //
1183                      // Convert XML into an actual object:
1184                      //
1185                  
1186 kumpf       1.1      _streamer->decode(data, 0, object);
1187                  
1188                      PEG_METHOD_EXIT();
1189                      return true;
1190                  }
1191                  
1192                  Boolean FileBasedStore::_loadAllInstances(
1193                      const CIMNamespaceName& nameSpace,
1194                      const CIMName& className,
1195                      Array<CIMInstance>& namedInstances)
1196                  {
1197                      PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::_loadAllInstances");
1198                  
1199                      Array<CIMObjectPath> instanceNames;
1200                      Buffer data;
1201                      Array<Uint32> indices;
1202                      Array<Uint32> sizes;
1203                  
1204                      //
1205                      // Form the names of the instance index and data files
1206                      //
1207 kumpf       1.1  
1208                      String indexFilePath = _getInstanceIndexFilePath(nameSpace, className);
1209                      String dataFilePath = _getInstanceDataFilePath(nameSpace, className);
1210                  
1211                      //
1212                      // Enumerate the index file:
1213                      //
1214                  
1215                      Array<Uint32> freeFlags;
1216                  
1217                      if (!InstanceIndexFile::enumerateEntries(
1218                              indexFilePath, freeFlags, indices, sizes, instanceNames, true))
1219                      {
1220                          PEG_METHOD_EXIT();
1221                          return false;
1222                      }
1223                  
1224                      //
1225                      // Form the array of instances result:
1226                      //
1227                  
1228 kumpf       1.1      if (instanceNames.size() > 0)
1229                      {
1230                          //
1231                          // Load all instances from the data file:
1232                          //
1233                  
1234                          if (!InstanceDataFile::loadAllInstances(dataFilePath, data))
1235                          {
1236                              PEG_METHOD_EXIT();
1237                              return false;
1238                          }
1239                  
1240                          //
1241                          // for each instance loaded, call XML parser to parse the XML
1242                          // data and create a CIMInstance object.
1243                          //
1244                  
1245                          CIMInstance tmpInstance;
1246                  
1247 kumpf       1.15         const char* buffer = data.getData();
1248 kumpf       1.1  
1249                          for (Uint32 i = 0; i < instanceNames.size(); i++)
1250                          {
1251                              if (!freeFlags[i])
1252                              {
1253                                  Uint32 pos= (Uint32)((&(buffer[indices[i]]))-buffer);
1254                                  _streamer->decode(data, pos, tmpInstance);
1255                  
1256                                  tmpInstance.setPath(instanceNames[i]);
1257                  
1258                                  namedInstances.append(tmpInstance);
1259                              }
1260                          }
1261                      }
1262                  
1263                      PEG_METHOD_EXIT();
1264                      return true;
1265                  }
1266                  
1267                  Array<NamespaceDefinition> FileBasedStore::enumerateNameSpaces()
1268                  {
1269 kumpf       1.1      PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::enumerateNameSpaces");
1270                  
1271                      Array<NamespaceDefinition> nameSpaces;
1272                  
1273                      for (Dir dir(_repositoryPath); dir.more(); dir.next())
1274                      {
1275                          String nameSpaceDirName = dir.getName();
1276 kumpf       1.6          if ((nameSpaceDirName == "..") ||
1277                              (nameSpaceDirName == ".") ||
1278                              (nameSpaceDirName == _CONFIGFILE_NAME))
1279 kumpf       1.1          {
1280                              continue;
1281                          }
1282                  
1283                          String nameSpacePath = _repositoryPath + "/" + nameSpaceDirName;
1284                  
1285                          if (!FileSystem::isDirectory(nameSpacePath + _CLASSES_SUFFIX) ||
1286                              !FileSystem::isDirectory(nameSpacePath + _INSTANCES_SUFFIX) ||
1287                              !FileSystem::isDirectory(nameSpacePath + _QUALIFIERS_SUFFIX))
1288                          {
1289 thilo.boehm 1.5              PEG_TRACE((TRC_REPOSITORY, Tracer::LEVEL2,
1290                                  "Namespace: %s ignored -- "
1291                                  "subdirectories are not correctly formed",
1292                                  (const char*)nameSpaceDirName.getCString()));
1293 kumpf       1.1              continue;
1294                          }
1295                  
1296                          NamespaceDefinition nsdef(_dirNameToNamespaceName(nameSpaceDirName));
1297                  
1298                          Boolean skipThisNamespace = false;
1299                  
1300                          for (Dir subdir(nameSpacePath); subdir.more(); subdir.next())
1301                          {
1302                              String nameSpaceSubDirName = subdir.getName();
1303                              if (nameSpaceSubDirName == ".." || nameSpaceSubDirName == ".")
1304                              {
1305                                  continue;
1306                              }
1307                  
1308                              String tmp = nameSpaceSubDirName;
1309                              tmp.toLower();
1310                  
1311                              if (tmp[0] == 's')
1312                              {
1313                                  if ((tmp[1]=='w' || tmp[1]=='r') &&
1314 kumpf       1.1                      (tmp[2]=='f' || tmp[2]=='s'))
1315                                  {
1316                                      nsdef.shareable = tmp[2]=='s';
1317                                      nsdef.updatesAllowed = tmp[1]=='w';
1318                                      String parent = nameSpaceSubDirName.subString(3);
1319                                      if (parent.size())
1320                                      {
1321                                          nsdef.parentNameSpace = _dirNameToNamespaceName(parent);
1322                                      }
1323                                  }
1324                                  else
1325                                  {
1326 thilo.boehm 1.5                      PEG_TRACE((TRC_REPOSITORY, Tracer::LEVEL2,
1327                                          "Namespace %s ignored - "
1328                                          "using incorrect parent namespace specification: %s",
1329                                          (const char*)nameSpaceDirName.getCString(),
1330                                          (const char*)nameSpaceSubDirName.getCString()));
1331                  
1332 kumpf       1.1                      skipThisNamespace = true;
1333                                  }
1334                  #ifndef PEGASUS_ENABLE_REMOTE_CMPI
1335                                  break;
1336                  #endif
1337                              }
1338                  #ifdef PEGASUS_ENABLE_REMOTE_CMPI
1339                              else if (tmp[0] == 'r')
1340                              {
1341 kumpf       1.4                  // remoteInfo format is "ridhost[@port]" where "id" is a lower
1342                                  // case two-character identifier
1343                                  nsdef.remoteInfo = nameSpaceSubDirName;
1344 kumpf       1.1  
1345 thilo.boehm 1.5                  PEG_TRACE((TRC_REPOSITORY, Tracer::LEVEL4,
1346                                      "Remote namespace: %s >%s",
1347                                      (const char*)nameSpaceDirName.getCString(),
1348                                      (const char*)nameSpaceSubDirName.getCString()));
1349 kumpf       1.1              }
1350                  #endif
1351                          }
1352                  
1353                          if (!skipThisNamespace)
1354                          {
1355                              _nameSpacePathTable.insert(
1356                                  nsdef.name.getString(),
1357                                  _repositoryPath + "/" + nameSpaceDirName);
1358                              nameSpaces.append(nsdef);
1359                          }
1360                      }
1361                  
1362                      PEG_METHOD_EXIT();
1363                      return nameSpaces;
1364                  }
1365                  
1366                  void FileBasedStore::createNameSpace(
1367                      const CIMNamespaceName& nameSpace,
1368                      Boolean shareable,
1369                      Boolean updatesAllowed,
1370 venkat.puvvada 1.11     const String& parentNameSpace,
1371                         const String& remoteInfo)
1372 kumpf          1.1  {
1373                         PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::createNameSpace");
1374                     
1375                     #ifndef PEGASUS_SUPPORT_UTF8_FILENAME
1376                         // Do not allow file names to contain characters outside of 7-bit ASCII.
1377                         String nameSpaceNameString = nameSpace.getString();
1378                         Uint32 len = nameSpaceNameString.size();
1379                         for (Uint32 i = 0; i < len; ++i)
1380                         {
1381                             if ((Uint16)nameSpaceNameString[i] > 0x007F)
1382                             {
1383                                 PEG_METHOD_EXIT();
1384                                 throw PEGASUS_CIM_EXCEPTION(
1385                                     CIM_ERR_INVALID_PARAMETER, nameSpaceNameString);
1386                             }
1387                         }
1388                     #endif
1389                     
1390                         // Attempt to create all the namespace directories:
1391                     
1392                         String nameSpacePath =
1393 kumpf          1.1          _repositoryPath + "/" + _namespaceNameToDirName(nameSpace);
1394                     
1395                         if (!FileSystem::makeDirectory(nameSpacePath))
1396                         {
1397                             throw CannotCreateDirectory(nameSpacePath);
1398                         }
1399                     
1400                         String classesPath = nameSpacePath + _CLASSES_SUFFIX;
1401                         String instancesPath = nameSpacePath + _INSTANCES_SUFFIX;
1402                         String qualifiersPath = nameSpacePath + _QUALIFIERS_SUFFIX;
1403                     
1404                         if (!FileSystem::makeDirectory(classesPath))
1405                         {
1406                             throw CannotCreateDirectory(classesPath);
1407                         }
1408                     
1409                         if (!FileSystem::makeDirectory(instancesPath))
1410                         {
1411                             throw CannotCreateDirectory(instancesPath);
1412                         }
1413                     
1414 kumpf          1.1      if (!FileSystem::makeDirectory(qualifiersPath))
1415                         {
1416                             throw CannotCreateDirectory(qualifiersPath);
1417                         }
1418                     
1419                         if (shareable || !updatesAllowed || parentNameSpace.size())
1420                         {
1421                             String path = nameSpacePath + "/S" + (updatesAllowed ? "W" : "R") +
1422                                 (shareable ? "S" : "F");
1423                             if (parentNameSpace.size())
1424                             {
1425                                 path.append(_namespaceNameToDirName(parentNameSpace));
1426                             }
1427                     
1428                             if (!FileSystem::makeDirectory(path))
1429                             {
1430                                 throw CannotCreateDirectory(path);
1431                             }
1432                         }
1433                     
1434 venkat.puvvada 1.11 #ifdef PEGASUS_ENABLE_REMOTE_CMPI
1435                         if (remoteInfo.size())
1436                         {
1437                             String remoteDir(nameSpacePath);
1438                             remoteDir.append("/r10");
1439                             remoteDir.append(remoteInfo);
1440                             if (!FileSystem::makeDirectory(remoteDir))
1441                             {
1442                                 throw CannotCreateDirectory(remoteDir);
1443                             }
1444                         }
1445 karl           1.17 #else
1446                         // use unused parameter
1447                         remoteInfo.size();
1448 venkat.puvvada 1.11 #endif
1449                     
1450 kumpf          1.1      _nameSpacePathTable.insert(nameSpace.getString(), nameSpacePath);
1451                     
1452                         PEG_METHOD_EXIT();
1453                     }
1454                     
1455                     void FileBasedStore::modifyNameSpace(
1456                         const CIMNamespaceName& nameSpace,
1457                         Boolean shareable,
1458                         Boolean updatesAllowed)
1459                     {
1460                         PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::modifyNameSpace");
1461                     
1462                         String nameSpacePath = _getNameSpaceDirPath(nameSpace);
1463                         String oldSpecialDirName;
1464                     
1465                         for (Dir subdir(nameSpacePath); subdir.more(); subdir.next())
1466                         {
1467                             String dirName = subdir.getName();
1468                     
1469                             if ((dirName[0] == 's') || (dirName[0] == 'S'))
1470                             {
1471 kumpf          1.1              oldSpecialDirName = dirName;
1472                                 break;
1473                             }
1474                         }
1475                     
1476                         String newSpecialDirName = oldSpecialDirName;
1477                     
1478                         if (newSpecialDirName.size() == 0)
1479                         {
1480                             newSpecialDirName = "SWF";
1481                         }
1482                     
1483                         newSpecialDirName[0] = 'S';
1484                         newSpecialDirName[1] = updatesAllowed ? 'W' : 'R';
1485                         newSpecialDirName[2] = shareable ? 'S' : 'F';
1486                     
1487                         if (newSpecialDirName != oldSpecialDirName)
1488                         {
1489                             if (oldSpecialDirName.size())
1490                             {
1491                                 FileSystem::removeDirectoryHier(
1492 kumpf          1.1                  nameSpacePath + "/" + oldSpecialDirName);
1493                             }
1494                     
1495                             if (newSpecialDirName != "SWF")
1496                             {
1497                                 String newPath = nameSpacePath + "/" + newSpecialDirName;
1498                                 if (!FileSystem::makeDirectory(newPath))
1499                                 {
1500                                     PEG_METHOD_EXIT();
1501                                     throw CannotCreateDirectory(newPath);
1502                                 }
1503                             }
1504                         }
1505                     
1506                         PEG_METHOD_EXIT();
1507                     }
1508                     
1509                     void FileBasedStore::deleteNameSpace(const CIMNamespaceName& nameSpace)
1510                     {
1511                         PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::deleteNameSpace");
1512                     
1513 kumpf          1.1      String nameSpacePath = _getNameSpaceDirPath(nameSpace);
1514                     
1515                         if (!FileSystem::removeDirectoryHier(nameSpacePath))
1516                         {
1517                             PEG_METHOD_EXIT();
1518                             throw CannotRemoveDirectory(nameSpacePath);
1519                         }
1520                     
1521                         _nameSpacePathTable.remove(nameSpace.getString());
1522                     
1523                         PEG_METHOD_EXIT();
1524                     }
1525                     
1526                     Boolean FileBasedStore::isNameSpaceEmpty(const CIMNamespaceName& nameSpace)
1527                     {
1528                         PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::isNameSpaceEmpty");
1529                     
1530                         String nameSpacePath = _getNameSpaceDirPath(nameSpace);
1531                     
1532                         for (Dir dir(nameSpacePath); dir.more(); dir.next())
1533                         {
1534 kumpf          1.1          const char* name = dir.getName();
1535                     
1536                             if (strcmp(name, ".") != 0 &&
1537                                 strcmp(name, "..") != 0 &&
1538                                 System::strcasecmp(name, _CLASSES_DIR) != 0 &&
1539                                 System::strcasecmp(name, _INSTANCES_DIR) != 0 &&
1540                                 System::strcasecmp(name, _QUALIFIERS_DIR) != 0)
1541                             {
1542                                 // ATTN: Is it assumed that dependent namespaces are empty?
1543                                 return true;
1544                             }
1545                         }
1546                     
1547                         String classesPath = nameSpacePath + _CLASSES_SUFFIX;
1548                         String instancesPath = nameSpacePath + _INSTANCES_SUFFIX;
1549                         String qualifiersPath = nameSpacePath + _QUALIFIERS_SUFFIX;
1550                     
1551                         PEG_METHOD_EXIT();
1552                         return
1553                             FileSystem::isDirectoryEmpty(classesPath) &&
1554                             FileSystem::isDirectoryEmpty(instancesPath) &&
1555 kumpf          1.1          FileSystem::isDirectoryEmpty(qualifiersPath);
1556                     }
1557                     
1558                     Array<CIMQualifierDecl> FileBasedStore::enumerateQualifiers(
1559                         const CIMNamespaceName& nameSpace)
1560                     {
1561                         PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::enumerateQualifiers");
1562                     
1563                         String qualifiersRoot =
1564                             _getNameSpaceDirPath(nameSpace) + _QUALIFIERS_SUFFIX;
1565                     
1566                         Array<String> qualifierNames;
1567                     
1568                         if (!FileSystem::getDirectoryContents(qualifiersRoot, qualifierNames))
1569                         {
1570                             PEG_METHOD_EXIT();
1571                             String str ="enumerateQualifiers()";
1572                             throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1573                                 MessageLoaderParms("Repository.CIMRepository.INTERNAL_ERROR",
1574                                     "$0: internal error",
1575                                     str));
1576 kumpf          1.1      }
1577                     
1578                         Array<CIMQualifierDecl> qualifiers;
1579                     
1580                         for (Uint32 i = 0; i < qualifierNames.size(); i++)
1581                         {
1582                             CIMQualifierDecl qualifier = getQualifier(
1583                                 nameSpace, _unescapeUtf8FileNameCharacters(qualifierNames[i]));
1584                             qualifiers.append(qualifier);
1585                         }
1586                     
1587                         PEG_METHOD_EXIT();
1588                         return qualifiers;
1589                     }
1590                     
1591                     CIMQualifierDecl FileBasedStore::getQualifier(
1592                         const CIMNamespaceName& nameSpace,
1593                         const CIMName& qualifierName)
1594                     {
1595                         PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::getQualifier");
1596                     
1597 kumpf          1.1      CIMQualifierDecl qualifierDecl;
1598                     
1599                         //
1600                         // Get path of qualifier file:
1601                         //
1602                     
1603                         String qualifierFilePath = _getQualifierFilePath(nameSpace, qualifierName);
1604                     
1605                         try
1606                         {
1607                             _LoadObject(qualifierFilePath, qualifierDecl, _streamer);
1608                         }
1609                         catch (const CannotOpenFile&)
1610                         {
1611                             // Qualifier not found
1612                             PEG_METHOD_EXIT();
1613                             return CIMQualifierDecl();
1614                         }
1615                     
1616                         PEG_METHOD_EXIT();
1617                         return qualifierDecl;
1618 kumpf          1.1  }
1619                     
1620                     void FileBasedStore::setQualifier(
1621                         const CIMNamespaceName& nameSpace,
1622                         const CIMQualifierDecl& qualifierDecl)
1623                     {
1624                         PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::setQualifier");
1625                     
1626                         // -- Get path of qualifier file:
1627                     
1628                         String qualifierFilePath =
1629                             _getQualifierFilePath(nameSpace, qualifierDecl.getName());
1630                     
1631                         // -- If qualifier already exists, throw exception:
1632                     
1633                         if (FileSystem::existsNoCase(qualifierFilePath))
1634                         {
1635                             PEG_METHOD_EXIT();
1636                             throw PEGASUS_CIM_EXCEPTION(
1637                                 CIM_ERR_NOT_SUPPORTED, qualifierDecl.getName().getString());
1638                         }
1639 kumpf          1.1  
1640                         // -- Save qualifier:
1641                     
1642                         Buffer qualifierDeclXml;
1643                         _streamer->encode(qualifierDeclXml, qualifierDecl);
1644 karl           1.17     _SaveObject(qualifierFilePath, qualifierDeclXml);
1645 kumpf          1.1  
1646                         PEG_METHOD_EXIT();
1647                     }
1648                     
1649                     void FileBasedStore::deleteQualifier(
1650                         const CIMNamespaceName& nameSpace,
1651                         const CIMName& qualifierName)
1652                     {
1653                         PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::deleteQualifier");
1654                     
1655                         // -- Get path of qualifier file:
1656                     
1657                         String qualifierFilePath = _getQualifierFilePath(nameSpace, qualifierName);
1658                     
1659                         // -- Delete qualifier:
1660                     
1661                         if (!FileSystem::removeFileNoCase(qualifierFilePath))
1662                         {
1663                             PEG_METHOD_EXIT();
1664                             throw PEGASUS_CIM_EXCEPTION(
1665                                 CIM_ERR_NOT_FOUND, qualifierName.getString());
1666 kumpf          1.1      }
1667                     
1668                         PEG_METHOD_EXIT();
1669                     }
1670                     
1671                     Array<Pair<String, String> > FileBasedStore::enumerateClassNames(
1672                         const CIMNamespaceName& nameSpace)
1673                     {
1674                         PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::enumerateClassNames");
1675                     
1676                         Array<Pair<String, String> > classList;
1677                     
1678                         String classesPath = _getNameSpaceDirPath(nameSpace) + _CLASSES_SUFFIX;
1679                     
1680                         for (Dir dir(classesPath); dir.more(); dir.next())
1681                         {
1682                             String fileName = dir.getName();
1683                     
1684                             // Ignore the current and parent directories.
1685                     
1686                             if (fileName == "." || fileName == "..")
1687 kumpf          1.1              continue;
1688                     
1689                             Uint32 dot = fileName.find('.');
1690                     
1691                             // Ignore files without dots in them:
1692                     
1693                             if (dot == PEG_NOT_FOUND)
1694                                 continue;
1695                     
1696                             String className =
1697                                 _unescapeUtf8FileNameCharacters(fileName.subString(0, dot));
1698                             String superClassName =
1699                                 _unescapeUtf8FileNameCharacters(fileName.subString(dot + 1));
1700                     
1701                             if (superClassName == "#")
1702                                 superClassName.clear();
1703                     
1704                             classList.append(Pair<String, String>(className, superClassName));
1705                         }
1706                     
1707                         PEG_METHOD_EXIT();
1708 kumpf          1.1      return classList;
1709                     }
1710                     
1711                     CIMClass FileBasedStore::getClass(
1712                         const CIMNamespaceName& nameSpace,
1713                         const CIMName& className,
1714                         const CIMName& superClassName)
1715                     {
1716                         PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::getClass");
1717                     
1718                         String classFilePath =
1719                             _getClassFilePath(nameSpace, className, superClassName);
1720                         CIMClass cimClass;
1721                         _LoadObject(classFilePath, cimClass, _streamer);
1722                     
1723                         PEG_METHOD_EXIT();
1724                         return cimClass;
1725                     }
1726                     
1727                     void FileBasedStore::createClass(
1728                         const CIMNamespaceName& nameSpace,
1729 kumpf          1.3      const CIMClass& newClass,
1730                         const Array<ClassAssociation>& classAssocEntries)
1731 kumpf          1.1  {
1732                         PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::createClass");
1733                     
1734                     #ifndef PEGASUS_SUPPORT_UTF8_FILENAME
1735                         // Do not allow file names to contain characters outside of 7-bit ASCII.
1736                         String classNameString = newClass.getClassName().getString();
1737                         Uint32 len = classNameString.size();
1738                         for (Uint32 i = 0; i < len; ++i)
1739                         {
1740                             if ((Uint16)classNameString[i] > 0x007F)
1741                             {
1742                                 PEG_METHOD_EXIT();
1743                                 throw PEGASUS_CIM_EXCEPTION(
1744                                     CIM_ERR_INVALID_PARAMETER, classNameString);
1745                             }
1746                         }
1747                     #endif
1748                     
1749                         String classFilePath = _getClassFilePath(
1750                             nameSpace, newClass.getClassName(), newClass.getSuperClassName());
1751                         Buffer classXml;
1752 kumpf          1.1      _streamer->encode(classXml, newClass);
1753 karl           1.17     _SaveObject(classFilePath, classXml);
1754 kumpf          1.1  
1755 kumpf          1.3      if (classAssocEntries.size())
1756                         {
1757                             _addClassAssociationEntries(nameSpace, classAssocEntries);
1758                         }
1759                     
1760 kumpf          1.1      PEG_METHOD_EXIT();
1761                     }
1762                     
1763                     void FileBasedStore::modifyClass(
1764                         const CIMNamespaceName& nameSpace,
1765 kumpf          1.3      const CIMClass& modifiedClass,
1766 kumpf          1.6      const CIMName& oldSuperClassName,
1767 kumpf          1.3      Boolean isAssociation,
1768                         const Array<ClassAssociation>& classAssocEntries)
1769 kumpf          1.1  {
1770                         PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::modifyClass");
1771                     
1772                         String classFilePath = _getClassFilePath(
1773                             nameSpace,
1774                             modifiedClass.getClassName(),
1775                             modifiedClass.getSuperClassName());
1776                     
1777 kumpf          1.6      String oldClassFilePath = _getClassFilePath(
1778                             nameSpace,
1779                             modifiedClass.getClassName(),
1780                             oldSuperClassName);
1781                     
1782 kumpf          1.1      //
1783                         // Delete the old file containing the class:
1784                         //
1785                     
1786 kumpf          1.6      if (!FileSystem::removeFileNoCase(oldClassFilePath))
1787 kumpf          1.1      {
1788                             PEG_METHOD_EXIT();
1789                             // ATTN: Parameter should be file name, not method name.
1790                             String str = "FileBasedStore::modifyClass()";
1791                             throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1792                                 MessageLoaderParms(
1793                                     "Repository.CIMRepository.FAILED_TO_REMOVE_FILE",
1794 kumpf          1.6                  "failed to remove file in $0", classFilePath /*str*/));
1795 kumpf          1.1      }
1796                     
1797                         //
1798                         // Create new class file:
1799                         //
1800                     
1801                         Buffer classXml;
1802                         _streamer->encode(classXml, modifiedClass);
1803 karl           1.17     _SaveObject(classFilePath, classXml);
1804 kumpf          1.1  
1805 kumpf          1.3      //
1806                         // Update the association entries
1807                         //
1808                     
1809                         if (isAssociation)
1810                         {
1811                             _removeClassAssociationEntries(nameSpace, modifiedClass.getClassName());
1812                             if (classAssocEntries.size())
1813                             {
1814                                 _addClassAssociationEntries(nameSpace, classAssocEntries);
1815                             }
1816                         }
1817                     
1818 kumpf          1.1      PEG_METHOD_EXIT();
1819                     }
1820                     
1821                     void FileBasedStore::deleteClass(
1822                         const CIMNamespaceName& nameSpace,
1823                         const CIMName& className,
1824 kumpf          1.3      const CIMName& superClassName,
1825                         Boolean isAssociation,
1826                         const Array<CIMNamespaceName>& dependentNameSpaceNames)
1827 kumpf          1.1  {
1828                         PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::deleteClass");
1829                     
1830 kumpf          1.3      //
1831                         // Clean up the instance files in this namespace and in all dependent
1832                         // namespaces.  (It was already checked that no instances exist.)
1833                         //
1834                     
1835                         for (Uint32 i = 0; i < dependentNameSpaceNames.size(); i++)
1836                         {
1837                             String indexFilePath =
1838                                 _getInstanceIndexFilePath(nameSpace, className);
1839                             String dataFilePath =
1840                                 _getInstanceDataFilePath(nameSpace, className);
1841                     
1842                             FileSystem::removeFileNoCase(indexFilePath);
1843                             FileSystem::removeFileNoCase(dataFilePath);
1844                         }
1845                     
1846 kumpf          1.1      // Remove class file
1847                     
1848                         String classFilePath =
1849                             _getClassFilePath(nameSpace, className, superClassName);
1850                     
1851                         if (!FileSystem::removeFileNoCase(classFilePath))
1852                         {
1853                             PEG_METHOD_EXIT();
1854                             throw CannotRemoveFile(classFilePath);
1855                         }
1856                     
1857 kumpf          1.3      //
1858                         // Remove association entries
1859                         //
1860                     
1861                         if (isAssociation)
1862                         {
1863                             _removeClassAssociationEntries(nameSpace, className);
1864                         }
1865                     
1866 kumpf          1.1      PEG_METHOD_EXIT();
1867                     }
1868                     
1869                     Array<CIMObjectPath> FileBasedStore::enumerateInstanceNamesForClass(
1870                         const CIMNamespaceName& nameSpace,
1871                         const CIMName& className)
1872                     {
1873                         PEG_METHOD_ENTER(TRC_REPOSITORY,
1874                             "FileBasedStore::enumerateInstanceNamesForClass");
1875                     
1876                         //
1877                         // Get instance names from the instance index file for the class:
1878                         //
1879                         Array<Uint32> indices;
1880                         Array<Uint32> sizes;
1881                     
1882                         //
1883                         // Form the names of the instance index and data files
1884                         //
1885                     
1886                         String indexFilePath = _getInstanceIndexFilePath(nameSpace, className);
1887 kumpf          1.1      String dataFilePath = _getInstanceDataFilePath(nameSpace, className);
1888                     
1889                         //
1890                         // Get all instances for the class:
1891                         //
1892                     
1893                         Array<CIMObjectPath> instanceNames;
1894                         Array<Uint32> freeFlags;
1895                     
1896                         if (!InstanceIndexFile::enumerateEntries(
1897                                 indexFilePath, freeFlags, indices, sizes, instanceNames, false))
1898                         {
1899                             PEG_METHOD_EXIT();
1900                             throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1901                                 MessageLoaderParms(
1902                                     "Repository.CIMRepository.FAILED_TO_LOAD_INSTANCE_NAMES",
1903                                     "Failed to load instance names in class $0",
1904                                     className.getString()));
1905                         }
1906                     
1907                         PEG_METHOD_EXIT();
1908 kumpf          1.1      return instanceNames;
1909                     }
1910                     
1911                     Array<CIMInstance> FileBasedStore::enumerateInstancesForClass(
1912                         const CIMNamespaceName& nameSpace,
1913                         const CIMName& className)
1914                     {
1915                         PEG_METHOD_ENTER(TRC_REPOSITORY,
1916                             "FileBasedStore::enumerateInstancesForClass");
1917                     
1918                         Array<CIMInstance> cimInstances;
1919                     
1920                         if (!_loadAllInstances(nameSpace, className, cimInstances))
1921                         {
1922                             PEG_METHOD_EXIT();
1923                             throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1924                                 MessageLoaderParms(
1925                                     "Repository.CIMRepository.FAILED_TO_LOAD_INSTANCES",
1926                                     "Failed to load instances in class $0",
1927                                     className.getString()));
1928                         }
1929 kumpf          1.1  
1930                         PEG_METHOD_EXIT();
1931                         return cimInstances;
1932                     }
1933                     
1934                     CIMInstance FileBasedStore::getInstance(
1935                         const CIMNamespaceName& nameSpace,
1936                         const CIMObjectPath& instanceName)
1937                     {
1938                         PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::getInstance");
1939                     
1940                         //
1941                         // Get paths of index and data files:
1942                         //
1943                     
1944                         String indexFilePath = _getInstanceIndexFilePath(
1945                             nameSpace, instanceName.getClassName());
1946                     
1947                         String dataFilePath = _getInstanceDataFilePath(
1948                             nameSpace, instanceName.getClassName());
1949                     
1950 kumpf          1.1      //
1951                         // Get the index for this instance:
1952                         //
1953                     
1954                         Uint32 index;
1955                         Uint32 size;
1956                     
1957                         if (!InstanceIndexFile::lookupEntry(
1958                                 indexFilePath, instanceName, index, size))
1959                         {
1960                             PEG_METHOD_EXIT();
1961                             throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, instanceName.toString());
1962                         }
1963                     
1964                         //
1965                         // Load the instance from file:
1966                         //
1967                     
1968                         CIMInstance cimInstance;
1969                     
1970                         if (!_loadInstance(dataFilePath, cimInstance, index, size))
1971 kumpf          1.1      {
1972                             PEG_METHOD_EXIT();
1973                             throw CannotOpenFile(dataFilePath);
1974                         }
1975                     
1976                         PEG_METHOD_EXIT();
1977                         return cimInstance;
1978                     }
1979                     
1980                     void FileBasedStore::createInstance(
1981                         const CIMNamespaceName& nameSpace,
1982                         const CIMObjectPath& instanceName,
1983 kumpf          1.3      const CIMInstance& cimInstance,
1984                         const Array<InstanceAssociation>& instAssocEntries)
1985 kumpf          1.1  {
1986                         PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::createInstance");
1987                     
1988                         //
1989                         // Get paths to data and index files:
1990                         //
1991                     
1992                         String indexFilePath = _getInstanceIndexFilePath(
1993                             nameSpace, cimInstance.getClassName());
1994                     
1995                         String dataFilePath = _getInstanceDataFilePath(
1996                             nameSpace, cimInstance.getClassName());
1997                     
1998                         //
1999                         // Perform the operation in a transaction scope to enable rollback on
2000                         // failure.
2001                         //
2002                     
2003                         InstanceTransactionHandler transaction(indexFilePath, dataFilePath);
2004                     
2005                         //
2006 kumpf          1.1      // Save instance to file:
2007                         //
2008                     
2009                         Uint32 index;
2010                         Uint32 size;
2011                     
2012                         {
2013                             Buffer data;
2014                             _streamer->encode(data, cimInstance);
2015                             size = data.size();
2016                     
2017                             if (!InstanceDataFile::appendInstance(dataFilePath, data, index))
2018                             {
2019                                 PEG_METHOD_EXIT();
2020                                 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
2021                                     MessageLoaderParms(
2022                                         "Repository.CIMRepository.FAILED_TO_CREATE_INSTANCE",
2023                                         "Failed to create instance: $0",
2024                                         instanceName.toString()));
2025                             }
2026                         }
2027 kumpf          1.1  
2028                         //
2029                         // Create entry in index file:
2030                         //
2031                     
2032                         if (!InstanceIndexFile::createEntry(
2033                                 indexFilePath, instanceName, index, size))
2034                         {
2035                             PEG_METHOD_EXIT();
2036                             throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
2037                                 MessageLoaderParms(
2038                                     "Repository.CIMRepository.FAILED_TO_CREATE_INSTANCE",
2039                                     "Failed to create instance: $0",
2040                                     instanceName.toString()));
2041                         }
2042                     
2043                         transaction.complete();
2044                     
2045 kumpf          1.3      //
2046                         // Create association entries if an association instance.
2047                         //
2048                     
2049                         if (instAssocEntries.size())
2050                         {
2051                             _addInstanceAssociationEntries(nameSpace, instAssocEntries);
2052                         }
2053                     
2054 kumpf          1.1      PEG_METHOD_EXIT();
2055                     }
2056                     
2057                     void FileBasedStore::modifyInstance(
2058                         const CIMNamespaceName& nameSpace,
2059                         const CIMObjectPath& instanceName,
2060                         const CIMInstance& cimInstance)
2061                     {
2062                         PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::modifyInstance");
2063                     
2064                         //
2065                         // Get paths of index and data files:
2066                         //
2067                     
2068                         String indexFilePath = _getInstanceIndexFilePath(
2069                             nameSpace, cimInstance.getClassName());
2070                     
2071                         String dataFilePath = _getInstanceDataFilePath(
2072                             nameSpace, cimInstance.getClassName());
2073                     
2074                         //
2075 kumpf          1.1      // Look up the specified instance
2076                         //
2077                     
2078                         Uint32 oldSize;
2079                         Uint32 oldIndex;
2080                         Uint32 newSize;
2081                         Uint32 newIndex;
2082                     
2083                         if (!InstanceIndexFile::lookupEntry(
2084                                 indexFilePath, instanceName, oldIndex, oldSize))
2085                         {
2086                             PEG_METHOD_EXIT();
2087                             throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, instanceName.toString());
2088                         }
2089                     
2090                         //
2091                         // Perform the operation in a transaction scope to enable rollback on
2092                         // failure.
2093                         //
2094                     
2095                         InstanceTransactionHandler transaction(indexFilePath, dataFilePath);
2096 kumpf          1.1  
2097                         //
2098                         // Modify the data file:
2099                         //
2100                     
2101                         {
2102                             Buffer out;
2103                             _streamer->encode(out, cimInstance);
2104                     
2105                             newSize = out.size();
2106                     
2107                             if (!InstanceDataFile::appendInstance(dataFilePath, out, newIndex))
2108                             {
2109                                 PEG_METHOD_EXIT();
2110                                 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
2111                                     MessageLoaderParms(
2112                                         "Repository.CIMRepository.FAILED_TO_MODIFY_INSTANCE",
2113                                         "Failed to modify instance $0",
2114                                         instanceName.toString()));
2115                             }
2116                         }
2117 kumpf          1.1  
2118                         //
2119                         // Modify the index file:
2120                         //
2121                     
2122                         Uint32 freeCount;
2123                     
2124                         if (!InstanceIndexFile::modifyEntry(indexFilePath, instanceName, newIndex,
2125                             newSize, freeCount))
2126                         {
2127                             PEG_METHOD_EXIT();
2128                             throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
2129                                 MessageLoaderParms(
2130                                     "Repository.CIMRepository.FAILED_TO_MODIFY_INSTANCE",
2131                                     "Failed to modify instance $0",
2132                                     instanceName.toString()));
2133                         }
2134                     
2135                         //
2136                         // Compact the index and data files if the free count max was
2137                         // reached.
2138 kumpf          1.1      //
2139                     
2140                         if (freeCount >= _MAX_FREE_COUNT)
2141                         {
2142                             _CompactInstanceRepository(indexFilePath, dataFilePath);
2143                         }
2144                     
2145                         transaction.complete();
2146                     
2147                         PEG_METHOD_EXIT();
2148                     }
2149                     
2150                     void FileBasedStore::deleteInstance(
2151                         const CIMNamespaceName& nameSpace,
2152                         const CIMObjectPath& instanceName)
2153                     {
2154                         PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::deleteInstance");
2155                     
2156                         //
2157                         // Get paths of index and data files:
2158                         //
2159 kumpf          1.1  
2160                         String indexFilePath = _getInstanceIndexFilePath(
2161                             nameSpace, instanceName.getClassName());
2162                     
2163                         String dataFilePath = _getInstanceDataFilePath(
2164                             nameSpace, instanceName.getClassName());
2165                     
2166                         //
2167                         // Perform the operation in a transaction scope to enable rollback on
2168                         // failure.
2169                         //
2170                     
2171                         InstanceTransactionHandler transaction(indexFilePath, dataFilePath);
2172                     
2173                         //
2174                         // Lookup instance from the index file (raise error if not found).
2175                         //
2176                     
2177                         Uint32 index;
2178                         Uint32 size;
2179                     
2180 kumpf          1.1      if (!InstanceIndexFile::lookupEntry(
2181                                 indexFilePath, instanceName, index, size))
2182                         {
2183                             PEG_METHOD_EXIT();
2184                             throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, instanceName.toString());
2185                         }
2186                     
2187                         //
2188                         // Remove entry from index file.
2189                         //
2190                     
2191                         Uint32 freeCount;
2192                     
2193                         if (!InstanceIndexFile::deleteEntry(indexFilePath, instanceName, freeCount))
2194                         {
2195                             PEG_METHOD_EXIT();
2196                             throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
2197                                 MessageLoaderParms(
2198                                     "Repository.CIMRepository.FAILED_TO_DELETE_INSTANCE",
2199                                     "Failed to delete instance: $0",
2200                                     instanceName.toString()));
2201 kumpf          1.1      }
2202                     
2203                         //
2204                         // Compact the index and data files if the free count max was
2205                         // reached.
2206                         //
2207                     
2208                         if (freeCount >= _MAX_FREE_COUNT)
2209                         {
2210                             _CompactInstanceRepository(indexFilePath, dataFilePath);
2211                         }
2212                     
2213                         transaction.complete();
2214                     
2215 kumpf          1.3      //
2216                         // Delete from association table (if an association).
2217                         //
2218 kumpf          1.1  
2219 kumpf          1.3      _removeInstanceAssociationEntries(nameSpace, instanceName);
2220 kumpf          1.1  
2221                         PEG_METHOD_EXIT();
2222                     }
2223                     
2224                     Boolean FileBasedStore::instanceExists(
2225                         const CIMNamespaceName& nameSpace,
2226                         const CIMObjectPath& instanceName)
2227                     {
2228                         PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::instanceExists");
2229                     
2230                         String path =
2231                             _getInstanceIndexFilePath(nameSpace, instanceName.getClassName());
2232                     
2233                         Uint32 index;
2234                         Uint32 size;
2235                         if (InstanceIndexFile::lookupEntry(path, instanceName, index, size))
2236                         {
2237                             PEG_METHOD_EXIT();
2238                             return true;
2239                         }
2240                     
2241 kumpf          1.1      PEG_METHOD_EXIT();
2242                         return false;
2243                     }
2244                     
2245 kumpf          1.3  void FileBasedStore::_addClassAssociationEntries(
2246 kumpf          1.1      const CIMNamespaceName& nameSpace,
2247                         const Array<ClassAssociation>& classAssocEntries)
2248                     {
2249 kumpf          1.3      PEG_METHOD_ENTER(TRC_REPOSITORY,
2250                             "FileBasedStore::_addClassAssociationEntries");
2251 kumpf          1.1  
2252                         String assocFileName = _getAssocClassPath(nameSpace);
2253                         PEGASUS_STD(ofstream) os;
2254                     
2255                         if (!OpenAppend(os, assocFileName))
2256                         {
2257                             PEG_METHOD_EXIT();
2258                             throw CannotOpenFile(assocFileName);
2259                         }
2260                     
2261                         for (Uint32 i = 0; i < classAssocEntries.size(); i++)
2262                         {
2263 kumpf          1.9          _assocClassTable.append(
2264 kumpf          1.1              os,
2265                                 assocFileName,
2266 kumpf          1.9              classAssocEntries[i]);
2267 kumpf          1.1      }
2268                     
2269                         PEG_METHOD_EXIT();
2270                     }
2271                     
2272 kumpf          1.3  void FileBasedStore::_removeClassAssociationEntries(
2273 kumpf          1.1      const CIMNamespaceName& nameSpace,
2274                         const CIMName& assocClassName)
2275                     {
2276 kumpf          1.3      PEG_METHOD_ENTER(TRC_REPOSITORY,
2277                             "FileBasedStore::_removeClassAssociationEntries");
2278 kumpf          1.1  
2279                         String assocFileName = _getAssocClassPath(nameSpace);
2280 kumpf          1.9      _assocClassTable.deleteAssociation(assocFileName, assocClassName);
2281 kumpf          1.1  
2282                         PEG_METHOD_EXIT();
2283                     }
2284                     
2285                     void FileBasedStore::getClassAssociatorNames(
2286                         const CIMNamespaceName& nameSpace,
2287                         const Array<CIMName>& classList,
2288                         const Array<CIMName>& assocClassList,
2289                         const Array<CIMName>& resultClassList,
2290                         const String& role,
2291                         const String& resultRole,
2292                         Array<String>& associatorNames)
2293                     {
2294                         PEG_METHOD_ENTER(TRC_REPOSITORY,
2295                             "FileBasedStore::getClassAssociatorNames");
2296                     
2297                         String assocFileName = _getAssocClassPath(nameSpace);
2298                     
2299 thilo.boehm    1.2      // ATTN: Return value is ignored
2300 kumpf          1.9      _assocClassTable.getAssociatorNames(
2301 thilo.boehm    1.2          assocFileName,
2302                             classList,
2303                             assocClassList,
2304                             resultClassList,
2305                             role,
2306                             resultRole,
2307                             associatorNames);
2308 kumpf          1.1  
2309                         PEG_METHOD_EXIT();
2310                     }
2311                     
2312                     void FileBasedStore::getClassReferenceNames(
2313                         const CIMNamespaceName& nameSpace,
2314                         const Array<CIMName>& classList,
2315                         const Array<CIMName>& resultClassList,
2316                         const String& role,
2317                         Array<String>& referenceNames)
2318                     {
2319                         PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::getClassReferenceNames");
2320                     
2321                         String assocFileName = _getAssocClassPath(nameSpace);
2322                     
2323 thilo.boehm    1.2      // ATTN: Return value is ignored
2324 kumpf          1.9      _assocClassTable.getReferenceNames(
2325 thilo.boehm    1.2           assocFileName,
2326                              classList,
2327                              resultClassList,
2328                              role,
2329                              referenceNames);
2330 kumpf          1.1  
2331                         PEG_METHOD_EXIT();
2332                     }
2333                     
2334 kumpf          1.3  void FileBasedStore::_addInstanceAssociationEntries(
2335 kumpf          1.1      const CIMNamespaceName& nameSpace,
2336                         const Array<InstanceAssociation>& instanceAssocEntries)
2337                     {
2338 kumpf          1.3      PEG_METHOD_ENTER(TRC_REPOSITORY,
2339                             "FileBasedStore::_addInstanceAssociationEntries");
2340 kumpf          1.1  
2341                         String assocFileName = _getAssocInstPath(nameSpace);
2342                         PEGASUS_STD(ofstream) os;
2343                     
2344                         if (!OpenAppend(os, assocFileName))
2345                         {
2346                             PEG_METHOD_EXIT();
2347                             throw CannotOpenFile(assocFileName);
2348                         }
2349                     
2350                         for (Uint32 i = 0; i < instanceAssocEntries.size(); i++)
2351                         {
2352                             AssocInstTable::append(
2353                                 os,
2354                                 instanceAssocEntries[i].assocInstanceName,
2355                                 instanceAssocEntries[i].assocClassName,
2356                                 instanceAssocEntries[i].fromInstanceName,
2357                                 instanceAssocEntries[i].fromClassName,
2358                                 instanceAssocEntries[i].fromPropertyName,
2359                                 instanceAssocEntries[i].toInstanceName,
2360                                 instanceAssocEntries[i].toClassName,
2361 kumpf          1.1              instanceAssocEntries[i].toPropertyName);
2362                         }
2363                     
2364                         PEG_METHOD_EXIT();
2365                     }
2366                     
2367 kumpf          1.3  void FileBasedStore::_removeInstanceAssociationEntries(
2368 kumpf          1.1      const CIMNamespaceName& nameSpace,
2369                         const CIMObjectPath& assocInstanceName)
2370                     {
2371                         PEG_METHOD_ENTER(TRC_REPOSITORY,
2372 kumpf          1.3          "FileBasedStore::_removeInstanceAssociationEntries");
2373 kumpf          1.1  
2374                         String assocFileName = _getAssocInstPath(nameSpace);
2375                         AssocInstTable::deleteAssociation(assocFileName, assocInstanceName);
2376                     
2377                         PEG_METHOD_EXIT();
2378                     }
2379                     
2380                     void FileBasedStore::getInstanceAssociatorNames(
2381                         const CIMNamespaceName& nameSpace,
2382                         const CIMObjectPath& instanceName,
2383                         const Array<CIMName>& assocClassList,
2384                         const Array<CIMName>& resultClassList,
2385                         const String& role,
2386                         const String& resultRole,
2387                         Array<String>& associatorNames)
2388                     {
2389                         PEG_METHOD_ENTER(TRC_REPOSITORY,
2390                             "FileBasedStore::getInstanceAssociatorNames");
2391                     
2392                         String assocFileName = _getAssocInstPath(nameSpace);
2393                     
2394 kumpf          1.1      // ATTN: Return value is ignored.
2395                         AssocInstTable::getAssociatorNames(
2396                             assocFileName,
2397                             instanceName,
2398                             assocClassList,
2399                             resultClassList,
2400                             role,
2401                             resultRole,
2402                             associatorNames);
2403                     
2404                         PEG_METHOD_EXIT();
2405                     }
2406                     
2407                     void FileBasedStore::getInstanceReferenceNames(
2408                         const CIMNamespaceName& nameSpace,
2409                         const CIMObjectPath& instanceName,
2410                         const Array<CIMName>& resultClassList,
2411                         const String& role,
2412                         Array<String>& referenceNames)
2413                     {
2414                         PEG_METHOD_ENTER(TRC_REPOSITORY,
2415 kumpf          1.1          "FileBasedStore::getInstanceReferenceNames");
2416                     
2417                         String assocFileName = _getAssocInstPath(nameSpace);
2418                     
2419                         // ATTN: Return value is ignored.
2420                         AssocInstTable::getReferenceNames(
2421                             assocFileName,
2422                             instanceName,
2423                             resultClassList,
2424                             role,
2425                             referenceNames);
2426                     
2427                         PEG_METHOD_EXIT();
2428                     }
2429                     
2430 karl           1.17 ////////////////////////////////////////////////////////////////////////////////
2431                     //
2432                     // _SaveObject()
2433                     //
2434                     //      Saves objects (classes and qualifiers) from memory to
2435                     //      disk files.
2436                     //
2437                     ////////////////////////////////////////////////////////////////////////////////
2438                     
2439                     void FileBasedStore::_SaveObject(
2440                         const String& path,
2441                         Buffer& objectXml)
2442                     {
2443                         PEG_METHOD_ENTER(TRC_REPOSITORY, "FileBasedStore::_SaveObject");
2444                     
2445                     #ifdef PEGASUS_ENABLE_COMPRESSED_REPOSITORY
2446                         if (_compressMode)            // PEP214
2447                         {
2448                             PEGASUS_STD(ostringstream) os;
2449                             _streamer->write(os, objectXml);
2450                             string str = os.str();
2451 karl           1.17 
2452                             gzFile fp = gzopen(path.getCString(), "wb");
2453                     
2454                             if (fp == NULL)
2455                               throw CannotOpenFile(path);
2456                     
2457                             const char* ptr = str.data();
2458                             size_t rem = str.size();
2459                             int n;
2460                     
2461                             while (rem > 0 && (n = gzwrite(fp, (char*)ptr, rem)) > 0)
2462                             {
2463                                 ptr += n;
2464                                 rem -= n;
2465                             }
2466                     
2467                             gzclose(fp);
2468                         }
2469                         else
2470                     #endif /* PEGASUS_ENABLE_COMPRESSED_REPOSITORY */
2471                         {
2472 karl           1.17         PEGASUS_STD(ofstream) os(path.getCString() PEGASUS_IOS_BINARY);
2473                     
2474                             if (!os)
2475                             {
2476                                 PEG_METHOD_EXIT();
2477                                 throw CannotOpenFile(path);
2478                             }
2479                     
2480                             _streamer->write(os, objectXml);
2481                         }
2482                         PEG_METHOD_EXIT();
2483                     }
2484                     
2485 kumpf          1.1  PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2