/**
      Lookup the instance representation, given keys provided from CIMOM

      \param[in]    keys   SCXInstance with property keys set
      \returns             Pointer to located instance

      \throws              SCXInvalidArgumentException
      \throws              SCXInternalErrorException
      \throws              SCXCIMInstanceNotFound   The instance with given keys cannot be found

      This method knows which the key properties of the entity are and returns
      pointer to that item if found.

    */
    SCXCoreLib::SCXHandle<SCXSystemLib::ProcessInstance> ProcessProvider::FindInstance(const SCXInstance& keys) const // private
    {
        // Start by extracting all key properties
        ValidateScopingOperatingSystemKeys(keys);
        SupportedCimClasses cimtype = static_cast<SupportedCimClasses>(m_ProviderCapabilities.GetCimClassId(keys));
        if (eSCX_UnixProcessStatisticalInformation == cimtype) {
            ValidateKeyValue(L"ProcessCreationClassName", keys, L"SCX_UnixProcessStatisticalInformation");
            GetKeyRef(L"Name", keys);
        } else if (eSCX_UnixProcess == cimtype) {
            ValidateKeyValue(L"CreationClassName", keys, L"SCX_UnixProcess");
        } else {
            throw SCXInvalidStateException(L"Unknown cimtype value", SCXSRCLOCATION);
        }

        const SCXProperty &pidprop = GetKeyRef(L"Handle", keys);
        scxulong pid;

        for(size_t i=0; i<m_processes->Size(); i++)
        {
            SCXCoreLib::SCXHandle<SCXSystemLib::ProcessInstance> testinst = m_processes->GetInstance(i);
            if (testinst == NULL)
            {
                throw SCXInternalErrorException(L"Instance from list not an ProcessInstance", SCXSRCLOCATION);
            }
            // Compare key values of input args and the current instance
            testinst->GetPID(pid);
            if (StrFrom(pid) == pidprop.GetStrValue())
            {
                // Match
                return testinst;
            }
        }

        // As last resort, check if we the request is for the _Total instance
        if (m_processes->GetTotalInstance() != 0)
        {
            SCXCoreLib::SCXHandle<SCXSystemLib::ProcessInstance> testinst = m_processes->GetTotalInstance();
            if (testinst == NULL)
            {
                throw SCXInternalErrorException(L"Total instance not a ProcessInstance", SCXSRCLOCATION);
            }
            testinst->GetPID(pid);
            if (StrFrom(pid) == pidprop.GetStrValue())
            {
                return testinst;
            }
        }


        throw SCXCIMInstanceNotFound(keys.DumpString(), SCXSRCLOCATION);
    }
    /**
       Add a SCXInstance with the name property set frmo the ProcessInstance to the collection

       \param[in]   processinst    Process instance to get data from
       \param[out]  inst           Instance to add keys to
       \param[in]   cimtype        Type of CIM Class to return

       \throws      SCXInvalidArgumentException - The instance can not be converted to a ProcessInstance

       This method contains knowledge on which are the key fields for the class.
       The key properties are defined in the MOF file.

    */
    void ProcessProvider::AddKeys(SCXCoreLib::SCXHandle<SCXSystemLib::ProcessInstance> processinst, SCXInstance &inst, SupportedCimClasses cimtype) // private
    {
        SCX_LOGTRACE(m_log, L"ProcessProvider AddKeys()");

        if (processinst == NULL)
        {
            throw SCXInvalidArgumentException(L"einst", L"Not a ProcessInstance", SCXSRCLOCATION);
        }

        scxulong pid;
        if (processinst->GetPID(pid))
        {
            SCXProperty pid_prop(L"Handle", StrFrom(pid));
            inst.AddKey(pid_prop);
        }

        AddScopingOperatingSystemKeys(inst);
        if (eSCX_UnixProcessStatisticalInformation == cimtype)
        {
            std::string name;
            if (processinst->GetName(name))
            {
                SCXProperty name_prop(L"Name", StrFromMultibyte(name));
                inst.AddKey(name_prop);
                SCXProperty creationClass_prop(L"ProcessCreationClassName", L"SCX_UnixProcessStatisticalInformation");
                inst.AddKey(creationClass_prop);
            }
        }
        else if (eSCX_UnixProcess == cimtype)
        {
            SCXProperty creationClass_prop(L"CreationClassName", L"SCX_UnixProcess");
            inst.AddKey(creationClass_prop);
        }

    }
MI_BEGIN_NAMESPACE

static void EnumerateOneInstance(Context& context,
        SCX_UnixProcessStatisticalInformation_Class& inst, bool keysOnly,
        SCXCoreLib::SCXHandle<SCXSystemLib::ProcessInstance> processinst)
{
    SCXLogHandle& log = SCXCore::g_ProcessProvider.GetLogHandle();

    // Add the key properties first.
    scxulong pid;
    if (processinst->GetPID(pid))
    {
        inst.Handle_value(StrToUTF8(StrFrom(pid)).c_str());
    }

    // Add keys of scoping operating system
    try {
        SCXCoreLib::NameResolver mi;
        inst.CSName_value(StrToMultibyte(mi.GetHostDomainname()).c_str());
    } catch (SCXException& e){
        SCX_LOGWARNING(log, StrAppend(
                    StrAppend(L"Can't read host/domainname because ", e.What()),
                    e.Where()));
    }

    try {
        SCXSystemLib::SCXOSTypeInfo osinfo;
        inst.OSName_value(StrToMultibyte(osinfo.GetOSName(true)).c_str());
    } catch (SCXException& e){
        SCX_LOGWARNING(log, StrAppend(
                    StrAppend(L"Can't read OS name because ", e.What()),
                    e.Where()));
    }

    inst.CSCreationClassName_value("SCX_ComputerSystem");
    inst.OSCreationClassName_value("SCX_OperatingSystem");
    inst.ProcessCreationClassName_value("SCX_UnixProcessStatisticalInformation");

    std::string name;
    if (processinst->GetName(name))
    {
        inst.Name_value(name.c_str());
    }

    if (!keysOnly)
    {
        unsigned int uint = 0;
        scxulong ulong = 0;

        inst.Description_value("A snapshot of a current process");
        inst.Caption_value("Unix process information");

        if (processinst->GetRealData(ulong))
        {
            inst.RealData_value(ulong);
        }

        if (processinst->GetRealStack(ulong))
        {
            inst.RealStack_value(ulong);
        }

        if (processinst->GetVirtualText(ulong))
        {
            inst.VirtualText_value(ulong);
        }

        if (processinst->GetVirtualData(ulong))
        {
            inst.VirtualData_value(ulong);
        }

        if (processinst->GetVirtualStack(ulong))
        {
            inst.VirtualStack_value(ulong);
        }

        if (processinst->GetVirtualMemoryMappedFileSize(ulong))
        {
            inst.VirtualMemoryMappedFileSize_value(ulong);
        }

        if (processinst->GetVirtualSharedMemory(ulong))
        {
            inst.VirtualSharedMemory_value(ulong);
        }

        if (processinst->GetCpuTimeDeadChildren(ulong))
        {
            inst.CpuTimeDeadChildren_value(ulong);
        }

        if (processinst->GetSystemTimeDeadChildren(ulong))
        {
            inst.SystemTimeDeadChildren_value(ulong);
        }

        if (processinst->GetRealText(ulong))
        {
            inst.RealText_value(ulong);
        }

        if (processinst->GetCPUTime(uint))
        {
            inst.CPUTime_value(uint);
        }

        if (processinst->GetBlockWritesPerSecond(ulong))
        {
            inst.BlockWritesPerSecond_value(ulong);
        }

        if (processinst->GetBlockReadsPerSecond(ulong))
        {
            inst.BlockReadsPerSecond_value(ulong);
        }

        if (processinst->GetBlockTransfersPerSecond(ulong))
        {
            inst.BlockTransfersPerSecond_value(ulong);
        }

        if (processinst->GetPercentUserTime(ulong))
        {
            inst.PercentUserTime_value((unsigned char) ulong);
        }

        if (processinst->GetPercentPrivilegedTime(ulong))
        {
            inst.PercentPrivilegedTime_value((unsigned char) ulong);
        }

        if (processinst->GetUsedMemory(ulong))
        {
            inst.UsedMemory_value(ulong);
        }

        if (processinst->GetPercentUsedMemory(ulong))
        {
            inst.PercentUsedMemory_value((unsigned char) ulong);
        }

        if (processinst->GetPagesReadPerSec(ulong))
        {
            inst.PagesReadPerSec_value(ulong);
        }
    }
    context.Post(inst);
}