//%2006//////////////////////////////////////////////////////////////////////// // // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems. // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.; // IBM Corp.; EMC Corporation, The Open Group. // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.; // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group. // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.; // EMC Corporation; VERITAS Software Corporation; The Open Group. // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.; // EMC Corporation; Symantec Corporation; The Open Group. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // //============================================================================== // //%///////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "DefaultRepository.h" #include "RepositoryDeclContext.h" #include "InstanceIndexFile.h" #include "InstanceDataFile.h" #include "AssocInstTable.h" #include "AssocClassTable.h" #include "ObjectCache.h" #include "Filtering.h" #ifdef PEGASUS_ENABLE_COMPRESSED_REPOSITORY // #define win32 # include # include #endif #if 0 #undef PEG_METHOD_ENTER #undef PEG_METHOD_EXIT #define PEG_METHOD_ENTER(x,y) cout<<"--- Enter: "< _classCache(PEGASUS_CLASS_CACHE_SIZE); #endif /* PEGASUS_USE_CLASS_CACHE */ static ObjectCache _qualifierCache(PEGASUS_QUALIFIER_CACHE_SIZE); //////////////////////////////////////////////////////////////////////////////// // // _LoadFileToMemory() PEP214 // // The gzxxxx functions read both compresed and non-compresed files. // // There is no conditional flag on reading of files since gzread() // (from zlib) is capable of reading compressed and non-compressed // files (so it contains the logic that examines the header // and magic number). Everything will work properly if the repository // has some compressed and some non-compressed files. // // //////////////////////////////////////////////////////////////////////////////// void _LoadFileToMemory(Buffer& data, const String& path) { #ifdef PEGASUS_ENABLE_COMPRESSED_REPOSITORY Uint32 fileSize; if (!FileSystem::getFileSize(path, fileSize)) throw CannotOpenFile(path); gzFile fp = gzopen(path.getCString(), "rb"); if (fp == NULL) throw CannotOpenFile(path); data.reserveCapacity(fileSize); char buffer[4096]; int n; while ((n = gzread(fp, buffer, sizeof(buffer))) > 0) data.append(buffer, n); gzclose(fp); #else FileSystem::loadFileToMemory(data, path); #endif /* PEGASUS_ENABLE_COMPRESSED_REPOSITORY */ } //////////////////////////////////////////////////////////////////////////////// // // _LoadObject() // // Loads objects (classes and qualifiers) from disk to // memory objects. // //////////////////////////////////////////////////////////////////////////////// template void _LoadObject( const String& path, Object& object, ObjectStreamer* streamer) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::_LoadObject"); // Get the real path of the file: String realPath; if (!FileSystem::existsNoCase(path, realPath)) { PEG_TRACE_STRING(TRC_REPOSITORY, Tracer::LEVEL4, path + " does not exist."); PEG_METHOD_EXIT(); throw CannotOpenFile(path); } PEG_TRACE_STRING(TRC_REPOSITORY, Tracer::LEVEL4, "realpath = " + realPath); // Load file into memory: Buffer data; _LoadFileToMemory(data, realPath); streamer->decode(data, 0, object); PEG_METHOD_EXIT(); } //////////////////////////////////////////////////////////////////////////////// // // _SaveObject() // // Saves objects (classes and qualifiers) from memory to // disk files. // //////////////////////////////////////////////////////////////////////////////// void _SaveObject( const String& path, Buffer& objectXml, ObjectStreamer* streamer) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::_SaveObject"); // cout << "SAVE[" << path << "]" << endl; #ifdef PEGASUS_ENABLE_COMPRESSED_REPOSITORY if (compressMode) // PEP214 { PEGASUS_STD(ostringstream) os; streamer->write(os, objectXml); string str = os.str(); gzFile fp = gzopen(path.getCString(), "wb"); if (fp == NULL) throw CannotOpenFile(path); const char* ptr = str.data(); size_t rem = str.size(); int n; while (rem > 0 && (n = gzwrite(fp, (char*)ptr, rem)) > 0) { ptr += n; rem -= n; } gzclose(fp); } else #endif /* PEGASUS_ENABLE_COMPRESSED_REPOSITORY */ { PEGASUS_STD(ofstream) os(path.getCString() PEGASUS_IOS_BINARY); if (!os) { PEG_METHOD_EXIT(); throw CannotOpenFile(path); } streamer->write(os, objectXml); } PEG_METHOD_EXIT(); } //////////////////////////////////////////////////////////////////////////////// // // _beginInstanceTransaction() // // Creates rollback files to allow an incomplete transaction to be voided. // //////////////////////////////////////////////////////////////////////////////// void _beginInstanceTransaction( const String& indexFilePath, const String& dataFilePath) { PEG_METHOD_ENTER(TRC_REPOSITORY, "_beginInstanceTransaction"); // // Begin the transaction (an incomplete transaction will cause // a rollback the next time an instance-oriented routine is invoked). // if (!InstanceIndexFile::beginTransaction(indexFilePath)) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms("Repository.DefaultRepository.BEGIN_FAILED", "begin failed")); } if (!InstanceDataFile::beginTransaction(dataFilePath)) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms("Repository.DefaultRepository.BEGIN_FAILED", "begin failed")); } PEG_METHOD_EXIT(); } //////////////////////////////////////////////////////////////////////////////// // // _commitInstanceTransaction() // // Removes the rollback files to complete the transaction. // //////////////////////////////////////////////////////////////////////////////// void _commitInstanceTransaction( const String& indexFilePath, const String& dataFilePath) { PEG_METHOD_ENTER(TRC_REPOSITORY, "_commitInstanceTransaction"); // // Commit the transaction by removing the rollback files. // if (!InstanceIndexFile::commitTransaction(indexFilePath)) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms("Repository.DefaultRepository.COMMIT_FAILED", "commit failed")); } if (!InstanceDataFile::commitTransaction(dataFilePath)) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms("Repository.DefaultRepository.COMMIT_FAILED", "commit failed")); } PEG_METHOD_EXIT(); } //////////////////////////////////////////////////////////////////////////////// // // _rollbackInstanceTransaction() // // Restores instance index and data files to void an incomplete operation. // If there are no rollback files, this method has no effect. // //////////////////////////////////////////////////////////////////////////////// static String _dirName(const String& path) { Uint32 n = path.size(); for (Uint32 i = n; i != 0; ) { if (path[--i] == '/') return path.subString(0, i); } return String("."); } void _rollbackInstanceTransaction( const String& indexFilePath, const String& dataFilePath) { PEG_METHOD_ENTER(TRC_REPOSITORY, "_rollbackInstanceTransaction"); // Avoid rollback logic if directory has no .rollback files. String path = _dirName(indexFilePath); Array rollbackFiles; if (FileSystem::glob(path, "*.rollback", rollbackFiles)) { if (rollbackFiles.size() == 0) return; } // Proceed to rollback logic. if (!InstanceIndexFile::rollbackTransaction(indexFilePath)) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms("Repository.DefaultRepository.ROLLBACK_FAILED", "rollback failed")); } if (!InstanceDataFile::rollbackTransaction(dataFilePath)) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms( "Repository.DefaultRepository.ROLLBACK_FAILED", "rollback failed")); } PEG_METHOD_EXIT(); } //////////////////////////////////////////////////////////////////////////////// // // InstanceTransactionHandler // // This class is used to manage a repository instance transaction. The // transaction is started when the class is instantiated, committed when // the complete() method is called, and rolled back if the destructor is // called without a prior call to complete(). // // The appropriate repository write locks must be owned while an // InstanceTransactionHandler instance exists. // //////////////////////////////////////////////////////////////////////////////// class InstanceTransactionHandler { public: InstanceTransactionHandler( const String& indexFilePath, const String& dataFilePath) : _indexFilePath(indexFilePath), _dataFilePath(dataFilePath), _isComplete(false) { _rollbackInstanceTransaction(_indexFilePath, _dataFilePath); _beginInstanceTransaction(_indexFilePath, _dataFilePath); } ~InstanceTransactionHandler() { if (!_isComplete) { _rollbackInstanceTransaction(_indexFilePath, _dataFilePath); } } void complete() { _commitInstanceTransaction(_indexFilePath, _dataFilePath); _isComplete = true; } private: String _indexFilePath; String _dataFilePath; Boolean _isComplete; }; //////////////////////////////////////////////////////////////////////////////// // // DefaultRepository::_rollbackIncompleteTransactions() // // Searches for incomplete instance transactions for all classes in all // namespaces. Restores instance index and data files to void an // incomplete operation. If no incomplete instance transactions are // outstanding, this method has no effect. // //////////////////////////////////////////////////////////////////////////////// static Boolean _containsNoCase(const Array& array, const String& str) { for (Uint32 i = 0; i < array.size(); i++) { if (String::equalNoCase(array[i], str)) return true; } return false; } void DefaultRepository::_rollbackIncompleteTransactions() { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::_rollbackIncompleteTransactions"); WriteLock wlock(_lock); AutoFileLock fileLock(_lockFile); Array namespaceNames; _nameSpaceManager.getNameSpaceNames(namespaceNames); for (Uint32 i = 0; i < namespaceNames.size(); i++) { // Form a list of .rollback files. Array rollbackFiles; FileSystem::glob( _nameSpaceManager.getInstanceDirRoot(namespaceNames[i]), "*.rollback", rollbackFiles); // Don't bother doing rollback if there are no rollback files. // The algorithm below is expensive. if (rollbackFiles.size() == 0) continue; Array classNames; _nameSpaceManager.getSubClassNames( namespaceNames[i], CIMName(), true, classNames); for (Uint32 j = 0; j < classNames.size(); j++) { // // Get paths of index and data files: // String indexFilePath = _getInstanceIndexFilePath( namespaceNames[i], classNames[j]); String dataFilePath = _getInstanceDataFilePath( namespaceNames[i], classNames[j]); // Only perform rollback processing if there is a rollback file // for either the data or index file. if (_containsNoCase(rollbackFiles, dataFilePath + ".rollback") || _containsNoCase(rollbackFiles, indexFilePath + ".rollback")) { // // Attempt rollback (if there are no rollback files, this will // have no effect). This code is here to rollback uncommitted // changes left over from last time an instance-oriented // function // was called. // _rollbackInstanceTransaction(indexFilePath, dataFilePath); } } } PEG_METHOD_EXIT(); } //////////////////////////////////////////////////////////////////////////////// // // DefaultRepository // // The following are not implemented: // // DefaultRepository::execQuery() // DefaultRepository::invokeMethod() // // Note that invokeMethod() will not never implemented since it is not // meaningful for a repository. // //////////////////////////////////////////////////////////////////////////////// DefaultRepository::DefaultRepository( const String& repositoryRoot, Uint32 mode) : Repository(repositoryRoot, mode), _nameSpaceManager(repositoryRoot), _lock(), _resolveInstance(true) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::DefaultRepository"); Boolean binaryMode = mode & DefaultRepository::MODE_BIN; if (mode == DefaultRepository::MODE_DEFAULT) { binaryMode = ConfigManager::parseBooleanValue( ConfigManager::getInstance()->getCurrentValue( "enableBinaryRepository")); } #ifdef PEGASUS_ENABLE_COMPRESSED_REPOSITORY // PEP214 // FUTURE?? - compressMode = mode & DefaultRepository::MODE_COMPRESSED; compressMode=1; char* s = getenv("PEGASUS_ENABLE_COMPRESSED_REPOSITORY"); if (s && (strcmp(s, "build_non_compressed") == 0)) { compressMode =0; #ifdef TEST_OUTPUT cout << "In Compress mode: build_non_compresed found" << endl; #endif /* TEST_OUTPUT */ } #endif /* PEGASUS_ENABLE_COMPRESSED_REPOSITORY */ #ifdef TEST_OUTPUT cout << "repositoryRoot = " << repositoryRoot << endl; cout << "DefaultRepository: binaryMode=" << binaryMode << ", mode=" << mode << endl; cout << "DefaultRepository: compressMode= " << compressMode << endl; #endif /* TEST_OUTPUT */ if (binaryMode>0) { // BUILD BINARY streamer = new AutoStreamer(new BinaryStreamer(), BINREP_MARKER); ((AutoStreamer*)streamer)->addReader(new XmlStreamer(), 0); } else { // BUILD XML streamer = new AutoStreamer(new XmlStreamer(),0xff); ((AutoStreamer*)streamer)->addReader( new BinaryStreamer(), BINREP_MARKER); ((AutoStreamer*)streamer)->addReader(new XmlStreamer(), 0); } _context = new RepositoryDeclContext(this); _isDefaultInstanceProvider = ConfigManager::parseBooleanValue( ConfigManager::getInstance()->getCurrentValue( "repositoryIsDefaultInstanceProvider")); _lockFile = ConfigManager::getInstance()->getHomedPath( PEGASUS_REPOSITORY_LOCK_FILE).getCString(); _rollbackIncompleteTransactions(); PEG_METHOD_EXIT(); } DefaultRepository::~DefaultRepository() { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::~DefaultRepository"); delete streamer; delete _context; AssocClassTable::removeCaches(); PEG_METHOD_EXIT(); } String _toString(Boolean x) { return(x ? "true" : "false"); } CIMClass DefaultRepository::getClass( bool lock, const CIMNamespaceName& nameSpace, const CIMName& className, Boolean localOnly, Boolean includeQualifiers, Boolean includeClassOrigin, const CIMPropertyList& propertyList) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::getClass"); ConditionalReadLock rlock(_lock, lock); PEG_TRACE_STRING(TRC_REPOSITORY, Tracer::LEVEL4, "nameSpace= " + nameSpace.getString() + ", className= " + className.getString() + ", localOnly= " + _toString(localOnly) + ", includeQualifiers= " + _toString(includeQualifiers) + ", includeClassOrigin= " + _toString(includeClassOrigin)); String classFilePath; classFilePath = _nameSpaceManager.getClassFilePath( nameSpace, className, NameSpaceRead); CIMClass cimClass; try { #ifdef PEGASUS_USE_CLASS_CACHE // Check the cache first: if (!_classCache.get(classFilePath, cimClass)) { // Not in cache so load from disk: _LoadObject(classFilePath, cimClass, streamer); // Put in cache: _classCache.put(classFilePath, cimClass); } #else /* PEGASUS_USE_CLASS_CACHE */ _LoadObject(classFilePath, cimClass, streamer); #endif /* PEGASUS_USE_CLASS_CACHE */ } catch (Exception&) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, className.getString()); } // Remove properties based on propertylist and localOnly flag (Bug 565) Boolean propertyListNull = propertyList.isNull(); Filtering::filterClass( cimClass, localOnly, includeQualifiers, includeClassOrigin, propertyList); PEG_METHOD_EXIT(); return cimClass; } Boolean DefaultRepository::_checkInstanceAlreadyExists( const CIMNamespaceName& nameSpace, const CIMObjectPath& instanceName) const { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::_checkInstanceAlreadyExists"); // // Get the names of all superclasses and subclasses of this class // Array classNames; CIMName className = instanceName.getClassName(); classNames.append(className); _nameSpaceManager.getSubClassNames(nameSpace, className, true, classNames); _nameSpaceManager.getSuperClassNames(nameSpace, className, classNames); // // Search for an instance with the specified key values // for (Uint32 i = 0; i < classNames.size(); i++) { CIMObjectPath tmpInstanceName = instanceName; tmpInstanceName.setClassName(classNames[i]); String path = _getInstanceIndexFilePath(nameSpace, classNames[i]); Uint32 index; Uint32 size; if (InstanceIndexFile::lookupEntry(path, tmpInstanceName, index, size)) { PEG_METHOD_EXIT(); return true; } } PEG_METHOD_EXIT(); return false; } CIMInstance DefaultRepository::getInstance( bool lock, const CIMNamespaceName& nameSpace, const CIMObjectPath& instanceName, Boolean localOnly, Boolean includeQualifiers, Boolean includeClassOrigin, const CIMPropertyList& propertyList) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::getInstance"); ConditionalReadLock rlock(_lock, lock); // // Validate namespace // if ((!instanceName.getNameSpace().isNull()) && (!instanceName.getNameSpace().equal(nameSpace))) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, instanceName.toString()); } if (!_nameSpaceManager.classExists(nameSpace, instanceName.getClassName())) { throw PEGASUS_CIM_EXCEPTION( CIM_ERR_INVALID_CLASS, instanceName.getClassName().getString()); } // // Get paths of index and data files: // String indexFilePath = _getInstanceIndexFilePath( nameSpace, instanceName.getClassName()); String dataFilePath = _getInstanceDataFilePath( nameSpace, instanceName.getClassName()); // // Get the index for this instance: // Uint32 index; Uint32 size; if (!InstanceIndexFile::lookupEntry( indexFilePath, instanceName, index, size)) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, instanceName.toString()); } // // Load the instance from file: // CIMInstance cimInstance; if (!_loadInstance(dataFilePath, cimInstance, index, size)) { PEG_METHOD_EXIT(); throw CannotOpenFile(dataFilePath); } // // Resolve the instance (if requested): // if (_resolveInstance) { CIMConstClass cimClass; Resolver::resolveInstance (cimInstance, _context, nameSpace, cimClass, true); } Filtering::filterInstance( cimInstance, localOnly, includeQualifiers, includeClassOrigin, propertyList); PEG_METHOD_EXIT(); return cimInstance; } void DefaultRepository::deleteClass( bool lock, const CIMNamespaceName& nameSpace, const CIMName& className) { PEG_METHOD_ENTER(TRC_REPOSITORY,"DefaultRepository::deleteClass"); ConditionalWriteLock wlock(_lock, lock); AutoFileLock fileLock(_lockFile); // // Get the class and check to see if it is an association class: // CIMClass cimClass = getClass( false, nameSpace, className, false, true, false, CIMPropertyList()); Boolean isAssociation = cimClass.isAssociation(); // // Delete the class. The NameSpaceManager::deleteClass() method throws // an exception if the class has subclasses. // #ifdef PEGASUS_USE_CLASS_CACHE _classCache.evict(_nameSpaceManager.getClassFilePath( nameSpace, className, NameSpaceRead)); #endif /* PEGASUS_USE_CLASS_CACHE */ _nameSpaceManager.deleteClass(nameSpace, className); // // Remove associations: // if (isAssociation) { Array assocFileName = _nameSpaceManager.getAssocClassPath(nameSpace,NameSpaceDelete); if (FileSystem::exists(assocFileName[0])) AssocClassTable::deleteAssociation(assocFileName[0], className); } PEG_METHOD_EXIT(); } void _CompactInstanceRepository( const String& indexFilePath, const String& dataFilePath) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::_CompactInstanceRepository"); // // Compact the data file first: // Array freeFlags; Array indices; Array sizes; Array instanceNames; if (!InstanceIndexFile::enumerateEntries( indexFilePath, freeFlags, indices, sizes, instanceNames, true)) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms( "Repository.DefaultRepository.INDEX_ENUM_ENTRIES_FAILED", "Failed to obtain the entries from the Repository Instance" " Index file.")); } if (!InstanceDataFile::compact(dataFilePath, freeFlags, indices, sizes)) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms( "Repository.DefaultRepository.COMPACT_FAILED", "Failed to compact the Repository Instance Data file.")); } // // Now compact the index file: // if (!InstanceIndexFile::compact(indexFilePath)) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms( "Repository.DefaultRepository.INDEX_COMPACT_FAILED", "Failed to compact the Repository Instance Index file.")); } PEG_METHOD_EXIT(); } void DefaultRepository::deleteInstance( bool lock, const CIMNamespaceName& nameSpace, const CIMObjectPath& instanceName) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::deleteInstance"); // // Validate namespace // if ((!instanceName.getNameSpace().isNull()) && (!instanceName.getNameSpace().equal(nameSpace))) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION( CIM_ERR_NOT_FOUND, instanceName.toString()); } ConditionalWriteLock wlock(_lock, lock); AutoFileLock fileLock(_lockFile); String errMessage; // // Get paths of index and data files: // String indexFilePath = _getInstanceIndexFilePath( nameSpace, instanceName.getClassName()); String dataFilePath = _getInstanceDataFilePath( nameSpace, instanceName.getClassName()); // // Perform the operation in a transaction scope to enable rollback on // failure. // InstanceTransactionHandler transaction(indexFilePath, dataFilePath); // // Lookup instance from the index file (raise error if not found). // Uint32 index; Uint32 size; if (!InstanceIndexFile::lookupEntry( indexFilePath, instanceName, index, size)) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, instanceName.toString()); } // // Remove entry from index file. // Uint32 freeCount; if (!InstanceIndexFile::deleteEntry(indexFilePath, instanceName, freeCount)) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms( "Repository.DefaultRepository.FAILED_TO_DELETE_INSTANCE", "Failed to delete instance: $0", instanceName.toString())); } transaction.complete(); // // Compact the index and data files if the free count max was // reached. // if (freeCount == _MAX_FREE_COUNT) _CompactInstanceRepository(indexFilePath, dataFilePath); // // Delete from assocation table (if an assocation). // String assocFileName = _nameSpaceManager.getAssocInstPath(nameSpace); if (FileSystem::exists(assocFileName)) AssocInstTable::deleteAssociation(assocFileName, instanceName); PEG_METHOD_EXIT(); } void DefaultRepository::_createAssocClassEntries( const CIMNamespaceName& nameSpace, const CIMConstClass& assocClass) { PEG_METHOD_ENTER( TRC_REPOSITORY, "DefaultRepository::_createAssocClassEntries"); // Open input file: Array assocFileName = _nameSpaceManager.getAssocClassPath(nameSpace,NameSpaceWrite); ofstream os; if (!OpenAppend(os, assocFileName[0])) { PEG_METHOD_EXIT(); throw CannotOpenFile(assocFileName[0]); } // Get the association's class name: CIMName assocClassName = assocClass.getClassName(); // For each property: Uint32 n = assocClass.getPropertyCount(); for (Uint32 i = 0; i < n; i++) { CIMConstProperty fromProp = assocClass.getProperty(i); if (fromProp.getType() == CIMTYPE_REFERENCE) { for (Uint32 j = 0; j < n; j++) { CIMConstProperty toProp = assocClass.getProperty(j); if (toProp.getType() == CIMTYPE_REFERENCE && (!fromProp.getName().equal (toProp.getName()))) { CIMName fromClassName = fromProp.getReferenceClassName(); CIMName fromPropertyName = fromProp.getName(); CIMName toClassName = toProp.getReferenceClassName(); CIMName toPropertyName = toProp.getName(); AssocClassTable::append( os, assocFileName[0], assocClassName, fromClassName, fromPropertyName, toClassName, toPropertyName); } } } } PEG_METHOD_EXIT(); } void DefaultRepository::createClass( bool lock, const CIMNamespaceName& nameSpace, const CIMClass& newClass, const ContentLanguageList& contentLangs) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::createClass"); ConditionalWriteLock wlock(_lock, lock); AutoFileLock fileLock(_lockFile); // -- Resolve the class: CIMClass cimClass(newClass); Resolver::resolveClass (cimClass, _context, nameSpace); // -- If an association, populate associations file: if (cimClass.isAssociation()) _createAssocClassEntries(nameSpace, cimClass); // -- Create namespace manager entry: String classFilePath; _nameSpaceManager.createClass(nameSpace, cimClass.getClassName(), cimClass.getSuperClassName(), classFilePath); // -- Create the class file: Buffer classXml; streamer->encode(classXml, cimClass); //XmlWriter::appendClassElement(classXml, cimClass); _SaveObject(classFilePath, classXml,streamer); PEG_METHOD_EXIT(); } /*------------------------------------------------------------------------------ This routine does the following: 1. Creates two entries in the association file for each relationship formed by this new assocation instance. A binary association (one with two references) ties two instances together. Suppose there are two instances: I1 and I2. Then two entries are created: I2 -> I1 I1 -> I2 For a ternary relationship, six entries will be created. Suppose there are three instances: I1, I2, and I3: I1 -> I2 I1 -> I3 I2 -> I1 I2 -> I3 I3 -> I1 I3 -> I2 So for an N-ary relationship, there will be 2*N entries created. 2. Verifies that the association instance refers to real objects. (note that an association reference may refer to either an instance or a class). Throws an exception if one of the references does not refer to a valid object. ------------------------------------------------------------------------------*/ void DefaultRepository::_createAssocInstEntries( const CIMNamespaceName& nameSpace, const CIMConstClass& cimClass, const CIMInstance& cimInstance, const CIMObjectPath& instanceName) { PEG_METHOD_ENTER( TRC_REPOSITORY, "DefaultRepository::_createAssocInstEntries"); // Open input file: String assocFileName = _nameSpaceManager.getAssocInstPath(nameSpace); ofstream os; if (!OpenAppend(os, assocFileName)) { PEG_METHOD_EXIT(); throw CannotOpenFile(assocFileName); } // Get the association's instance name and class name: String assocInstanceName = instanceName.toString(); CIMName assocClassName = instanceName.getClassName(); // For each property: for (Uint32 i = 0, n = cimInstance.getPropertyCount(); i < n; i++) { CIMConstProperty fromProp = cimInstance.getProperty(i); // If a reference property: if (fromProp.getType() == CIMTYPE_REFERENCE) { // For each property: for (Uint32 j = 0, n = cimInstance.getPropertyCount(); j < n; j++) { CIMConstProperty toProp = cimInstance.getProperty(j); // If a reference property and not the same property: if (toProp.getType() == CIMTYPE_REFERENCE && (!fromProp.getName().equal (toProp.getName()))) { CIMObjectPath fromRef; fromProp.getValue().get(fromRef); CIMObjectPath toRef; toProp.getValue().get(toRef); // Fix for bugzilla 667: // Strip off the hostname if it is the same as the // local host if ((fromRef.getHost() != String::EMPTY) && (System::isLocalHost(fromRef.getHost()))) { PEG_TRACE_CSTRING(TRC_REPOSITORY, Tracer::LEVEL4, "_createAssocInstEntries() - Stripping off local " "hostName from fromRef"); fromRef.setHost(String::EMPTY); } // Strip off the namespace when it is the same as the // one this instance is created in. if ((fromRef.getHost() == String::EMPTY) && (fromRef.getNameSpace() == nameSpace)) { PEG_TRACE_CSTRING(TRC_REPOSITORY, Tracer::LEVEL4, "_createAssocInstEntries() - Stripping off " "local nameSpace from fromRef"); fromRef.setNameSpace(CIMNamespaceName()); } // Strip off the hostname if it is the same as the // local host if ((toRef.getHost() != String::EMPTY) && (System::isLocalHost(toRef.getHost()))) { PEG_TRACE_CSTRING(TRC_REPOSITORY, Tracer::LEVEL4, "_createAssocInstEntries() - Stripping off " "local hostName from toRef"); toRef.setHost(String::EMPTY); } // Strip off the namespace when it is the same as the // one this instance is created in. if ((toRef.getHost() == String::EMPTY) && (toRef.getNameSpace() == nameSpace)) { PEG_TRACE_CSTRING(TRC_REPOSITORY, Tracer::LEVEL4, "_createAssocInstEntries() - Stripping off " "local nameSpace from toRef"); toRef.setNameSpace(CIMNamespaceName()); } String fromObjectName = fromRef.toString(); CIMName fromClassName = fromRef.getClassName(); CIMName fromPropertyName = fromProp.getName(); String toObjectName = toRef.toString(); CIMName toClassName = toRef.getClassName(); CIMName toPropertyName = toProp.getName(); AssocInstTable::append( os, assocInstanceName, assocClassName, fromObjectName, fromClassName, fromPropertyName, toObjectName, toClassName, toPropertyName); } } } } PEG_METHOD_EXIT(); } CIMObjectPath DefaultRepository::createInstance( bool lock, const CIMNamespaceName& nameSpace, const CIMInstance& newInstance, const ContentLanguageList& contentLangs) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::createInstance"); ConditionalWriteLock wlock(_lock, lock); AutoFileLock fileLock(_lockFile); String errMessage; // // Resolve the instance. Looks up class and fills out properties but // not the qualifiers. // CIMInstance cimInstance(newInstance); CIMConstClass cimClass; Resolver::resolveInstance (cimInstance, _context, nameSpace, cimClass, false); CIMObjectPath instanceName = cimInstance.buildPath(cimClass); // // Make sure the class has keys (otherwise it will be impossible to // create the instance). // if (!cimClass.hasKeys()) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms("Repository.DefaultRepository.CLASS_HAS_NO_KEYS", "class has no keys: $0", cimClass.getClassName().getString())); } // // Be sure instance does not already exist: // if (_checkInstanceAlreadyExists(nameSpace, instanceName)) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION(CIM_ERR_ALREADY_EXISTS, instanceName.toString()); } // // Create association entries if an association instance. // if (cimClass.isAssociation()) _createAssocInstEntries(nameSpace, cimClass, cimInstance, instanceName); // // Get paths to data and index files: // String indexFilePath = _getInstanceIndexFilePath( nameSpace, newInstance.getClassName()); String dataFilePath = _getInstanceDataFilePath( nameSpace, newInstance.getClassName()); // // Perform the operation in a transaction scope to enable rollback on // failure. // InstanceTransactionHandler transaction(indexFilePath, dataFilePath); // // Save instance to file: // Uint32 index; Uint32 size; { Buffer data; streamer->encode(data, cimInstance); size = data.size(); if (!InstanceDataFile::appendInstance(dataFilePath, data, index)) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms( "Repository.DefaultRepository.FAILED_TO_CREATE_INSTANCE", "Failed to create instance: $0", instanceName.toString())); } } // // Create entry in index file: // if (!InstanceIndexFile::createEntry( indexFilePath, instanceName, index, size)) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms( "Repository.DefaultRepository.FAILED_TO_CREATE_INSTANCE", "Failed to create instance: $0", instanceName.toString())); } transaction.complete(); Resolver::resolveInstance (cimInstance, _context, nameSpace, cimClass, true); PEG_METHOD_EXIT(); return instanceName; } void DefaultRepository::modifyClass( bool lock, const CIMNamespaceName& nameSpace, const CIMClass& modifiedClass, const ContentLanguageList& contentLangs) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::modifyClass"); ConditionalWriteLock wlock(_lock, lock); AutoFileLock fileLock(_lockFile); // // Resolve the class: // CIMClass cimClass(modifiedClass); Resolver::resolveClass (cimClass, _context, nameSpace); // // Check to see if it is okay to modify this class: // String classFilePath; _nameSpaceManager.checkModify(nameSpace, cimClass.getClassName(), cimClass.getSuperClassName(), classFilePath); // // ATTN: KS // Disallow modification of classes which have instances (that are // in the repository). And we have no idea whether the class has // instances in other repositories or in providers. We should do // an enumerate instance names at a higher level (above the repository). // #ifdef PEGASUS_USE_CLASS_CACHE _classCache.evict(classFilePath); #endif /* PEGASUS_USE_CLASS_CACHE */ // // Delete the old file containing the class: // if (!FileSystem::removeFileNoCase(classFilePath)) { PEG_METHOD_EXIT(); String str = "DefaultRepository::modifyClass()"; throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms( "Repository.DefaultRepository.FAILED_TO_REMOVE_FILE", "failed to remove file in $0", str)); } // // Create new class file: // Buffer classXml; streamer->encode(classXml, cimClass); //XmlWriter::appendClassElement(classXml, cimClass); _SaveObject(classFilePath, classXml,streamer); if (cimClass.isAssociation()) { // Remove from Association Array assocFileName = _nameSpaceManager.getAssocClassPath(nameSpace,NameSpaceDelete); if (FileSystem::exists(assocFileName[0])) { AssocClassTable::deleteAssociation( assocFileName[0], cimClass.getClassName()); // Create the association again. _createAssocClassEntries(nameSpace, cimClass); } else { PEG_METHOD_EXIT(); throw CannotOpenFile(assocFileName[0]); } } // // Cache this class: // #ifdef PEGASUS_USE_CLASS_CACHE _classCache.put(classFilePath, cimClass); #endif /* PEGASUS_USE_CLASS_CACHE */ PEG_METHOD_EXIT(); } void DefaultRepository::modifyInstance( bool lock, const CIMNamespaceName& nameSpace, const CIMInstance& modifiedInstance, Boolean includeQualifiers, const CIMPropertyList& propertyList, const ContentLanguageList& contentLangs) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::modifyInstance"); ConditionalWriteLock wlock(_lock, lock); AutoFileLock fileLock(_lockFile); // // Do this: // String errMessage; CIMInstance cimInstance; // The instance that replaces the original if (propertyList.isNull()) { // // Replace all the properties in the instance // if (includeQualifiers) { // // Replace the entire instance with the given instance // (this is the default behavior) // cimInstance = modifiedInstance; } else { // // Replace all the properties in the instance, but keep the // original qualifiers on the instance and on the properties // _resolveInstance = false; cimInstance = getInstance( false, nameSpace, modifiedInstance.getPath (), false, true, true, CIMPropertyList()); _resolveInstance = true; CIMInstance newInstance( modifiedInstance.getPath ().getClassName()); CIMInstance givenInstance = modifiedInstance; // // Copy over the original instance qualifiers // for (Uint32 i = 0; i < cimInstance.getQualifierCount(); i++) { newInstance.addQualifier(cimInstance.getQualifier(i)); } // // Loop through the properties replacing each property in the // original with a new value, but keeping the original qualifiers // for (Uint32 i=0; iencode(out, cimInstance); //XmlWriter::appendInstanceElement(out, cimInstance); newSize = out.size(); if (!InstanceDataFile::appendInstance(dataFilePath, out, newIndex)) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms( "Repository.DefaultRepository.FAILED_TO_MODIFY_INSTANCE", "Failed to modify instance $0", instanceName.toString())); } } // // Modify the index file: // Uint32 freeCount; if (!InstanceIndexFile::modifyEntry(indexFilePath, instanceName, newIndex, newSize, freeCount)) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms( "Repository.DefaultRepository.FAILED_TO_MODIFY_INSTANCE", "Failed to modify instance $0", instanceName.toString())); } transaction.complete(); // // Compact the index and data files if the free count max was // reached. // if (freeCount == _MAX_FREE_COUNT) _CompactInstanceRepository(indexFilePath, dataFilePath); // // Resolve the instance: // Resolver::resolveInstance (cimInstance, _context, nameSpace, cimClass, true); PEG_METHOD_EXIT(); } Array DefaultRepository::enumerateClasses( bool lock, const CIMNamespaceName& nameSpace, const CIMName& className, Boolean deepInheritance, Boolean localOnly, Boolean includeQualifiers, Boolean includeClassOrigin) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::enumerateClasses"); ConditionalReadLock rlock(_lock, lock); Array classNames; _nameSpaceManager.getSubClassNames( nameSpace, className, deepInheritance, classNames); Array result; for (Uint32 i = 0; i < classNames.size(); i++) { result.append(getClass(false, nameSpace, classNames[i], localOnly, includeQualifiers, includeClassOrigin, CIMPropertyList())); } PEG_METHOD_EXIT(); return result; } Array DefaultRepository::enumerateClassNames( bool lock, const CIMNamespaceName& nameSpace, const CIMName& className, Boolean deepInheritance) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::enumerateClassNames"); ConditionalReadLock rlock(_lock, lock); Array classNames; _nameSpaceManager.getSubClassNames( nameSpace, className, deepInheritance, classNames,true); PEG_METHOD_EXIT(); return classNames; } Boolean DefaultRepository::_loadAllInstances( const CIMNamespaceName& nameSpace, const CIMName& className, Array& namedInstances) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::_loadAllInstances"); Array instanceNames; Buffer data; Array indices; Array sizes; // // Form the names of the instance index and data files // String indexFilePath = _getInstanceIndexFilePath(nameSpace, className); String dataFilePath = _getInstanceDataFilePath(nameSpace, className); // // Enumerate the index file: // Array freeFlags; if (!InstanceIndexFile::enumerateEntries( indexFilePath, freeFlags, indices, sizes, instanceNames, true)) { PEG_METHOD_EXIT(); return false; } // // Form the array of instances result: // if (instanceNames.size() > 0) { // // Load all instances from the data file: // if (!InstanceDataFile::loadAllInstances(dataFilePath, data)) { PEG_METHOD_EXIT(); return false; } // // for each instance loaded, call XML parser to parse the XML // data and create a CIMInstance object. // CIMInstance tmpInstance; Uint32 bufferSize = data.size(); char* buffer = (char*)data.getData(); for (Uint32 i = 0; i < instanceNames.size(); i++) { if (!freeFlags[i]) { Uint32 pos= (Uint32)((&(buffer[indices[i]]))-buffer); streamer->decode(data, pos, tmpInstance); Resolver::resolveInstance (tmpInstance, _context, nameSpace, true); tmpInstance.setPath (instanceNames[i]); namedInstances.append (tmpInstance); } } } PEG_METHOD_EXIT(); return true; } Array DefaultRepository::enumerateInstancesForSubtree( bool lock, const CIMNamespaceName& nameSpace, const CIMName& className, Boolean deepInheritance, Boolean localOnly, Boolean includeQualifiers, Boolean includeClassOrigin, const CIMPropertyList& propertyList) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::enumerateInstancesForSubtree"); // It is not necessary to control access to the ReadWriteSem _lock here. // This method calls enumerateInstancesForClass, which does its own // access control. // // Get all descendent classes of this class: // Array classNames; classNames.append(className); _nameSpaceManager.getSubClassNames(nameSpace, className, true, classNames); // // Get all instances for this class and all its descendent classes // Array namedInstances; for (Uint32 i = 0; i < classNames.size(); i++) { Array localNamedInstances = enumerateInstancesForClass(true, nameSpace, classNames[i], false, includeQualifiers, includeClassOrigin, propertyList); // ATTN: Handles everything but deepInheritance. for (Uint32 i = 0 ; i < localNamedInstances.size(); i++) { Filtering::filterInstance(localNamedInstances[i], localOnly, includeQualifiers, includeClassOrigin, propertyList); } namedInstances.appendArray(localNamedInstances); } PEG_METHOD_EXIT(); return namedInstances; } Array DefaultRepository::enumerateInstancesForClass( bool lock, const CIMNamespaceName& nameSpace, const CIMName& className, Boolean localOnly, Boolean includeQualifiers, Boolean includeClassOrigin, const CIMPropertyList& propertyList) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::enumerateInstancesForClass"); ConditionalReadLock rlock(_lock, lock); // // Get all instances for this class // Array namedInstances; if (!_loadAllInstances(nameSpace, className, namedInstances)) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms( "Repository.DefaultRepository.FAILED_TO_LOAD_INSTANCES", "Failed to load instances in class $0", className.getString())); } // Do any required filtering of properties, qualifiers, classorigin // on the returned instances. for (Uint32 i = 0 ; i < namedInstances.size(); i++) { Filtering::filterInstance(namedInstances[i], localOnly, includeQualifiers, includeClassOrigin, propertyList); } PEG_METHOD_EXIT(); return namedInstances; } Array DefaultRepository::enumerateInstanceNamesForSubtree( bool lock, const CIMNamespaceName& nameSpace, const CIMName& className) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::enumerateInstanceNamesForSubtree"); // It is not necessary to control access to the ReadWriteSem _lock here. // This method calls enumerateInstanceNamesForClass, which does its own // access control. // // Get names of descendent classes: // Array classNames; classNames.append(className); _nameSpaceManager.getSubClassNames(nameSpace, className, true, classNames); // // Enumerate instance names for each of the subclasses // Array instanceNames; for (Uint32 i = 0; i < classNames.size(); i++) { instanceNames.appendArray( enumerateInstanceNamesForClass(true, nameSpace, classNames[i])); } PEG_METHOD_EXIT(); return instanceNames; } Array DefaultRepository::enumerateInstanceNamesForClass( bool lock, const CIMNamespaceName& nameSpace, const CIMName& className) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::enumerateInstanceNamesForClass"); ConditionalReadLock rlock(_lock, lock); // // Get instance names from the instance index file for the class: // Array instanceNames; Array indices; Array sizes; // // Form the names of the instance index and data files // String indexFilePath = _getInstanceIndexFilePath(nameSpace, className); String dataFilePath = _getInstanceDataFilePath(nameSpace, className); // // Get all instances for the class: // Array freeFlags; if (!InstanceIndexFile::enumerateEntries( indexFilePath, freeFlags, indices, sizes, instanceNames, false)) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms( "Repository.DefaultRepository.FAILED_TO_LOAD_INSTANCE_NAMES", "Failed to load instance names in class $0", className.getString())); } PEG_METHOD_EXIT(); return instanceNames; } Array DefaultRepository::execQuery( bool lock, const String& queryLanguage, const String& query) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::execQuery"); ConditionalReadLock rlock(_lock, lock); PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_SUPPORTED, "execQuery()"); PEGASUS_UNREACHABLE(PEG_METHOD_EXIT(); return Array();) } Array DefaultRepository::associators( bool lock, const CIMNamespaceName& nameSpace, const CIMObjectPath& objectName, const CIMName& assocClass, const CIMName& resultClass, const String& role, const String& resultRole, Boolean includeQualifiers, Boolean includeClassOrigin, const CIMPropertyList& propertyList) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::associators"); ConditionalReadLock rlock(_lock, lock); Array names = associatorNames( false, nameSpace, objectName, assocClass, resultClass, role, resultRole); Array result; for (Uint32 i = 0, n = names.size(); i < n; i++) { CIMNamespaceName tmpNameSpace = names[i].getNameSpace(); if (tmpNameSpace.isNull()) tmpNameSpace = nameSpace; // // ATTN-CAKG-P2-20020726: The following condition does not correctly // distinguish instanceNames from classNames in every case // The instanceName of a singleton instance of a keyless class also // has no key bindings // if (names[i].getKeyBindings ().size () == 0) { CIMObjectPath tmpRef = names[i]; tmpRef.setHost(String()); tmpRef.setNameSpace(CIMNamespaceName()); CIMClass cimClass = getClass( false, tmpNameSpace, tmpRef.getClassName(), false, includeQualifiers, includeClassOrigin, propertyList); CIMObject cimObject(cimClass); cimObject.setPath (names[i]); result.append(cimObject); } else { CIMObjectPath tmpRef = names[i]; tmpRef.setHost(String()); tmpRef.setNameSpace(CIMNamespaceName()); CIMInstance cimInstance = getInstance( false, tmpNameSpace, tmpRef, false, includeQualifiers, includeClassOrigin, propertyList); CIMObject cimObject(cimInstance); cimObject.setPath (names[i]); result.append(cimObject); } } PEG_METHOD_EXIT(); return result; } Array DefaultRepository::associatorNames( bool lock, const CIMNamespaceName& nameSpace, const CIMObjectPath& objectName, const CIMName& assocClass, const CIMName& resultClass, const String& role, const String& resultRole) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::associatorNames"); ConditionalReadLock rlock(_lock, lock); Array associatorNames; // The assocClass parameter implies subclasses, so retrieve them Array assocClassList; if (!assocClass.isNull()) { _nameSpaceManager.getSubClassNames( nameSpace, assocClass, true, assocClassList); assocClassList.append(assocClass); } // The resultClass parameter implies subclasses, so retrieve them Array resultClassList; if (!resultClass.isNull()) { _nameSpaceManager.getSubClassNames( nameSpace, resultClass, true, resultClassList); resultClassList.append(resultClass); } // // ATTN-CAKG-P2-20020726: The following condition does not correctly // distinguish instanceNames from classNames in every case // The instanceName of a singleton instance of a keyless class also // has no key bindings // if (objectName.getKeyBindings ().size () == 0) { CIMName className = objectName.getClassName(); Array classList; _nameSpaceManager.getSuperClassNames(nameSpace, className, classList); classList.append(className); Array assocFileName = _nameSpaceManager.getAssocClassPath(nameSpace,NameSpaceRead); for (int i=0,m=assocFileName.size(); i result; for (Uint32 i = 0, n = associatorNames.size(); i < n; i++) { CIMObjectPath r = associatorNames[i]; if (r.getHost().size() == 0) r.setHost(System::getHostName()); if (r.getNameSpace().isNull()) r.setNameSpace(nameSpace); result.append(r); } PEG_METHOD_EXIT(); return result; } Array DefaultRepository::references( bool lock, const CIMNamespaceName& nameSpace, const CIMObjectPath& objectName, const CIMName& resultClass, const String& role, Boolean includeQualifiers, Boolean includeClassOrigin, const CIMPropertyList& propertyList) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::references"); ConditionalReadLock rlock(_lock, lock); Array names = referenceNames( false, nameSpace, objectName, resultClass, role); Array result; for (Uint32 i = 0, n = names.size(); i < n; i++) { CIMNamespaceName tmpNameSpace = names[i].getNameSpace(); if (tmpNameSpace.isNull()) tmpNameSpace = nameSpace; // ATTN: getInstance() should this be able to handle instance names // with host names and namespaces? CIMObjectPath tmpRef = names[i]; tmpRef.setHost(String()); tmpRef.setNameSpace(CIMNamespaceName()); // // ATTN-CAKG-P2-20020726: The following condition does not correctly // distinguish instanceNames from classNames in every case // The instanceName of a singleton instance of a keyless class also // has no key bindings // if (objectName.getKeyBindings ().size () == 0) { CIMClass cimClass = getClass( false, tmpNameSpace, tmpRef.getClassName(), false, includeQualifiers, includeClassOrigin, propertyList); CIMObject cimObject = CIMObject (cimClass); cimObject.setPath (names[i]); result.append (cimObject); } else { CIMInstance instance = getInstance( false, tmpNameSpace, tmpRef, false, includeQualifiers, includeClassOrigin, propertyList); CIMObject cimObject = CIMObject (instance); cimObject.setPath (names[i]); result.append (cimObject); } } PEG_METHOD_EXIT(); return result; } Array DefaultRepository::referenceNames( bool lock, const CIMNamespaceName& nameSpace, const CIMObjectPath& objectName, const CIMName& resultClass, const String& role) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::referenceNames"); ConditionalReadLock rlock(_lock, lock); Array tmpReferenceNames; // The resultClass parameter implies subclasses, so retrieve them Array resultClassList; try { if (!resultClass.isNull()) { _nameSpaceManager.getSubClassNames( nameSpace, resultClass, true, resultClassList); resultClassList.append(resultClass); } // ATTN-CAKG-P2-20020726: The following condition does not correctly // distinguish instanceNames from classNames in every case // The instanceName of a singleton instance of a keyless class also // has no key bindings // if (objectName.getKeyBindings ().size () == 0) { CIMName className = objectName.getClassName(); Array classList; _nameSpaceManager.getSuperClassNames( nameSpace, className, classList); classList.append(className); Array assocFileName = _nameSpaceManager.getAssocClassPath(nameSpace,NameSpaceRead); Boolean refs=false; for (int i = 0, m=assocFileName.size(); !refs && i < m; i++) { if (AssocClassTable::getReferenceNames( assocFileName[i], classList, resultClassList, role, tmpReferenceNames)) { refs |= true; } } if (refs == false) { // Ignore error! It's okay not to have references. } } else { String assocFileName = _nameSpaceManager.getAssocInstPath(nameSpace); if (!AssocInstTable::getReferenceNames( assocFileName, objectName, resultClassList, role, tmpReferenceNames)) { // Ignore error! It's okay not to have references. } } } catch (const CIMException& exception) { if (exception.getCode() == CIM_ERR_INVALID_CLASS) { throw PEGASUS_CIM_EXCEPTION( CIM_ERR_INVALID_PARAMETER, exception.getMessage()); } else { throw; } } Array result; for (Uint32 i = 0, n = tmpReferenceNames.size(); i < n; i++) { CIMObjectPath r = tmpReferenceNames[i]; if (r.getHost().size() == 0) r.setHost(System::getHostName()); if (r.getNameSpace().isNull()) r.setNameSpace(nameSpace); result.append(r); } PEG_METHOD_EXIT(); return result; } CIMValue DefaultRepository::getProperty( bool lock, const CIMNamespaceName& nameSpace, const CIMObjectPath& instanceName, const CIMName& propertyName) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::getProperty"); ConditionalReadLock rlock(_lock, lock); // // Retrieve the specified instance // CIMInstance cimInstance = getInstance( false, nameSpace, instanceName, false, true, true, CIMPropertyList()); // // Get the requested property from the instance // Uint32 pos = cimInstance.findProperty(propertyName); // ATTN: This breaks if the property is simply null if (pos == PEG_NOT_FOUND) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION( CIM_ERR_NO_SUCH_PROPERTY, propertyName.getString()); } CIMProperty prop = cimInstance.getProperty(pos); // // Return the value: // PEG_METHOD_EXIT(); return prop.getValue(); } void DefaultRepository::setProperty( bool lock, const CIMNamespaceName& nameSpace, const CIMObjectPath& instanceName, const CIMName& propertyName, const CIMValue& newValue, const ContentLanguageList& contentLangs) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::setProperty"); // It is not necessary to control access to the ReadWriteSem _lock here. // This method calls modifyInstance, which does its own access control. // // Create the instance to pass to modifyInstance() // CIMInstance instance(instanceName.getClassName()); instance.addProperty(CIMProperty(propertyName, newValue)); instance.setPath (instanceName); // // Create the propertyList to pass to modifyInstance() // Array propertyListArray; propertyListArray.append(propertyName); CIMPropertyList propertyList(propertyListArray); // // Modify the instance to set the value of the given property // modifyInstance( true, nameSpace, instance, false, propertyList, ContentLanguageList()); PEG_METHOD_EXIT(); } CIMQualifierDecl DefaultRepository::getQualifier( bool lock, const CIMNamespaceName& nameSpace, const CIMName& qualifierName) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::getQualifier"); ConditionalReadLock rlock(_lock, lock); // // Get path of qualifier file: // String qualifierFilePath = _nameSpaceManager.getQualifierFilePath( nameSpace, qualifierName,NameSpaceRead); // // Load qualifier: // CIMQualifierDecl qualifierDecl; try { // Check the cache first: if (!_qualifierCache.get(qualifierFilePath, qualifierDecl)) { // Not in cache so load from disk: _LoadObject(qualifierFilePath, qualifierDecl, streamer); // Put in cache: _qualifierCache.put(qualifierFilePath, qualifierDecl); } } catch (const CannotOpenFile&) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION (CIM_ERR_NOT_FOUND, qualifierName.getString()); } PEG_METHOD_EXIT(); return qualifierDecl; } void DefaultRepository::setQualifier( bool lock, const CIMNamespaceName& nameSpace, const CIMQualifierDecl& qualifierDecl, const ContentLanguageList& contentLangs) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::setQualifier"); ConditionalWriteLock wlock(_lock, lock); AutoFileLock fileLock(_lockFile); // -- Get path of qualifier file: String qualifierFilePath = _nameSpaceManager.getQualifierFilePath( nameSpace, qualifierDecl.getName(),NameSpaceWrite); // -- If qualifier already exists, throw exception: if (FileSystem::existsNoCase(qualifierFilePath)) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION( CIM_ERR_NOT_SUPPORTED, qualifierDecl.getName().getString()); } // -- Save qualifier: Buffer qualifierDeclXml; streamer->encode(qualifierDeclXml, qualifierDecl); //XmlWriter::appendQualifierDeclElement(qualifierDeclXml, qualifierDecl); _SaveObject(qualifierFilePath, qualifierDeclXml,streamer); _qualifierCache.put(qualifierFilePath, (CIMQualifierDecl&)qualifierDecl); PEG_METHOD_EXIT(); } void DefaultRepository::deleteQualifier( bool lock, const CIMNamespaceName& nameSpace, const CIMName& qualifierName) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::deleteQualifier"); ConditionalWriteLock wlock(_lock, lock); AutoFileLock fileLock(_lockFile); // -- Get path of qualifier file: String qualifierFilePath = _nameSpaceManager.getQualifierFilePath( nameSpace, qualifierName,NameSpaceDelete); // -- Delete qualifier: if (!FileSystem::removeFileNoCase(qualifierFilePath)) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION (CIM_ERR_NOT_FOUND, qualifierName.getString()); } _qualifierCache.evict(qualifierFilePath); PEG_METHOD_EXIT(); } Array DefaultRepository::enumerateQualifiers( bool lock, const CIMNamespaceName& nameSpace) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::enumerateQualifiers"); ConditionalReadLock rlock(_lock, lock); String qualifiersRoot = _nameSpaceManager.getQualifiersRoot(nameSpace); Array qualifierNames; if (!FileSystem::getDirectoryContents(qualifiersRoot, qualifierNames)) { PEG_METHOD_EXIT(); String str ="enumerateQualifiers()"; throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms("Repository.DefaultRepository.INTERNAL_ERROR", "$0: internal error", str)); } Array qualifiers; for (Uint32 i = 0; i < qualifierNames.size(); i++) { #ifdef PEGASUS_REPOSITORY_ESCAPE_UTF8 // All chars above 0x7F will be escape. CIMQualifierDecl qualifier = getQualifier(false, nameSpace, escapeStringDecoder(qualifierNames[i])); #else CIMQualifierDecl qualifier = getQualifier( false, nameSpace, qualifierNames[i]); #endif qualifiers.append(qualifier); } PEG_METHOD_EXIT(); return qualifiers; } void DefaultRepository::createNameSpace( bool lock, const CIMNamespaceName& nameSpace, const NameSpaceAttributes& attributes) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::createNameSpace"); ConditionalWriteLock wlock(_lock, lock); AutoFileLock fileLock(_lockFile); _nameSpaceManager.createNameSpace(nameSpace, attributes); PEG_METHOD_EXIT(); } void DefaultRepository::modifyNameSpace( bool lock, const CIMNamespaceName& nameSpace, const NameSpaceAttributes& attributes) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::modifyNameSpace"); ConditionalWriteLock wlock(_lock, lock); AutoFileLock fileLock(_lockFile); _nameSpaceManager.modifyNameSpace(nameSpace, attributes); PEG_METHOD_EXIT(); } Array DefaultRepository::enumerateNameSpaces( bool lock) const { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::enumerateNameSpaces"); ConditionalReadLock rlock(const_cast(_lock), lock); Array nameSpaceNames; _nameSpaceManager.getNameSpaceNames(nameSpaceNames); PEG_METHOD_EXIT(); return nameSpaceNames; } void DefaultRepository::deleteNameSpace( bool lock, const CIMNamespaceName& nameSpace) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::deleteNameSpace"); ConditionalWriteLock wlock(_lock, lock); AutoFileLock fileLock(_lockFile); _nameSpaceManager.deleteNameSpace(nameSpace); PEG_METHOD_EXIT(); } Boolean DefaultRepository::getNameSpaceAttributes( bool lock, const CIMNamespaceName& nameSpace, NameSpaceAttributes& attributes) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::deleteNameSpace"); ConditionalReadLock rlock(const_cast(_lock), lock); attributes.clear(); PEG_METHOD_EXIT(); return _nameSpaceManager.getNameSpaceAttributes(nameSpace, attributes); } Boolean DefaultRepository::isRemoteNameSpace( bool lock, const CIMNamespaceName& nameSpaceName, String& remoteInfo) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::isRemoteNamespace"); ConditionalReadLock rlock(const_cast(_lock), lock); PEG_METHOD_EXIT(); return _nameSpaceManager.isRemoteNameSpace(nameSpaceName, remoteInfo); } //---------------------------------------------------------------------- // // _getInstanceIndexFilePath() // // returns the file path of the instance index file. // //---------------------------------------------------------------------- String DefaultRepository::_getInstanceIndexFilePath( const CIMNamespaceName& nameSpace, const CIMName& className) const { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::_getInstanceIndexFilePath"); String tmp = _nameSpaceManager.getInstanceDataFileBase( nameSpace, className); tmp.append(".idx"); PEG_METHOD_EXIT(); return tmp; } //---------------------------------------------------------------------- // // _getInstanceDataFilePath() // // returns the file path of the instance file. // //---------------------------------------------------------------------- String DefaultRepository::_getInstanceDataFilePath( const CIMNamespaceName& nameSpace, const CIMName& className) const { PEG_METHOD_ENTER( TRC_REPOSITORY, "DefaultRepository::_getInstanceDataFilePath"); String tmp = _nameSpaceManager.getInstanceDataFileBase( nameSpace, className); tmp.append(".instances"); PEG_METHOD_EXIT(); return tmp; } Boolean DefaultRepository::_loadInstance( const String& path, CIMInstance& object, Uint32 index, Uint32 size) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::_loadInstance"); // // Load instance (in XML) from instance file into memory: // Buffer data; if (!InstanceDataFile::loadInstance(path, index, size, data)) { PEG_METHOD_EXIT(); return false; } // // Convert XML into an actual object: // streamer->decode(data, 0, object); //XmlParser parser((char*)data.getData()); //XmlReader::getObject(parser, object); PEG_METHOD_EXIT(); return true; } void DefaultRepository::setDeclContext( bool lock, RepositoryDeclContext* context) { PEG_METHOD_ENTER(TRC_REPOSITORY, "DefaultRepository::setDeclContext"); ConditionalWriteLock wlock(_lock, lock); AutoFileLock fileLock(_lockFile); _context = context; PEG_METHOD_EXIT(); } #ifdef PEGASUS_DEBUG void DefaultRepository::DisplayCacheStatistics( bool lock) { #ifdef PEGASUS_USE_CLASS_CACHE cout << "Repository Class Cache Statistics:" << endl; _classCache.DisplayCacheStatistics(); #endif cout << "Repository Qualifier Cache Statistics:" << endl; _qualifierCache.DisplayCacheStatistics(); } #endif void DefaultRepository::getSubClassNames( bool lock, const CIMNamespaceName& nameSpaceName, const CIMName& className, Boolean deepInheritance, Array& subClassNames) const { ConditionalReadLock rlock(const_cast(_lock), lock); _nameSpaceManager.getSubClassNames(nameSpaceName, className, deepInheritance, subClassNames); } /** Get the names of all superclasses (direct and indirect) of this class. */ void DefaultRepository::getSuperClassNames( bool lock, const CIMNamespaceName& nameSpaceName, const CIMName& className, Array& superClassNames) const { ConditionalReadLock rlock(const_cast(_lock), lock); _nameSpaceManager.getSuperClassNames( nameSpaceName, className, superClassNames); } PEGASUS_NAMESPACE_END