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

File: [Pegasus] / pegasus / src / Pegasus / Repository / CIMRepository.cpp (download)
Revision: 1.51, Thu Dec 13 14:54:26 2001 UTC (22 years, 6 months ago) by mike
Branch: MAIN
CVS Tags: pre-meta-dispatcher, merge_of_dev, VERSION_1_07
Changes since 1.50: +1008 -422 lines
Merged dev branch into main trunk.

//%/////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000, 2001 The Open group, BMC Software, Tivoli Systems, IBM
//
// 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.
//
//==============================================================================
//
// Author: Mike Brasher (mbrasher@bmc.com)
//
// Modified By: Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com)
//              Yi Zhou, Hewlett-Packard Company (yi_zhou@hp.com)
//              Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
//
//%/////////////////////////////////////////////////////////////////////////////

#include <Pegasus/Common/Config.h>
#include <cctype>
#include <cstdio>
#include <fstream>
#include <Pegasus/Common/Pair.h>
#include <Pegasus/Common/Destroyer.h>
#include <Pegasus/Common/FileSystem.h>
#include <Pegasus/Common/Exception.h>
#include <Pegasus/Common/XmlReader.h>
#include <Pegasus/Common/XmlWriter.h>
#include <Pegasus/Common/DeclContext.h>
#include <Pegasus/Common/DeclContext.h>
#include <Pegasus/Common/System.h>
#include "CIMRepository.h"
#include "RepositoryDeclContext.h"
#include "InstanceIndexFile.h"
#include "InstanceFile.h"
#include "AssocInstTable.h"
#include "AssocClassTable.h"

#define INDENT_XML_FILES

PEGASUS_USING_STD;

PEGASUS_NAMESPACE_BEGIN

////////////////////////////////////////////////////////////////////////////////
//
// _LoadObject()
//
//      Loads objects (classes and qualifiers) from disk to
//      memory objects.
//
////////////////////////////////////////////////////////////////////////////////

template<class Object>
void _LoadObject(
    const String& path,
    Object& object)
{
    // Get the real path of the file:

    String realPath;

    if (!FileSystem::existsNoCase(path, realPath))
        throw CannotOpenFile(path);

    // Load file into memory:

    Array<Sint8> data;
    FileSystem::loadFileToMemory(data, realPath);
    data.append('\0');

    XmlParser parser((char*)data.getData());

    XmlReader::getObject(parser, object);
}

////////////////////////////////////////////////////////////////////////////////
//
// _SaveObject()
//
//      Saves objects (classes and qualifiers) from memory to
//      disk files.
//
////////////////////////////////////////////////////////////////////////////////

template<class Object>
void _SaveObject(const String& path, const Object& object)
{
    Array<Sint8> out;
    object.toXml(out);

    ArrayDestroyer<char> destroyer(path.allocateCString());
    PEGASUS_STD(ofstream) os(destroyer.getPointer() PEGASUS_IOS_BINARY);

    if (!os)
        throw CannotOpenFile(path);

#ifdef INDENT_XML_FILES
    out.append('\0');
    XmlWriter::indentedPrint(os, out.getData(), 2);
#else
    os.write((char*)out.getData(), out.size());
#endif
}

static String _MakeAssocInstPath(
    const String& nameSpace,
    const String& repositoryRoot)
{
    String tmp = nameSpace;
    tmp.translate('/', '#');
    return String(Cat(repositoryRoot, "/", tmp, "/instances/associations"));
}

static String _MakeAssocClassPath(
    const String& nameSpace,
    const String& repositoryRoot)
{
    String tmp = nameSpace;
    tmp.translate('/', '#');
    return String(Cat(repositoryRoot, "/", tmp, "/classes/associations"));
}

////////////////////////////////////////////////////////////////////////////////
//
// CIMRepository
//
//     The following are not implemented:
//
//         CIMRepository::execQuery()
//         CIMRepository::referencesNames()
//         CIMRepository::invokeMethod()
//
//     Note that invokeMethod() will not never implemented since it is not
//     meaningful for a repository.
//
//     ATTN: make operations on files non-case-sensitive.
//
////////////////////////////////////////////////////////////////////////////////

CIMRepository::CIMRepository(const String& repositoryRoot)
   : _repositoryRoot(repositoryRoot), _nameSpaceManager(repositoryRoot),
     _lock()
{
    _context = new RepositoryDeclContext(this);
    _isDefaultInstanceProvider = (ConfigManager::getInstance()->getCurrentValue(
        "repositoryIsDefaultInstanceProvider") == "true");
    _providerName = ConfigManager::getInstance()->getCurrentValue(
        "repositoryProviderName");
}

CIMRepository::~CIMRepository()
{
    delete _context;
}


void CIMRepository::read_lock(void) throw(IPCException)
{
   _lock.wait_read(pegasus_thread_self());
}

void CIMRepository::read_unlock(void)
{
   _lock.unlock_read(pegasus_thread_self());
}

void CIMRepository::write_lock(void) throw(IPCException)
{
   _lock.wait_write(pegasus_thread_self());
}

void CIMRepository::write_unlock(void)
{
   _lock.unlock_write(pegasus_thread_self());
}

CIMClass CIMRepository::getClass(
    const String& nameSpace,
    const String& className,
    Boolean localOnly,
    Boolean includeQualifiers,
    Boolean includeClassOrigin,
    const CIMPropertyList& propertyList)
{
    // ATTN: localOnly, includeQualifiers, and includeClassOrigin are ignored
    // for now.

   

    String classFilePath;
    classFilePath = _nameSpaceManager.getClassFilePath(nameSpace, className);

    CIMClass cimClass;

    try
    {
        _LoadObject(classFilePath, cimClass);
    }
    catch (Exception & e)
    {
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, className);
    }

    return cimClass;
}

//----------------------------------------------------------------------
//
// _getInstanceIndex()
//
//      Returns the index (or byte location) and size of the instance 
//      record in the instance file for a given instance.  Returns false
//      if the instance cannot be found.
//
//----------------------------------------------------------------------

Boolean CIMRepository::_getInstanceIndex(
    const String& nameSpace,
    const CIMReference& instanceName,
    String& className,
    Uint32& size,
    Uint32& index,
    Boolean searchSuperClasses) const
{
    // -- Get all descendent classes of this class:


    className = instanceName.getClassName();

    Array<String> classNames;
    _nameSpaceManager.getSubClassNames(nameSpace, className, true, classNames);
    classNames.prepend(className);

    // -- Get all superclasses of this one:

    if (searchSuperClasses)
        _nameSpaceManager.getSuperClassNames(nameSpace, className, classNames);

    // -- Get instance names from each qualifying instance file for the class

    for (Uint32 i = 0; i < classNames.size(); i++)
    {
        CIMReference tmpInstanceName = instanceName;
        tmpInstanceName.setClassName(classNames[i]);

        // -- Lookup index of instance:

        String path = _getIndexFilePath(nameSpace, classNames[i]);

        if (InstanceIndexFile::lookup(path, tmpInstanceName, size, index))
        {
            className = classNames[i];
            return true;
        }
    }

    return false;
}

CIMInstance CIMRepository::getInstance(
    const String& nameSpace,
    const CIMReference& instanceName,
    Boolean localOnly,
    Boolean includeQualifiers,
    Boolean includeClassOrigin,
    const CIMPropertyList& propertyList)
{
    // -- Get the index for this instance:

    String className;
    Uint32 index;
    Uint32 size;


    if (!_getInstanceIndex(nameSpace, instanceName, className, size, index))
    {
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, instanceName.toString());
    }

    // -- Load the instance from file:

    String path = _getInstanceFilePath(nameSpace, className);
    CIMInstance cimInstance;
    if (!_loadInstance(path, cimInstance, index, size))
    {
        throw CannotOpenFile(path);
    }

    return cimInstance;
}

void CIMRepository::deleteClass(
    const String& nameSpace,
    const String& className)
{
    // -- Get the class and check to see if it is an association class:


    CIMClass cimClass = getClass(nameSpace, className, false);
    Boolean isAssociation = cimClass.isAssociation();

    // -- Disallow deletion if class has instances:

    String path = _getIndexFilePath(nameSpace, className);
    String realPath;

    if (FileSystem::existsNoCase(path, realPath))
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_CLASS_HAS_INSTANCES, className);

    // -- Delete the class (disallowed if there are subclasses):

    _nameSpaceManager.deleteClass(nameSpace, className);

    // -- Remove association:

    if (isAssociation)
    {
        String assocFileName = _MakeAssocClassPath(nameSpace, _repositoryRoot);

        if (FileSystem::exists(assocFileName))
            AssocClassTable::deleteAssociation(assocFileName, className);
    }
}

void CIMRepository::deleteInstance(
    const String& nameSpace,
    const CIMReference& instanceName)
{

    String errMessage;

    // -- Lookup instance from the index file:

    String indexFilePath = _getIndexFilePath(
        nameSpace, instanceName.getClassName());

    Uint32 index;
    Uint32 size;

    if (!InstanceIndexFile::lookup(indexFilePath, instanceName, size, index))
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, instanceName.toString());

    // -- Remove entry from index file:

    if (!InstanceIndexFile::remove(indexFilePath, instanceName))
    {
        errMessage.append("Failed to delete instance ");
        errMessage.append(instanceName.toString());
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED, errMessage);
    }

    // -- Remove the instance from the instance file:

    String instanceFilePath = _getInstanceFilePath(
        nameSpace, instanceName.getClassName());

    if (!InstanceFile::removeInstance(instanceFilePath, size, index))
    {
        errMessage.append("Failed to delete instance ");
        errMessage.append(instanceName.toString());
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED, errMessage);
    }

    // -- Rename the temporary index and instance files back to the original:

    if (!_renameTempInstanceAndIndexFiles(indexFilePath, instanceFilePath))
    {
        errMessage.append("Unexpected error occurred while deleting instance ");
        errMessage.append(instanceName.toString());
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED, errMessage);
    }

    // -- Remove it from the association table (if it is really association).
    // -- We ignore the return value intentionally. If it is an association,
    // -- true is returned. Otherwise, true is returned.

    String assocFileName = _MakeAssocInstPath(nameSpace, _repositoryRoot);

    if (FileSystem::exists(assocFileName))
        AssocInstTable::deleteAssociation(assocFileName, instanceName);
}

void CIMRepository::_createAssocClassEntries(
    const String& nameSpace,
    const CIMConstClass& assocClass)
{
    // Open input file:


    String assocFileName = _MakeAssocClassPath(nameSpace, _repositoryRoot);
    ofstream os;

    if (!OpenAppend(os, assocFileName))
        throw CannotOpenFile(assocFileName);

    // Get the association's class name:

    String 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() != toProp.getName())
                {
                    String fromClassName = fromProp.getReferenceClassName();
                    String fromPropertyName = fromProp.getName();
                    String toClassName = toProp.getReferenceClassName();
                    String toPropertyName = toProp.getName();

                    AssocClassTable::append(
                        os,
                        assocClassName,
                        fromClassName,
                        fromPropertyName,
                        toClassName,
                        toPropertyName);
                }
            }
        }
    }
}

void CIMRepository::createClass(
    const String& nameSpace,
    const CIMClass& newClass)
{


    // -- Resolve the class:
        CIMClass cimClass(newClass);
        
    cimClass.resolve(_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:

    _SaveObject(classFilePath, cimClass);
}

/*------------------------------------------------------------------------------

    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 CIMRepository::_createAssocInstEntries(
    const String& nameSpace,
    const CIMConstClass& cimClass,
    const CIMInstance& cimInstance,
    const CIMReference& instanceName)
{
    // Open input file:

   
    String assocFileName = _MakeAssocInstPath(nameSpace, _repositoryRoot);
    ofstream os;

    if (!OpenAppend(os, assocFileName))
        throw CannotOpenFile(assocFileName);

    // Get the association's instance name and class name:

    String assocInstanceName = instanceName.toString();
    String 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() != toProp.getName())
                {
                    CIMReference fromRef;
                    fromProp.getValue().get(fromRef);

                    CIMReference toRef;
                    toProp.getValue().get(toRef);

                    String fromObjectName = fromRef.toString();
                    String fromClassName = fromRef.getClassName();
                    String fromPropertyName = fromProp.getName();
                    String toObjectName = toRef.toString();
                    String toClassName = toRef.getClassName();
                    String toPropertyName = toProp.getName();

                    AssocInstTable::append(
                        os,
                        assocInstanceName,
                        assocClassName,
                        fromObjectName,
                        fromClassName,
                        fromPropertyName,
                        toObjectName,
                        toClassName,
                        toPropertyName);
                }
            }
        }
    }
}

CIMReference CIMRepository::createInstance(
    const String& nameSpace,
    const CIMInstance& newInstance)
{

    String errMessage;

    // -- Resolve the instance (looks up class):
    CIMInstance cimInstance(newInstance);

    CIMConstClass cimClass;
    cimInstance.resolve(_context, nameSpace, cimClass);
    CIMReference instanceName = cimInstance.getInstanceName(cimClass);

    // -- Make sure the class has keys (otherwise it will be impossible to
    // -- create the instance.

    if (!cimClass.hasKeys())
    {
        errMessage = "class has no keys: ";
        errMessage += cimClass.getClassName();
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED, errMessage);
    }

    // -- Be sure instance does not already exist:

    String className;
    Uint32 dummyIndex;
    Uint32 dummySize;

    if (_getInstanceIndex(nameSpace, instanceName, className, dummySize, 
        dummyIndex, true))
    {
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_ALREADY_EXISTS, 
            instanceName.toString());
    }

    // -- Handle if association:

    if (cimClass.isAssociation())
    {
        _createAssocInstEntries(nameSpace,
            cimClass, cimInstance, instanceName);
    }

    // -- Get instance file path:

    String instanceFilePath = _getInstanceFilePath(nameSpace,
        cimInstance.getClassName());

    // -- Save instance to file:

    Uint32 index;
    Uint32 size;
    if (!_saveInstance(instanceFilePath, cimInstance, index, size))
    {
        errMessage.append("Failed to create instance ");
        errMessage.append(instanceName.toString());
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED, errMessage);
    }

    // -- Make index file entry:

    String indexFilePath = _getIndexFilePath(
        nameSpace, cimInstance.getClassName());

    if (!InstanceIndexFile::insert(indexFilePath, instanceName, size, index))
    {
        errMessage.append("Failed to create instance ");
        errMessage.append(instanceName.toString());
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED, errMessage);
    }

    // -- Rename the temporary index and instance files back to the original

    if (!_renameTempInstanceAndIndexFiles(indexFilePath, instanceFilePath))
    {
        errMessage.append("Unexpected error occurred while creating instance ");
        errMessage.append(instanceName.toString());
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED, errMessage);
    }
    return (instanceName);
}

void CIMRepository::modifyClass(
    const String& nameSpace,
    const CIMClass& modifiedClass)
{


    // -- Resolve the class:
        CIMClass cimClass(modifiedClass);

    cimClass.resolve(_context, nameSpace);

    // -- Check to see if it is okay to modify this class:

    String classFilePath;

    _nameSpaceManager.checkModify(nameSpace, cimClass.getClassName(),
        cimClass.getSuperClassName(), classFilePath);

    // -- Delete the old file containing the class:

    if (!FileSystem::removeFileNoCase(classFilePath))
    {
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED,
            "failed to remove file in CIMRepository::modifyClass()");
    }

    // -- Create new class file:

    _SaveObject(classFilePath, cimClass);
}

void CIMRepository::modifyInstance(
    const String& nameSpace,
    const CIMNamedInstance& modifiedInstance,
    Boolean includeQualifiers,
    const CIMPropertyList& propertyList)
{


    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.getInstance();
        }
        else
        {
            //
            // Replace all the properties in the instance, but keep the
            // original qualifiers on the instance and on the properties
            //

            cimInstance = getInstance(nameSpace,
                modifiedInstance.getInstanceName(), false, true);
            CIMInstance newInstance(
                modifiedInstance.getInstanceName().getClassName());
            CIMInstance givenInstance = modifiedInstance.getInstance();

            //
            // 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; i<givenInstance.getPropertyCount(); i++)
            {
                // Copy the given property value (not qualifiers)
                CIMProperty givenProperty = givenInstance.getProperty(i);
                CIMProperty newProperty(
                    givenProperty.getName(),
                    givenProperty.getValue(),
                    givenProperty.getArraySize(),
                    givenProperty.getReferenceClassName(),
                    givenProperty.getClassOrigin(),
                    givenProperty.getPropagated());

                // Copy the original property qualifiers
                Uint32 origPos =
                    cimInstance.findProperty(newProperty.getName());
                if (origPos != PEG_NOT_FOUND)
                {
                    CIMProperty origProperty = cimInstance.getProperty(origPos);
                    for (Uint32 j=0; j<origProperty.getQualifierCount(); j++)
                    {
                        newProperty.addQualifier(origProperty.getQualifier(i));
                    }
                }

                // Add the newly constructed property to the new instance
                newInstance.addProperty(newProperty);
            }

            // Use the newly merged instance to replace the original instance
            cimInstance = newInstance;
        }
    }
    else
    {
        //
        // Replace only the properties specified in the given instance
        //

        cimInstance = getInstance(nameSpace,
            modifiedInstance.getInstanceName(), false, true);
        CIMInstance givenInstance = modifiedInstance.getInstance();

        // NOTE: Instance qualifiers are not changed when a property list
        // is specified.  Property qualifiers are replaced with the
        // corresponding property values.

        //
        // Loop through the propertyList replacing each property in the original
        //
        for (Uint32 i=0; i<propertyList.getNumProperties(); i++)
        {
            Uint32 origPropPos =
                cimInstance.findProperty(propertyList.getPropertyName(i));
            if (origPropPos != PEG_NOT_FOUND)
            {
                // Case: Property set in original
                CIMProperty origProperty =
                    cimInstance.getProperty(origPropPos);

                // Get the given property value
                Uint32 givenPropPos =
                    givenInstance.findProperty(propertyList.getPropertyName(i));
                if (givenPropPos != PEG_NOT_FOUND)
                {
                    // Case: Property set in original and given
                    CIMProperty givenProperty =
                        givenInstance.getProperty(givenPropPos);

                    // Copy over the property from the given to the original
                    if (includeQualifiers)
                    {
                        // Case: Total property replacement
                        cimInstance.removeProperty(origPropPos);
                        cimInstance.addProperty(givenProperty);
                    }
                    else
                    {
                        // Case: Replace only the property value (not quals)
                        origProperty.setValue(givenProperty.getValue());
                        cimInstance.removeProperty(origPropPos);
                        cimInstance.addProperty(origProperty);
                    }
                }
                else
                {
                    // Case: Property set in original and not in given
                    // Just remove the property (set to null)
                    cimInstance.removeProperty(origPropPos);
                }
            }
            else
            {
                // Case: Property not set in original

                // Get the given property value
                Uint32 givenPropPos =
                    givenInstance.findProperty(propertyList.getPropertyName(i));
                if (givenPropPos != PEG_NOT_FOUND)
                {
                    // Case: Property set in given and not in original
                    CIMProperty givenProperty =
                        givenInstance.getProperty(givenPropPos);

                    // Copy over the property from the given to the original
                    if (includeQualifiers)
                    {
                        // Case: Total property copy
                        cimInstance.addProperty(givenProperty);
                    }
                    else
                    {
                        // Case: Copy only the property value (not qualifiers)
                        CIMProperty newProperty(
                            givenProperty.getName(),
                            givenProperty.getValue(),
                            givenProperty.getArraySize(),
                            givenProperty.getReferenceClassName(),
                            givenProperty.getClassOrigin(),
                            givenProperty.getPropagated());
                        cimInstance.addProperty(newProperty);
                    }
                }
                else
                {
                    // Case: Property not set in original or in given

                    // Nothing to do; just make sure the property name is valid
                    // ATTN: This is not the most efficient solution
                    CIMClass cimClass = getClass(
                        nameSpace, cimInstance.getClassName(), false);
                    if (!cimClass.existsProperty(
                        propertyList.getPropertyName(i)))
                    {
                        // ATTN: This exception may be returned by setProperty
                        throw PEGASUS_CIM_EXCEPTION(
                            CIM_ERR_NO_SUCH_PROPERTY, "modifyInstance()");
                    }
                }
            }
        }
    }

    // -- Resolve the instance (looks up the class):

    CIMConstClass cimClass;
    cimInstance.resolve(_context, nameSpace, cimClass);

    CIMReference instanceName = cimInstance.getInstanceName(cimClass);

    // -- Disallow if instance name is changed by this operation (attempt
    // -- to modify a key property.

    if (instanceName != modifiedInstance.getInstanceName())
    {
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED,
            "Attempted to modify a key property");
    }

    // -- Lookup index of entry from index file:

    String indexFilePath = _getIndexFilePath(
        nameSpace, instanceName.getClassName());

    Uint32 oldSize;
    Uint32 oldIndex;
    Uint32 newSize;
    Uint32 newIndex;

    if (!InstanceIndexFile::lookup(indexFilePath, instanceName, oldSize, 
        oldIndex))
    {
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, instanceName.toString());
    }

    // -- modify the instance file

    String instanceFilePath = _getInstanceFilePath(
        nameSpace, instanceName.getClassName());

    if (!_modifyInstance(instanceFilePath, cimInstance, oldIndex,  oldSize,
        newIndex, newSize))
    {
        errMessage.append("Failed to modify instance ");
        errMessage.append(instanceName.toString());
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED, errMessage);
    }

    // -- modify the instance index file

    if (!InstanceIndexFile::modify(indexFilePath, instanceName,  newSize,
        newIndex))
    {
        errMessage.append("Failed to modify instance ");
        errMessage.append(instanceName.toString());
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED, errMessage);
    }

    // -- Rename the temporary index and instance files back to the original

    if (!_renameTempInstanceAndIndexFiles(indexFilePath, instanceFilePath))
    {
        errMessage.append("Unexpected error occurred while modifying instance ");
        errMessage.append(instanceName.toString());
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED, errMessage);
    }
}

Array<CIMClass> CIMRepository::enumerateClasses(
    const String& nameSpace,
    const String& className,
    Boolean deepInheritance,
    Boolean localOnly,
    Boolean includeQualifiers,
    Boolean includeClassOrigin)
{


    Array<String> classNames;

    _nameSpaceManager.getSubClassNames(
        nameSpace, className, deepInheritance, classNames);

    Array<CIMClass> result;

    for (Uint32 i = 0; i < classNames.size(); i++)
    {
        result.append(getClass(nameSpace, classNames[i], localOnly,
            includeQualifiers, includeClassOrigin));
    }

    return result;
}

Array<String> CIMRepository::enumerateClassNames(
    const String& nameSpace,
    const String& className,
    Boolean deepInheritance)
{



    Array<String> classNames;

    _nameSpaceManager.getSubClassNames(
        nameSpace, className, deepInheritance, classNames);

    return classNames;
}

Array<CIMNamedInstance> CIMRepository::enumerateInstances(
    const String& nameSpace,
    const String& className,
    Boolean deepInheritance,
    Boolean localOnly,
    Boolean includeQualifiers,
    Boolean includeClassOrigin,
    const CIMPropertyList& propertyList)
{



    // -- Get all descendent classes of this class:

    Array<String> classNames;
    _nameSpaceManager.getSubClassNames(nameSpace, className, true, classNames);
    classNames.prepend(className);

    // -- Get all instances for this class and all its descendent classes

    Array<CIMNamedInstance> namedInstances;

    for (Uint32 i = 0; i < classNames.size(); i++)
    {
        if (!_loadAllInstances(nameSpace, classNames[i], namedInstances))
        {
            String errMessage = "Failed to load instances in class ";
            errMessage.append(classNames[i]);
            throw PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED, errMessage);
        }
    }

    return namedInstances;
}

Array<CIMReference> CIMRepository::enumerateInstanceNames(
    const String& nameSpace,
    const String& className)
{



    // -- Get all descendent classes of this class:

    Array<String> classNames;
    _nameSpaceManager.getSubClassNames(nameSpace, className, true, classNames);
    classNames.prepend(className);

    // -- Get instance names from each qualifying instance file for the class:

    Array<CIMReference> instanceNames;
    Array<Uint32> indices;
    Array<Uint32> sizes;

    for (Uint32 i = 0; i < classNames.size(); i++)
    {
        // -- Form the name of the class index file:

        String path = _getIndexFilePath(nameSpace, classNames[i]);

        // Get all instances for that class:

        if (!InstanceIndexFile::appendInstanceNamesTo(path, instanceNames, 
            indices, sizes))
        {
            String errMessage = "Failed to load instance names in class ";
            errMessage.append(classNames[i]);
            throw PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED, errMessage);
        }
        PEGASUS_ASSERT(instanceNames.size() == indices.size());
        PEGASUS_ASSERT(instanceNames.size() == sizes.size());
    }

    return instanceNames;
}

Array<CIMInstance> CIMRepository::execQuery(
    const String& queryLanguage,
    const String& query)
{
    throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_SUPPORTED, "execQuery()");


    return Array<CIMInstance>();
}

Array<CIMObjectWithPath> CIMRepository::associators(
    const String& nameSpace,
    const CIMReference& objectName,
    const String& assocClass,
    const String& resultClass,
    const String& role,
    const String& resultRole,
    Boolean includeQualifiers,
    Boolean includeClassOrigin,
    const CIMPropertyList& propertyList)
{



    Array<CIMReference> names = associatorNames(
        nameSpace,
        objectName,
        assocClass,
        resultClass,
        role,
        resultRole);

    Array<CIMObjectWithPath> result;

    for (Uint32 i = 0, n = names.size(); i < n; i++)
    {
        String tmpNameSpace = names[i].getNameSpace();

        if (tmpNameSpace.size() == 0)
            tmpNameSpace = nameSpace;

        if (names[i].isClassName())
        {
            CIMReference tmpRef = names[i];
            tmpRef.setHost(String());
            tmpRef.setNameSpace(String());

            CIMClass cimClass = getClass(
                tmpNameSpace,
                tmpRef.getClassName(),
                false,
                includeQualifiers,
                includeClassOrigin,
                propertyList);

            CIMObject cimObject(cimClass);
            result.append(CIMObjectWithPath(names[i], cimObject));
        }
        else
        {
            CIMReference tmpRef = names[i];
            tmpRef.setHost(String());
            tmpRef.setNameSpace(String());

            CIMInstance cimInstance = getInstance(
                tmpNameSpace,
                tmpRef,
                false,
                includeQualifiers,
                includeClassOrigin,
                propertyList);

            CIMObject cimObject(cimInstance);
            result.append(CIMObjectWithPath(names[i], cimObject));
        }
    }

    return result;
}

Array<CIMReference> CIMRepository::associatorNames(
    const String& nameSpace,
    const CIMReference& objectName,
    const String& assocClass,
    const String& resultClass,
    const String& role,
    const String& resultRole)
{



    Array<String> associatorNames;

    if (objectName.isClassName())
    {
        String assocFileName = _MakeAssocClassPath(nameSpace, _repositoryRoot);

        AssocClassTable::getAssociatorNames(
            assocFileName,
            objectName.toString(),
            assocClass,
            resultClass,
            role,
            resultRole,
            associatorNames);
    }
    else
    {
        String assocFileName = _MakeAssocInstPath(nameSpace, _repositoryRoot);

        AssocInstTable::getAssociatorNames(
            assocFileName,
            objectName,
            assocClass,
            resultClass,
            role,
            resultRole,
            associatorNames);
    }

    Array<CIMReference> result;

    for (Uint32 i = 0, n = associatorNames.size(); i < n; i++)
    {
        CIMReference r = associatorNames[i];

        if (r.getHost().size() == 0)
            r.setHost(System::getHostName());

        if (r.getNameSpace().size() == 0)
            r.setNameSpace(nameSpace);

        result.append(r);
    }

    return result;
}

Array<CIMObjectWithPath> CIMRepository::references(
    const String& nameSpace,
    const CIMReference& objectName,
    const String& resultClass,
    const String& role,
    Boolean includeQualifiers,
    Boolean includeClassOrigin,
    const CIMPropertyList& propertyList)
{



    Array<CIMReference> names = referenceNames(
        nameSpace,
        objectName,
        resultClass,
        role);

    Array<CIMObjectWithPath> result;

    for (Uint32 i = 0, n = names.size(); i < n; i++)
    {
        String tmpNameSpace = names[i].getNameSpace();

        if (tmpNameSpace.size() == 0)
            tmpNameSpace = nameSpace;

        // ATTN: getInstance() should this be able to handle instance names
        // with host names and namespaces?

        CIMReference tmpRef = names[i];
        tmpRef.setHost(String());
        tmpRef.setNameSpace(String());

        if (objectName.isClassName())
        {
            CIMClass cimClass = getClass(
                tmpNameSpace,
                tmpRef.getClassName(),
                false,
                includeQualifiers,
                includeClassOrigin,
                propertyList);

            result.append(CIMObjectWithPath(names[i], cimClass));
        }
        else
        {
            CIMInstance instance = getInstance(
                tmpNameSpace,
                tmpRef,
                false,
                includeQualifiers,
                includeClassOrigin,
                propertyList);

            result.append(CIMObjectWithPath(names[i], instance));
        }
    }

    return result;
}

Array<CIMReference> CIMRepository::referenceNames(
    const String& nameSpace,
    const CIMReference& objectName,
    const String& resultClass,
    const String& role)
{



    Array<String> tmpReferenceNames;

    if (objectName.isClassName())
    {
        String assocFileName = _MakeAssocClassPath(nameSpace, _repositoryRoot);

        if (!AssocClassTable::getReferenceNames(
            assocFileName,
            objectName.getClassName(),
            resultClass,
            role,
            tmpReferenceNames))
        {
            // Ignore error! It's okay not to have references.
        }
    }
    else
    {
        String assocFileName = _MakeAssocInstPath(nameSpace, _repositoryRoot);

        if (!AssocInstTable::getReferenceNames(
            assocFileName,
            objectName,
            resultClass,
            role,
            tmpReferenceNames))
        {
            // Ignore error! It's okay not to have references.
        }
    }

    Array<CIMReference> result;

    for (Uint32 i = 0, n = tmpReferenceNames.size(); i < n; i++)
    {
        CIMReference r = tmpReferenceNames[i];

        if (r.getHost().size() == 0)
            r.setHost(System::getHostName());

        if (r.getNameSpace().size() == 0)
            r.setNameSpace(nameSpace);

        result.append(r);
    }

    return result;
}

CIMValue CIMRepository::getProperty(
    const String& nameSpace,
    const CIMReference& instanceName,
    const String& propertyName)
{




    // -- Get the index for this instance:

    String className;
    Uint32 index;
    Uint32 size;

    if (!_getInstanceIndex(nameSpace, instanceName, className, size, index))
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, instanceName.toString());

    // -- Load the instance into memory:

    String path = _getInstanceFilePath(nameSpace, className);
    CIMInstance cimInstance;
    if (!_loadInstance(path, cimInstance, index, size))
    {
        throw CannotOpenFile(path);
    }

    // -- Grab the property from the instance:

    Uint32 pos = cimInstance.findProperty(propertyName);

    // ATTN: This breaks if the property is simply null
    if (pos == PEGASUS_NOT_FOUND)
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NO_SUCH_PROPERTY, "getProperty()");

    CIMProperty prop = cimInstance.getProperty(pos);

    // -- Return the value:

    return prop.getValue();
}

void CIMRepository::setProperty(
    const String& nameSpace,
    const CIMReference& instanceName,
    const String& propertyName,
    const CIMValue& newValue)
{



    //
    // Create the instance to pass to modifyInstance()
    //
    CIMInstance instance(instanceName.getClassName());
    // ATTN: Is this the correct construction for this property?
    instance.addProperty(CIMProperty(propertyName, newValue));
    CIMNamedInstance namedInstance(instanceName, instance);

    //
    // Create the propertyList to pass to modifyInstance()
    //
    Array<String> propertyListArray;
    propertyListArray.append(propertyName);
    CIMPropertyList propertyList(propertyListArray);

    //
    // Modify the instance to set the value of the given property
    //
    modifyInstance(nameSpace, namedInstance, false, propertyList);
}

CIMQualifierDecl CIMRepository::getQualifier(
    const String& nameSpace,
    const String& qualifierName)
{



    // -- Get path of qualifier file:

    String qualifierFilePath = _nameSpaceManager.getQualifierFilePath(
        nameSpace, qualifierName);

    // -- Load qualifier:

    CIMQualifierDecl qualifierDecl;

    try
    {
        _LoadObject(qualifierFilePath, qualifierDecl);
    }
    catch (CannotOpenFile&)
    {
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, qualifierName);
    }

    return qualifierDecl;
}

void CIMRepository::setQualifier(
    const String& nameSpace,
    const CIMQualifierDecl& qualifierDecl)
{



    // -- Get path of qualifier file:

    String qualifierFilePath = _nameSpaceManager.getQualifierFilePath(
        nameSpace, qualifierDecl.getName());

    // -- If qualifier alread exists, throw exception:

    if (FileSystem::existsNoCase(qualifierFilePath))
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_ALREADY_EXISTS, qualifierDecl.getName());

    // -- Save qualifier:

    _SaveObject(qualifierFilePath, qualifierDecl);
}

void CIMRepository::deleteQualifier(
    const String& nameSpace,
    const String& qualifierName)
{



    // -- Get path of qualifier file:

    String qualifierFilePath = _nameSpaceManager.getQualifierFilePath(
        nameSpace, qualifierName);

    // -- Delete qualifier:

    if (!FileSystem::removeFileNoCase(qualifierFilePath))
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_FOUND, qualifierName);
}

Array<CIMQualifierDecl> CIMRepository::enumerateQualifiers(
    const String& nameSpace)
{



    String qualifiersRoot = _nameSpaceManager.getQualifiersRoot(nameSpace);

    Array<String> qualifierNames;

    if (!FileSystem::getDirectoryContents(qualifiersRoot, qualifierNames))
    {
        throw PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED,
            "enumerateQualifiers(): internal error");
    }

    Array<CIMQualifierDecl> qualifiers;

    for (Uint32 i = 0; i < qualifierNames.size(); i++)
    {
        CIMQualifierDecl qualifier = getQualifier(nameSpace, qualifierNames[i]);
        qualifiers.append(qualifier);
    }

    return qualifiers;
}

CIMValue CIMRepository::invokeMethod(
    const String& nameSpace,
    const CIMReference& instanceName,
    const String& methodName,
    const Array<CIMValue>& inParameters,
    Array<CIMValue>& outParameters)
{
    throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_SUPPORTED, "invokeMethod()");



    return CIMValue();
}

void CIMRepository::createNameSpace(const String& nameSpace)
{


    _nameSpaceManager.createNameSpace(nameSpace);
}

Array<String> CIMRepository::enumerateNameSpaces() const
{


    Array<String> nameSpaceNames;
    _nameSpaceManager.getNameSpaceNames(nameSpaceNames);
    return nameSpaceNames;
}

void CIMRepository::deleteNameSpace(const String& nameSpace)
{



    _nameSpaceManager.deleteNameSpace(nameSpace);
}

//----------------------------------------------------------------------
//
// _getIndexFilePath()
//
//      returns the file path of the instance index file. 
//
//----------------------------------------------------------------------

String CIMRepository::_getIndexFilePath(
    const String& nameSpace,
    const String& className) const
{
    String tmp = _nameSpaceManager.getInstanceFileBase(nameSpace, className);
    tmp.append(".idx");
    return tmp;
}

//----------------------------------------------------------------------
//
// _getInstanceFilePath()
//
//      returns the file path of the instance file. 
//
//----------------------------------------------------------------------

String CIMRepository::_getInstanceFilePath(
    const String& nameSpace,
    const String& className) const
{
    String tmp = _nameSpaceManager.getInstanceFileBase(nameSpace, className);
    tmp.append(".instances");
    return tmp;
}

//----------------------------------------------------------------------
//
// _loadInstance()
//
//      Loads an instance object from disk to memory.  Returns true on 
//      success.
//
//----------------------------------------------------------------------

Boolean CIMRepository::_loadInstance(
    const String& path,
    CIMInstance& object,
    Uint32 index,
    Uint32 size)
{
    // Load instance from instance file into memory:


    Array<Sint8> data;
    if (!InstanceFile::loadInstance(path, index, size, data))
    {
        return false;
    }

    XmlParser parser((char*)data.getData());

    XmlReader::getObject(parser, object);

    return true;
}

//----------------------------------------------------------------------
//
// _loadAllInstances()
//
//      Loads all the instance objects for a given class from disk to memory. 
//      Returns true on success.
//
//----------------------------------------------------------------------

Boolean CIMRepository::_loadAllInstances(
    const String& nameSpace,
    const String& className,
    Array<CIMNamedInstance>& namedInstances)
{
    Array<CIMReference> instanceNames;
    Array<Sint8> data;
    Array<Uint32> indices;
    Array<Uint32> sizes;

    //
    // Form the name of the instance index file
    //
    String indexFilePath = _getIndexFilePath(nameSpace, className);

    //
    // Form the name of the instance file
    //
    String instanceFilePath = _getInstanceFilePath(nameSpace, className);

    //
    // Get all instance names and record information from the index file
    //
    if (!InstanceIndexFile::appendInstanceNamesTo(
        indexFilePath, instanceNames, indices, sizes))
    {
        return false;
    }
    PEGASUS_ASSERT(instanceNames.size() == indices.size());
    PEGASUS_ASSERT(instanceNames.size() == sizes.size());
   
    //
    // Load all instance data from the instance file
    //
    if (instanceNames.size() > 0)
    {
        if (!InstanceFile::loadAllInstances(instanceFilePath, data))
        {
            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++)
        {
            XmlParser parser(&(buffer[indices[i]]));

            XmlReader::getObject(parser, tmpInstance);

            namedInstances.append(CIMNamedInstance(instanceNames[i], tmpInstance));
        }
    }

    return true;
}

//----------------------------------------------------------------------
//
// _saveInstance()
//
//      Saves an instance object from memory to disk file.  Returns true
//      on success.
//
//----------------------------------------------------------------------

Boolean CIMRepository::_saveInstance(
    const String& path,
    const CIMInstance& object,
    Uint32& index,
    Uint32& size)
{
    Array<Sint8> out;
    object.toXml(out);

    if (!InstanceFile::insertInstance(out, path, index, size))
    {
        return false;
    }

    return true;
}

//----------------------------------------------------------------------
//
// _modifyInstance()
//
//      Modifies an instance object saved in the disk file.  Returns true
//      on success.
//
//----------------------------------------------------------------------

Boolean CIMRepository::_modifyInstance(
    const String& path,
    const CIMInstance& object,
    Uint32 oldIndex,
    Uint32 oldSize,
    Uint32& newIndex,
    Uint32& newSize)
{
    Array<Sint8> out;
    object.toXml(out);

    if (!InstanceFile::modifyInstance(out, path, oldIndex, oldSize, newIndex, 
                                      newSize))
    {
        return false;
    }

    return true;
}

//------------------------------------------------------------------------------
//
// _renameTempInstanceAndIndexFiles()
//
//      Renames the temporary instance and instance index files back to the
//      original files.  The temporary files were created for an insert,
//      remove, or modify operation (to avoid data inconsistency between
//      the two files in case of unexpected system termination or failure).  
//      This method is called after a successful insert, remove, or modify
//      operation on BOTH the index file and the instance file.  Returns
//      true on success.
//
//------------------------------------------------------------------------------

Boolean CIMRepository::_renameTempInstanceAndIndexFiles(
    const String& indexFilePath, 
    const String& instanceFilePath) 
{
    //
    // Rename the original files to backup files
    // 
    // This is done so that we would not lose the original files if an error
    // occurs in renaming the temporary files back after the original files
    // have been removed.
    //
    String realIndexFilePath;
    if (FileSystem::existsNoCase(indexFilePath, realIndexFilePath))
    {
        if (!FileSystem::renameFile(realIndexFilePath, 
                                    realIndexFilePath + ".orig"))
            return false;
    }
    else
    {
        realIndexFilePath = indexFilePath;
    }

    String realInstanceFilePath;
    if (FileSystem::existsNoCase(instanceFilePath, realInstanceFilePath))
    {
        if (!FileSystem::renameFile(realInstanceFilePath, 
                                    realInstanceFilePath + ".orig"))
            return false;
    }
    else
    {
        realInstanceFilePath = instanceFilePath;
    }

    //
    // Rename the temporary instance and index files back to be the original
    // files.
    //
    // If the index file is now empty (zero size), delete the temporary 
    // files instead.
    //
    Uint32 fileSize;
    String tmpIndexFilePath = realIndexFilePath + ".tmp";
    String tmpInstanceFilePath = realInstanceFilePath + ".tmp";

    if (!FileSystem::getFileSizeNoCase(tmpIndexFilePath, fileSize))
        return false;

    if (fileSize == 0)
    {
        if (!FileSystem::removeFileNoCase(tmpIndexFilePath))
            return false;

        if (!FileSystem::removeFileNoCase(tmpInstanceFilePath))
            return false;
    }
    else
    {
        if (!FileSystem::renameFile(tmpIndexFilePath, realIndexFilePath))
            return false;

        if (!FileSystem::renameFile(tmpInstanceFilePath, realInstanceFilePath))
            return false;
    }

    //
    // Now remove the backup files 
    //
    FileSystem::removeFile(realIndexFilePath + ".orig");
    FileSystem::removeFile(realInstanceFilePath + ".orig");

    return true;
}

void CIMRepository::setDeclContext(RepositoryDeclContext *context)
{
  _context = context;
}

PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2