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

   1 karl  1.47 //%2006////////////////////////////////////////////////////////////////////////
   2 mike  1.17 //
   3 karl  1.40 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
   4            // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
   5            // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
   6 karl  1.36 // IBM Corp.; EMC Corporation, The Open Group.
   7 karl  1.40 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
   8            // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
   9 karl  1.42 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
  10            // EMC Corporation; VERITAS Software Corporation; The Open Group.
  11 karl  1.47 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
  12            // EMC Corporation; Symantec Corporation; The Open Group.
  13 mike  1.17 //
  14            // Permission is hereby granted, free of charge, to any person obtaining a copy
  15 kumpf 1.26 // of this software and associated documentation files (the "Software"), to
  16            // deal in the Software without restriction, including without limitation the
  17            // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  18 mike  1.17 // sell copies of the Software, and to permit persons to whom the Software is
  19            // furnished to do so, subject to the following conditions:
  20 karl  1.56 //
  21 kumpf 1.26 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
  22 mike  1.17 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
  23            // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
  24 kumpf 1.26 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  25            // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  26            // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  27 mike  1.17 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28            // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29            //
  30            //==============================================================================
  31            //
  32            //%/////////////////////////////////////////////////////////////////////////////
  33            
  34 mike  1.18 #include <Pegasus/Common/Config.h>
  35 mike  1.17 #include <fstream>
  36            #include <cctype>
  37            #include <cstdio>
  38 mike  1.20 #include <cstring>
  39 mike  1.17 #include <cstdlib>
  40            #include <Pegasus/Common/FileSystem.h>
  41 kumpf 1.22 #include <Pegasus/Common/Tracer.h>
  42 mike  1.17 #include "InstanceIndexFile.h"
  43            
  44            PEGASUS_USING_STD;
  45            
  46            PEGASUS_NAMESPACE_BEGIN
  47            
  48 mike  1.20 ////////////////////////////////////////////////////////////////////////////////
  49            //
  50            // Local routines:
  51 mike  1.17 //
  52 mike  1.20 ////////////////////////////////////////////////////////////////////////////////
  53 kumpf 1.57 
  54 marek 1.32 #ifdef PEGASUS_OS_ZOS
  55 mike  1.20 
  56 marek 1.32 static Uint32 getOffset( streampos sp )
  57            {
  58                Uint32 result = (streamoff)sp;
  59            
  60                fpos_t posArray = sp.seekpos();
  61            
  62            
  63                result += posArray.__fpos_elem[1];
  64            
  65                return result;
  66            }
  67 kumpf 1.57 
  68 marek 1.32 #endif
  69 kumpf 1.57 
  70            //
  71            // Converts a CIMObjectPath to a form that can be used as a key in the index
  72            // file.  Newline and carriage return characters are escaped to prevent
  73            // problems with the line-based file format. 
  74            //
  75            
  76            static String _convertInstanceNameToKey(const CIMObjectPath& instanceName)
  77            {
  78                String instanceNameString(instanceName.toString());
  79                const Uint32 stringLength = instanceNameString.size();
  80                String keyString;
  81                keyString.reserveCapacity(stringLength);
  82            
  83                for (Uint32 i = 0; i < stringLength; i++)
  84                {
  85                    Char16 instanceNameChar = instanceNameString[i];
  86            
  87                    if (instanceNameChar == '\n')
  88                    {
  89                        keyString.append("\\n");
  90 kumpf 1.57         }
  91                    else if (instanceNameChar == '\r')
  92                    {
  93                        keyString.append("\\r");
  94                    }
  95                    else
  96                    {
  97                        keyString.append(instanceNameChar);
  98                    }
  99                }
 100            
 101                return keyString;
 102            }
 103            
 104            //
 105            // Converts an index file key to a CIMObjectPath object.  Newline and
 106            // carriage return characters are un-escaped.
 107            //
 108            
 109            static CIMObjectPath _convertKeyToInstanceName(const char* key)
 110            {
 111 kumpf 1.57     String keyString(key);
 112            
 113                for (Uint32 i = 0; i < keyString.size() - 1; i++)
 114                {
 115                    if (keyString[i] == '\\')
 116                    {
 117                        if (keyString[i+1] == 'n')
 118                        {
 119                            keyString[i] = '\n';
 120                            keyString.remove(i+1, 1);
 121                        }
 122                        else if (keyString[i+1] == 'r')
 123                        {
 124                            keyString[i] = '\r';
 125                            keyString.remove(i+1, 1);
 126                        }
 127                        else
 128                        {
 129                            i++;
 130                        }
 131                    }
 132 kumpf 1.57     }
 133            
 134                return CIMObjectPath(keyString);
 135            }
 136            
 137 mike  1.17 //
 138 mike  1.20 // Gets one line from the given file.
 139 mike  1.17 //
 140            
 141 mike  1.44 static Boolean _GetLine(fstream& fs, Buffer& x)
 142 mike  1.17 {
 143 marek 1.48     const Uint32 buffersize = 1023 + 1;
 144                Uint32 xcount = 0;
 145                Uint32 gcount = 0;
 146            
 147 mike  1.17     x.clear();
 148 marek 1.48     x.reserveCapacity(buffersize);
 149            
 150                // The general idea is, we will read the stream at buffersize each time.
 151                // if we get exactly buffersize-1, that means we didn't hit a \n
 152 kumpf 1.50     // so we loop again to read more,
 153 marek 1.48     // until we get a buffer that's not completely full.
 154                // That means we hit a \n so we exit the loop.
 155                do
 156                {
 157                    char input[buffersize];
 158            
 159 kumpf 1.50         // This will read up to buffersize-1 char,
 160 marek 1.48         // but stop as soon as it hit \n.
 161                    // This will NOT consume the \n at the end.
 162                    fs.get(input, buffersize, '\n');
 163            
 164 a.dunfey 1.51         gcount = (Uint32)fs.gcount();
 165 marek    1.48         x.append(input, gcount);
 166                       xcount += gcount;
 167 mike     1.17 
 168 marek    1.48     } while (gcount == buffersize-1 && fs.rdstate() != istream::failbit);
 169 mike     1.17 
 170 marek    1.48     // if we read 0 byte in the last call, that's because the read buffer is
 171                   // exactly multiple of the input line.
 172                   // So the 2nd last get() read everything up to the \n and
 173                   // the last get() read 0 char and set the failbit on the
 174                   // stream.  The clear() call will set the stream to ready state.
 175                   if (gcount == 0)
 176                   {
 177                       fs.clear();
 178                   }
 179 mike     1.17 
 180 marek    1.48     if (!fs.eof())
 181                   {
 182 kumpf    1.50         // we need to consume the '\n', because get() doesn't
 183                       char c = 0;
 184                       fs.get(c);
 185 marek    1.48     }
 186 mike     1.17 
 187 marek    1.48     // if xcount is non zero, then we have read something from the buffer.
 188                   return (xcount != 0);
 189 mike     1.20 }
 190               
 191               inline void _SkipWhitespace(char*& p)
 192               {
 193                   while (*p && isspace(*p))
 194                       p++;
 195 mike     1.17 }
 196               
 197               //
 198 mike     1.20 // Get an integer field from the character pointer and advance the
 199               // pointer past the field.
 200 mike     1.17 //
 201               
 202 mike     1.20 Boolean _GetIntField(
 203                   char*& ptr,
 204                   Boolean& error,
 205                   Uint32& value,
 206                   int base)
 207 mike     1.17 {
 208 mike     1.20     char* end = 0;
 209                   value = strtoul(ptr, &end, base);
 210               
 211 mike     1.17     error = false;
 212               
 213                   if (!end)
 214                   {
 215 mike     1.18         error = true;
 216                       return false;
 217 mike     1.17     }
 218               
 219 mike     1.20     _SkipWhitespace(end);
 220 mike     1.17 
 221 mike     1.20     if (*end == '\0')
 222 mike     1.18     {
 223                       error = true;
 224                       return false;
 225                   }
 226 mike     1.17 
 227 mike     1.20     ptr = end;
 228                   return true;
 229               }
 230 mike     1.18 
 231 mike     1.20 //
 232               // Gets the next record in the index file.
 233               //
 234 mike     1.17 
 235 mike     1.20 static Boolean _GetNextRecord(
 236 r.kieninger 1.39     fstream& fs,
 237 mike        1.44     Buffer& line,
 238 mike        1.20     Uint32& freeFlag,
 239                      Uint32& hashCode,
 240                      Uint32& index,
 241                      Uint32& size,
 242                      const char*& instanceName,
 243                      Boolean& error)
 244                  {
 245                      error = false;
 246 mike        1.17 
 247 mike        1.20     //
 248                      // Get next line:
 249                      //
 250                  
 251                      if (!_GetLine(fs, line))
 252 mike        1.18         return false;
 253 mike        1.17 
 254 mike        1.20     //
 255                      // Get the free flag field:
 256                      //
 257                  
 258                      char* end = (char*)line.getData();
 259 mike        1.18 
 260 mike        1.20     if (!_GetIntField(end, error, freeFlag, 10))
 261 kumpf       1.50         return false;
 262 mike        1.17 
 263 mike        1.20     if (freeFlag != 0 && freeFlag != 1)
 264 mike        1.18     {
 265 kumpf       1.50         error = true;
 266                          return false;
 267 mike        1.18     }
 268 mike        1.17 
 269 mike        1.20     //
 270                      // Get the hash-code field:
 271                      //
 272 mike        1.17 
 273 mike        1.20     if (!_GetIntField(end, error, hashCode, 16))
 274 kumpf       1.50         return false;
 275 mike        1.18 
 276 mike        1.20     //
 277                      // Get index field:
 278                      //
 279 mike        1.18 
 280 mike        1.20     if (!_GetIntField(end, error, index, 10))
 281 kumpf       1.50         return false;
 282 mike        1.18 
 283 mike        1.20     //
 284                      // Get size field:
 285                      //
 286 mike        1.17 
 287 mike        1.20     if (!_GetIntField(end, error, size, 10))
 288 kumpf       1.50         return false;
 289 mike        1.17 
 290 mike        1.20     //
 291                      // Get instance name:
 292                      //
 293 mike        1.18 
 294 mike        1.20     instanceName = end;
 295 mike        1.18 
 296 mike        1.17     return true;
 297                  }
 298                  
 299 mike        1.20 ////////////////////////////////////////////////////////////////////////////////
 300 mike        1.17 //
 301 mike        1.20 // InstanceIndexFile:
 302 mike        1.17 //
 303 mike        1.20 ////////////////////////////////////////////////////////////////////////////////
 304 mike        1.17 
 305 mike        1.20 Boolean InstanceIndexFile::lookupEntry(
 306 r.kieninger 1.39     const String& path,
 307 kumpf       1.24     const CIMObjectPath& instanceName,
 308 mike        1.20     Uint32& indexOut,
 309                      Uint32& sizeOut)
 310 mike        1.17 {
 311 kumpf       1.22     PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::lookupEntry()");
 312                  
 313 mike        1.20     fstream fs;
 314 mike        1.17 
 315 mike        1.20     if (!_openFile(path, fs))
 316 kumpf       1.22     {
 317                          PEG_METHOD_EXIT();
 318 kumpf       1.50         return false;
 319 kumpf       1.22     }
 320 mike        1.17 
 321 mike        1.20     Uint32 entryOffset = 0;
 322 mike        1.17 
 323 mike        1.20     Boolean result = _lookupEntry(
 324 kumpf       1.50         fs, instanceName, indexOut, sizeOut, entryOffset);
 325 mike        1.18 
 326 mike        1.20     fs.close();
 327 kumpf       1.22 
 328                      PEG_METHOD_EXIT();
 329 mike        1.20     return result;
 330 mike        1.17 }
 331                  
 332 mike        1.20 Boolean InstanceIndexFile::createEntry(
 333 r.kieninger 1.39     const String& path,
 334 kumpf       1.24     const CIMObjectPath& instanceName,
 335 mike        1.20     Uint32 indexIn,
 336                      Uint32 sizeIn)
 337 mike        1.17 {
 338 kumpf       1.22     PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::createEntry()");
 339                  
 340 mike        1.18     //
 341 mike        1.20     // Open the file:
 342                      //
 343                  
 344                      fstream fs;
 345                  
 346 kumpf       1.22     if (!_openFile(path, fs, true))
 347                      {
 348                          PEG_METHOD_EXIT();
 349 kumpf       1.50         return false;
 350 kumpf       1.22     }
 351 mike        1.20 
 352 mike        1.18     //
 353 mike        1.20     // Return false if entry already exists:
 354 mike        1.18     //
 355                  
 356 mike        1.20     Uint32 tmpIndex;
 357                      Uint32 tmpSize;
 358                      Uint32 tmpEntryOffset;
 359                  
 360                      if (InstanceIndexFile::_lookupEntry(
 361 kumpf       1.50         fs, instanceName, tmpIndex, tmpSize, tmpEntryOffset))
 362 kumpf       1.22     {
 363                          PEG_METHOD_EXIT();
 364 kumpf       1.50         return false;
 365 kumpf       1.22     }
 366 mike        1.20 
 367                      //
 368                      // Append the new entry to the end of the file:
 369                      //
 370 mike        1.18 
 371 mike        1.20     if (!_appendEntry(fs, instanceName, indexIn, sizeIn))
 372 kumpf       1.22     {
 373                          PEG_METHOD_EXIT();
 374 kumpf       1.50         return false;
 375 kumpf       1.22     }
 376 mike        1.17 
 377 mike        1.18     //
 378 mike        1.20     // Close the file:
 379 mike        1.18     //
 380 mike        1.17 
 381 mike        1.20     fs.close();
 382 kumpf       1.22 
 383                      PEG_METHOD_EXIT();
 384 mike        1.20     return true;
 385                  }
 386 mike        1.17 
 387 mike        1.20 Boolean InstanceIndexFile::deleteEntry(
 388 r.kieninger 1.39     const String& path,
 389 kumpf       1.24     const CIMObjectPath& instanceName,
 390 mike        1.20     Uint32& freeCount)
 391                  {
 392 kumpf       1.22     PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::deleteEntry()");
 393                  
 394 mike        1.20     freeCount = 0;
 395 mike        1.17 
 396 mike        1.20     //
 397                      // Open the file:
 398                      //
 399 mike        1.18 
 400 mike        1.20     fstream fs;
 401 mike        1.18 
 402 mike        1.20     if (!_openFile(path, fs))
 403                      {
 404 kumpf       1.22         PEG_METHOD_EXIT();
 405 kumpf       1.50         return false;
 406 mike        1.20     }
 407 mike        1.17 
 408 mike        1.20     //
 409                      // Mark the entry as free:
 410                      //
 411 mike        1.17 
 412 mike        1.20     if (!_markEntryFree(fs, instanceName))
 413                      {
 414 kumpf       1.22         PEG_METHOD_EXIT();
 415 kumpf       1.50         return false;
 416 mike        1.18     }
 417 mike        1.17 
 418 mike        1.18     //
 419 mike        1.20     // Increment the free count:
 420                      //
 421                  
 422                      freeCount = 0;
 423                  
 424                      if (!_incrementFreeCount(fs, freeCount))
 425 kumpf       1.22     {
 426                          PEG_METHOD_EXIT();
 427 kumpf       1.50         return false;
 428 kumpf       1.22     }
 429 mike        1.20 
 430                      //
 431                      // Close the file:
 432 mike        1.18     //
 433 mike        1.17 
 434 mike        1.20     fs.close();
 435 mike        1.17 
 436 kumpf       1.22     PEG_METHOD_EXIT();
 437 mike        1.17     return true;
 438                  }
 439                  
 440 mike        1.20 Boolean InstanceIndexFile::modifyEntry(
 441 r.kieninger 1.39     const String& path,
 442 kumpf       1.24     const CIMObjectPath& instanceName,
 443 mike        1.20     Uint32 indexIn,
 444                      Uint32 sizeIn,
 445                      Uint32& freeCount)
 446                  {
 447 kumpf       1.22     PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::modifyEntry()");
 448                  
 449 mike        1.20     //
 450                      // Open the file:
 451                      //
 452                  
 453                      fstream fs;
 454                  
 455                      if (!_openFile(path, fs))
 456 kumpf       1.22     {
 457                          PEG_METHOD_EXIT();
 458 kumpf       1.50         return false;
 459 kumpf       1.22     }
 460 mike        1.17 
 461 mike        1.18     //
 462 mike        1.20     // Mark the entry as free:
 463 mike        1.18     //
 464 mike        1.17 
 465 mike        1.20     if (!_markEntryFree(fs, instanceName))
 466 kumpf       1.22     {
 467                          PEG_METHOD_EXIT();
 468 kumpf       1.50         return false;
 469 kumpf       1.22     }
 470 mike        1.17 
 471 mike        1.18     //
 472 mike        1.20     // Append new entry:
 473                      //
 474                  
 475                      if (!_appendEntry(fs, instanceName, indexIn, sizeIn))
 476 kumpf       1.22     {
 477                          PEG_METHOD_EXIT();
 478 kumpf       1.50         return false;
 479 kumpf       1.22     }
 480 mike        1.20 
 481 mike        1.18     //
 482 mike        1.20     // Increment the free count:
 483 mike        1.18     //
 484 mike        1.17 
 485 mike        1.20     freeCount = 0;
 486 mike        1.17 
 487 mike        1.20     if (!_incrementFreeCount(fs, freeCount))
 488 kumpf       1.22     {
 489                          PEG_METHOD_EXIT();
 490 kumpf       1.50         return false;
 491 kumpf       1.22     }
 492 mike        1.17 
 493 mike        1.18     //
 494 mike        1.20     // Close the file:
 495 mike        1.18     //
 496 mike        1.17 
 497 mike        1.20     fs.close();
 498 mike        1.17 
 499 kumpf       1.22     PEG_METHOD_EXIT();
 500 mike        1.18     return true;
 501                  }
 502 mike        1.17 
 503 mike        1.20 Boolean InstanceIndexFile::enumerateEntries(
 504                      const String& path,
 505                      Array<Uint32>& freeFlags,
 506                      Array<Uint32>& indices,
 507                      Array<Uint32>& sizes,
 508 kumpf       1.24     Array<CIMObjectPath>& instanceNames,
 509 mike        1.20     Boolean includeFreeEntries)
 510 mike        1.18 {
 511 kumpf       1.22     PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::enumerateEntries()");
 512                  
 513 mike        1.18     //
 514 mike        1.20     // Reserve space for at least COUNT entries:
 515 mike        1.18     //
 516 mike        1.17 
 517 mike        1.20     const Uint32 COUNT = 1024;
 518                  
 519 kumpf       1.27     freeFlags.reserveCapacity(COUNT);
 520                      indices.reserveCapacity(COUNT);
 521                      sizes.reserveCapacity(COUNT);
 522                      instanceNames.reserveCapacity(COUNT);
 523 mike        1.17 
 524 mike        1.18     //
 525 mike        1.20     // Open input file:
 526 mike        1.18     //
 527 mike        1.20 
 528                      fstream fs;
 529                  
 530                      if (!_openFile(path, fs))
 531 kumpf       1.22     {
 532                          // file does not exist, just return with no instanceNames
 533                          PEG_METHOD_EXIT();
 534                          return true;
 535                      }
 536 mike        1.20 
 537                      //
 538                      // Iterate over all instances to build output arrays:
 539 mike        1.18     //
 540 mike        1.20 
 541 mike        1.44     Buffer line;
 542 mike        1.20     Uint32 freeFlag;
 543                      Uint32 hashCode;
 544                      const char* instanceName;
 545                      Uint32 index;
 546                      Uint32 size;
 547                      Boolean error;
 548                  
 549                      while (_GetNextRecord(
 550 kumpf       1.50         fs, line, freeFlag, hashCode, index, size, instanceName, error))
 551 mike        1.17     {
 552 kumpf       1.50         if (!freeFlag || includeFreeEntries)
 553                          {
 554                              freeFlags.append(freeFlag);
 555                              indices.append(index);
 556                              sizes.append(size);
 557 kumpf       1.57             instanceNames.append(_convertKeyToInstanceName(instanceName));
 558 kumpf       1.50         }
 559 mike        1.17     }
 560                  
 561 mike        1.20     if (error)
 562 kumpf       1.22     {
 563                          PEG_METHOD_EXIT();
 564 kumpf       1.50         return false;
 565 kumpf       1.22     }
 566 mike        1.20 
 567 kumpf       1.22     PEG_METHOD_EXIT();
 568 mike        1.20     return true;
 569                  }
 570                  
 571                  Boolean InstanceIndexFile::_incrementFreeCount(
 572                      PEGASUS_STD(fstream)& fs,
 573                      Uint32& freeCount)
 574                  {
 575 kumpf       1.50     PEG_METHOD_ENTER(TRC_REPOSITORY,
 576                          "InstanceIndexFile::_incrementFreeCount()");
 577 kumpf       1.22 
 578 mike        1.20     //
 579                      // Position file pointer to beginning of file (where free count is
 580                      // located) and read the current free count.
 581                      //
 582                  
 583                      fs.seekg(0);
 584                      char hexString[9];
 585                      fs.read(hexString, 8);
 586                  
 587                      if (!fs)
 588 kumpf       1.22     {
 589                          PEG_METHOD_EXIT();
 590 kumpf       1.50         return false;
 591 kumpf       1.22     }
 592 mike        1.17 
 593 mike        1.20     hexString[8] = '\0';
 594 mike        1.17 
 595 mike        1.18     //
 596 mike        1.20     // Convert hex string to integer:
 597 mike        1.18     //
 598 mike        1.20 
 599                      char* end = 0;
 600                      long tmp = strtol(hexString, &end, 16);
 601                  
 602                      if (!end || *end != '\0' || tmp < 0)
 603 kumpf       1.22     {
 604                          PEG_METHOD_EXIT();
 605 kumpf       1.50         return false;
 606 kumpf       1.22     }
 607 mike        1.20 
 608                      freeCount = Uint32(tmp);
 609 mike        1.17 
 610 mike        1.18     //
 611 mike        1.20     // Increment and rewrite the free count:
 612 mike        1.18     //
 613 mike        1.17 
 614 mike        1.20     sprintf(hexString, "%08X", ++freeCount);
 615                      fs.seekg(0);
 616                      fs.write(hexString, 8);
 617 mike        1.17 
 618 kumpf       1.22     PEG_METHOD_EXIT();
 619 mike        1.20     return !!fs;
 620 mike        1.17 }
 621                  
 622 mike        1.20 Boolean InstanceIndexFile::_openFile(
 623 r.kieninger 1.39     const String& path,
 624 kumpf       1.22     PEGASUS_STD(fstream)& fs,
 625                      Boolean create)
 626 mike        1.17 {
 627 kumpf       1.22     PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::_openFile()");
 628                  
 629 mike        1.20     const char ZERO_FREE_COUNT[] = "00000000\n";
 630 mike        1.17 
 631 mike        1.20     //
 632                      // Open the file:
 633                      //
 634 mike        1.17 
 635 kumpf       1.50     if (!FileSystem::openNoCase(
 636                              fs, path, ios::in | ios::out PEGASUS_OR_IOS_BINARY))
 637 mike        1.18     {
 638 kumpf       1.22         if (create)
 639                          {
 640 kumpf       1.50             //
 641                              // File does not exist so create it:
 642                              //
 643 david       1.38             fs.open(path.getCString(), ios::out PEGASUS_OR_IOS_BINARY);
 644 kumpf       1.22 
 645                              if (!fs)
 646                              {
 647                                  PEG_METHOD_EXIT();
 648 kumpf       1.50                 return false;
 649 kumpf       1.22             }
 650                  
 651 kumpf       1.50             fs.write(ZERO_FREE_COUNT, sizeof(ZERO_FREE_COUNT) - 1);
 652                              fs.close();
 653 kumpf       1.22 
 654 kumpf       1.50             //
 655                              // Reopen the file:
 656 kumpf       1.22             //
 657                  
 658 kumpf       1.50             if (!FileSystem::openNoCase(
 659                                      fs, path, ios::in | ios::out PEGASUS_OR_IOS_BINARY))
 660 kumpf       1.22             {
 661                                  PEG_METHOD_EXIT();
 662 kumpf       1.50                 return false;
 663 kumpf       1.22             }
 664                          }
 665                          else
 666                          {
 667                              PEG_METHOD_EXIT();
 668                              return false;
 669                          }
 670 mike        1.20     }
 671 mike        1.18 
 672 mike        1.20     //
 673                      // Position the file pointer beyond the free count:
 674                      //
 675                  
 676                      fs.seekg(sizeof(ZERO_FREE_COUNT) - 1);
 677 mike        1.18 
 678 kumpf       1.22     PEG_METHOD_EXIT();
 679 mike        1.18     return true;
 680                  }
 681                  
 682 mike        1.20 Boolean InstanceIndexFile::_appendEntry(
 683                      PEGASUS_STD(fstream)& fs,
 684 kumpf       1.24     const CIMObjectPath& instanceName,
 685 mike        1.20     Uint32 indexIn,
 686                      Uint32 sizeIn)
 687 mike        1.18 {
 688 kumpf       1.22     PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::_appendEntry()");
 689                  
 690 mike        1.18     //
 691 mike        1.20     // Position the file at the end:
 692                      //
 693                  
 694                      fs.seekg(0, ios::end);
 695                  
 696                      if (!fs)
 697 kumpf       1.22     {
 698                          PEG_METHOD_EXIT();
 699 kumpf       1.50         return false;
 700 kumpf       1.22     }
 701 mike        1.20 
 702                      //
 703                      // Write the entry:
 704 mike        1.18     //
 705 mike        1.20 
 706 mike        1.18     Uint32 targetHashCode = instanceName.makeHashCode();
 707                  
 708                      char buffer[32];
 709                      sprintf(buffer, "%08X", targetHashCode);
 710 mike        1.20 
 711                      fs << "0 " << buffer << ' ' << indexIn << ' ' << sizeIn << ' ';
 712 chuck       1.43 
 713                      // Calling getCString to ensure that utf-8 goes to the file
 714                      // Calling write to ensure no data conversion by the stream
 715 kumpf       1.57     CString name = _convertInstanceNameToKey(instanceName).getCString();
 716 kumpf       1.46     fs.write((const char *)name,
 717                          static_cast<streamsize>(strlen((const char *)name)));
 718 chuck       1.43     fs << endl;
 719 mike        1.20 
 720 kumpf       1.22     PEG_METHOD_EXIT();
 721 mike        1.20     return !!fs;
 722 mike        1.18 }
 723 mike        1.17 
 724 mike        1.20 Boolean InstanceIndexFile::_markEntryFree(
 725                      PEGASUS_STD(fstream)& fs,
 726 kumpf       1.24     const CIMObjectPath& instanceName)
 727 mike        1.18 {
 728 kumpf       1.22     PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::_markEntryFree()");
 729                  
 730 mike        1.18     //
 731 mike        1.20     // First look up the entry:
 732 mike        1.18     //
 733 mike        1.17 
 734 mike        1.20     Uint32 index = 0;
 735                      Uint32 size = 0;
 736                      Uint32 entryOffset = 0;
 737                  
 738                      if (!InstanceIndexFile::_lookupEntry(
 739 kumpf       1.50         fs, instanceName, index, size, entryOffset))
 740 mike        1.18     {
 741 kumpf       1.22         PEG_METHOD_EXIT();
 742 kumpf       1.50         return false;
 743 mike        1.18     }
 744 mike        1.17 
 745 mike        1.18     //
 746 mike        1.20     // Now mark the entry as free (change the first character of the entry
 747                      // from a '0' to a '1').
 748 mike        1.18     //
 749 mike        1.20 
 750                      fs.seekg(entryOffset);
 751                  
 752                      if (!fs)
 753                      {
 754 kumpf       1.22         PEG_METHOD_EXIT();
 755 kumpf       1.50         return false;
 756 mike        1.20     }
 757                  
 758                      fs.write("1", 1);
 759                  
 760 kumpf       1.22     PEG_METHOD_EXIT();
 761 mike        1.20     return !!fs;
 762                  }
 763                  
 764                  Boolean InstanceIndexFile::_lookupEntry(
 765                      PEGASUS_STD(fstream)& fs,
 766 kumpf       1.24     const CIMObjectPath& instanceName,
 767 mike        1.20     Uint32& indexOut,
 768                      Uint32& sizeOut,
 769                      Uint32& entryOffset)
 770                  {
 771 kumpf       1.22     PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::_lookupEntry()");
 772                  
 773 mike        1.20     indexOut = 0;
 774                      sizeOut = 0;
 775                      entryOffset = 0;
 776                  
 777 r.kieninger 1.39     // For for bugzilla 1508. Hostname and namespace are not included
 778                      // in the comparison here. Instances in the repository index file
 779                      // are generally stored without hostname and namespace. If the hostname
 780                      // and namespace of the instance to look up would not match, we would have
 781                      // not gotten here at all.
 782                      CIMObjectPath shortInstanceName = instanceName;
 783                      shortInstanceName.setNameSpace(CIMNamespaceName());
 784                      shortInstanceName.setHost(String::EMPTY);
 785                  
 786                      Uint32 targetHashCode = shortInstanceName.makeHashCode();
 787 mike        1.44     Buffer line;
 788 mike        1.20     Uint32 freeFlag;
 789                      Uint32 hashCode;
 790                      const char* instanceNameTmp;
 791                      Uint32 index;
 792                      Uint32 size;
 793                      Boolean error;
 794 kumpf       1.50 #ifndef PEGASUS_OS_ZOS
 795 a.dunfey    1.51         entryOffset = (Uint32)fs.tellp();
 796 kumpf       1.50 #else
 797 marek       1.32         entryOffset = getOffset(fs.tellp());
 798 kumpf       1.50 #endif
 799 mike        1.20 
 800                      while (_GetNextRecord(
 801 kumpf       1.50         fs, line, freeFlag, hashCode, index, size, instanceNameTmp, error))
 802 mike        1.20     {
 803 r.kieninger 1.39 
 804 chuck       1.37 #ifdef PEGASUS_REPOSITORY_NOT_NORMALIZED
 805                          // See bugzilla 1207.  If the object paths in the repository
 806                          // are not normalized, then the hashcodes cannot be used for
 807                          // the look up (because the hash is based on the normalized path).
 808                          if (freeFlag == 0 &&
 809 kumpf       1.57             _convertKeyToInstanceName(instanceNameTmp) == shortInstanceName)
 810 chuck       1.37 #else
 811 kumpf       1.50         if (freeFlag == 0 &&
 812                              hashCode == targetHashCode &&
 813 kumpf       1.57             _convertKeyToInstanceName(instanceNameTmp) == shortInstanceName)
 814 chuck       1.37 #endif
 815 kumpf       1.50         {
 816                              indexOut = index;
 817                              sizeOut = size;
 818 kumpf       1.22             PEG_METHOD_EXIT();
 819 kumpf       1.50             return true;
 820                          }
 821 mike        1.20 
 822 kumpf       1.50 #ifndef PEGASUS_OS_ZOS
 823 a.dunfey    1.51         entryOffset = (Uint32)fs.tellp();
 824 kumpf       1.50 #else
 825 marek       1.32         entryOffset = getOffset(fs.tellp());
 826 kumpf       1.50 #endif
 827 mike        1.20     }
 828                  
 829                      fs.clear();
 830                  
 831 kumpf       1.22     PEG_METHOD_EXIT();
 832 mike        1.20     return false;
 833                  }
 834                  
 835                  Boolean InstanceIndexFile::compact(
 836                      const String& path)
 837                  {
 838 kumpf       1.22     PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::compact()");
 839                  
 840 mike        1.20     //
 841                      // Open input file:
 842                      //
 843                  
 844                      fstream fs;
 845                  
 846                      if (!_openFile(path, fs))
 847 kumpf       1.22     {
 848                          PEG_METHOD_EXIT();
 849 kumpf       1.50         return false;
 850 kumpf       1.22     }
 851 mike        1.20 
 852                      //
 853                      // Open temporary file (delete it first):
 854                      //
 855                  
 856                      fstream tmpFs;
 857                      String tmpPath = path;
 858 kumpf       1.29     tmpPath.append(".tmp");
 859 mike        1.20 
 860 kumpf       1.22     FileSystem::removeFileNoCase(tmpPath);
 861 mike        1.20 
 862 kumpf       1.22     if (!_openFile(tmpPath, tmpFs, true))
 863                      {
 864                          PEG_METHOD_EXIT();
 865 kumpf       1.50         return false;
 866 kumpf       1.22     }
 867 mike        1.20 
 868                      //
 869                      // Iterate over all instances to build output arrays:
 870                      //
 871 mike        1.17 
 872 mike        1.44     Buffer line;
 873 mike        1.20     Uint32 freeFlag;
 874 mike        1.17     Uint32 hashCode;
 875 mike        1.20     const char* instanceName;
 876                      Uint32 index;
 877 mike        1.18     Uint32 size;
 878 mike        1.17     Boolean error;
 879 mike        1.20     Uint32 adjust = 0;
 880 mike        1.17 
 881 mike        1.20     while (_GetNextRecord(
 882 kumpf       1.50         fs, line, freeFlag, hashCode, index, size, instanceName, error))
 883 mike        1.17     {
 884 kumpf       1.50         //
 885                          // Copy the entry over to the temporary file if it is not free.
 886                          // Otherwise, discard the entry and update subsequent indices to
 887                          // compensate for removal of this block.
 888                          //
 889                  
 890                          if (freeFlag)
 891                          {
 892                              adjust += size;
 893                          }
 894                          else
 895                          {
 896 kumpf       1.57             if (!_appendEntry(tmpFs, _convertKeyToInstanceName(instanceName),
 897 kumpf       1.28                 index - adjust, size))
 898 kumpf       1.50             {
 899                                  error = true;
 900                                  break;
 901                              }
 902                          }
 903 mike        1.17     }
 904                  
 905 mike        1.20     //
 906                      // Close both files:
 907                  
 908                      fs.close();
 909 mateus.baur 1.54 
 910                      FileSystem::syncWithDirectoryUpdates(tmpFs);
 911 mike        1.20     tmpFs.close();
 912                  
 913                      //
 914                      // If an error occurred, remove the temporary file and
 915                      // return false.
 916                      //
 917 mike        1.18 
 918                      if (error)
 919                      {
 920 kumpf       1.50         FileSystem::removeFileNoCase(tmpPath);
 921 kumpf       1.22         PEG_METHOD_EXIT();
 922 kumpf       1.50         return false;
 923 mike        1.20     }
 924                  
 925                      //
 926                      // Replace index file with temporary file:
 927                      //
 928                  
 929 kumpf       1.22     if (!FileSystem::removeFileNoCase(path))
 930                      {
 931                          PEG_METHOD_EXIT();
 932 kumpf       1.50         return false;
 933 kumpf       1.22     }
 934 mike        1.20 
 935                      if (!FileSystem::renameFile(tmpPath, path))
 936 kumpf       1.22     {
 937                          PEG_METHOD_EXIT();
 938 kumpf       1.50         return false;
 939 kumpf       1.22     }
 940 mike        1.20 
 941 kumpf       1.22     PEG_METHOD_EXIT();
 942 mike        1.20     return true;
 943                  }
 944                  
 945                  Boolean InstanceIndexFile::hasNonFreeEntries(const String& path)
 946                  {
 947                      //
 948                      // If file does not exist, there are no instances:
 949                      //
 950                  
 951                      if (!FileSystem::existsNoCase(path))
 952 kumpf       1.50         return false;
 953 mike        1.20 
 954                      //
 955                      // We must iterate all the entries looking for a non-free one:
 956                      //
 957                  
 958                      Array<Uint32> freeFlags;
 959                      Array<Uint32> indices;
 960                      Array<Uint32> sizes;
 961 kumpf       1.24     Array<CIMObjectPath> instanceNames;
 962 mike        1.20 
 963                      if (!InstanceIndexFile::enumerateEntries(
 964 kumpf       1.50         path, freeFlags, indices, sizes, instanceNames, false))
 965 mike        1.20     {
 966 kumpf       1.50         // This won't happen!
 967                          return false;
 968 mike        1.18     }
 969                  
 970 mike        1.20     return freeFlags.size() != 0;
 971                  }
 972                  
 973                  Boolean InstanceIndexFile::beginTransaction(const String& path)
 974                  {
 975 kumpf       1.22     PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::beginTransaction()");
 976                  
 977 chuck       1.45     String rollbackPath = path;
 978                      rollbackPath.append(".rollback");
 979                  
 980                      //
 981                      // If the index file does not exist, then create a rollback file with
 982                      // freecount of 0.
 983                      //
 984                      if (!FileSystem::existsNoCase(path))
 985                      {
 986                          // Make sure the rollback file does not exist.
 987                          if (FileSystem::existsNoCase(rollbackPath))
 988                          {
 989                              if (!FileSystem::removeFileNoCase(rollbackPath))
 990                              {
 991                                  PEG_METHOD_EXIT();
 992                                  return false;
 993                              }
 994                          }
 995                  
 996 kumpf       1.50         // Create the rollback file, and write the freecount of 0.
 997 chuck       1.45         fstream fs;
 998                          if (!_openFile(rollbackPath, fs, true))
 999                          {
1000                              // Make sure no rollback file is left over.
1001                              FileSystem::removeFileNoCase(rollbackPath);
1002                  
1003                              PEG_METHOD_EXIT();
1004 kumpf       1.50                 return false;
1005 chuck       1.45         }
1006                          fs.close();
1007                  
1008                          PEG_METHOD_EXIT();
1009                          return true;
1010                      }
1011                  
1012 mike        1.20     //
1013                      // Create a rollback file which is a copy of the index file. The
1014                      // new filename is formed by appending ".rollback" to the name of
1015 kumpf       1.49     // the index file.  The rollback file, if it exists, is considered
1016                      // the "master" copy of the data.  To ensure its completeness, the
1017                      // index file is renamed to the rollback file and the data is then
1018                      // copied back to the index file.
1019 mike        1.20     //
1020 kumpf       1.49 
1021                      if (!FileSystem::renameFileNoCase(path, rollbackPath))
1022                      {
1023                          PEG_METHOD_EXIT();
1024 kumpf       1.50         return false;
1025 kumpf       1.49     }
1026                  
1027                      if (!FileSystem::copyFile(rollbackPath, path))
1028 kumpf       1.22     {
1029 kumpf       1.49         // Try to restore the initial state
1030                          FileSystem::removeFileNoCase(path);
1031                          FileSystem::renameFileNoCase(rollbackPath, path);
1032 chuck       1.45 
1033 kumpf       1.22         PEG_METHOD_EXIT();
1034 kumpf       1.50         return false;
1035 kumpf       1.22     }
1036 mike        1.20 
1037 kumpf       1.22     PEG_METHOD_EXIT();
1038 mike        1.20     return true;
1039                  }
1040                  
1041                  Boolean InstanceIndexFile::rollbackTransaction(const String& path)
1042                  {
1043 kumpf       1.50     PEG_METHOD_ENTER(TRC_REPOSITORY,
1044                          "InstanceIndexFile::rollbackTransaction()");
1045 kumpf       1.22 
1046 mike        1.20     //
1047                      // If the rollback file does not exist, then everything is fine (nothing
1048                      // to roll back).
1049                      //
1050                  
1051 kumpf       1.23     if (!FileSystem::existsNoCase(path + ".rollback"))
1052 kumpf       1.22     {
1053                          PEG_METHOD_EXIT();
1054 kumpf       1.50         return true;
1055 kumpf       1.22     }
1056 mike        1.20 
1057                      //
1058                      // To roll back, simply delete the index file and rename
1059                      // the rollback file over it.
1060                      //
1061                  
1062 kumpf       1.25     if (FileSystem::existsNoCase(path))
1063 kumpf       1.22     {
1064 kumpf       1.25         if (!FileSystem::removeFileNoCase(path))
1065                          {
1066                              PEG_METHOD_EXIT();
1067 kumpf       1.50             return false;
1068 kumpf       1.25         }
1069 kumpf       1.22     }
1070 mike        1.20 
1071 kumpf       1.22     PEG_METHOD_EXIT();
1072 kumpf       1.23     return FileSystem::renameFileNoCase(path + ".rollback", path);
1073 mike        1.20 }
1074                  
1075                  Boolean InstanceIndexFile::commitTransaction(const String& path)
1076                  {
1077 kumpf       1.22     PEG_METHOD_ENTER(TRC_REPOSITORY, "InstanceIndexFile::commitTransaction()");
1078                  
1079 mike        1.20     //
1080                      // To commit, simply remove the rollback file:
1081                      //
1082                  
1083                      String rollbackPath = path;
1084 kumpf       1.29     rollbackPath.append(".rollback");
1085 mike        1.20 
1086 kumpf       1.22     PEG_METHOD_EXIT();
1087 mike        1.20     return FileSystem::removeFileNoCase(rollbackPath);
1088 mike        1.17 }
1089                  
1090                  PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2