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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2