void doCreate(const char *partname, const char *xml, unsigned updateFlags, StringArray &filesNotFound)
    {
        createPart(partname, xml);

        if (pmExisting)
        {
            if (!checkFlag(PKGADD_MAP_REPLACE))
                throw MakeStringException(PKG_NAME_EXISTS, "PackageMap %s already exists, either delete it or specify overwrite", pmid.str());
        }

        cloneDfsInfo(updateFlags, filesNotFound);

        if (pmExisting)
            packageMaps->removeTree(pmExisting);

        Owned<IPropertyTree> pmTree = createPTree("PackageMap", ipt_ordered);
        pmTree->setProp("@id", pmid);
        pmTree->setPropBool("@multipart", true);
        pmTree->addPropTree("Part", pmPart.getClear());
        packageMaps->addPropTree("PackageMap", pmTree.getClear());

        VStringBuffer xpath("PackageMap[@id='%s'][@querySet='%s']", pmid.str(), target.get());
        Owned<IPropertyTree> pkgSet = getPkgSetRegistry(process, false);
        IPropertyTree *psEntry = pkgSet->queryPropTree(xpath);

        if (!psEntry)
        {
            psEntry = pkgSet->addPropTree("PackageMap", createPTree("PackageMap"));
            psEntry->setProp("@id", pmid);
            psEntry->setProp("@querySet", target);
        }
        makePackageActive(pkgSet, psEntry, target, checkFlag(PKGADD_MAP_ACTIVATE));
    }
void activatePackageMapInfo(const char *target, const char *name, const char *process, bool globalScope, bool activate)
{
    if (!target || !*target)
        throw MakeStringExceptionDirect(PKG_TARGET_NOT_DEFINED, "No target defined");

    if (!name || !*name)
        throw MakeStringExceptionDirect(PKG_MISSING_PARAM, "No pmid specified");

    Owned<IRemoteConnection> globalLock = querySDS().connect("PackageSets", myProcessSession(), RTM_LOCK_WRITE|RTM_CREATE_QUERY, SDS_LOCK_TIMEOUT);
    if (!globalLock)
        throw MakeStringException(PKG_DALI_LOOKUP_ERROR, "Unable to retrieve PackageSets information from dali /PackageSets");

    StringBuffer lcTarget(target);
    target = lcTarget.toLowerCase().str();

    StringBuffer lcName(name);
    name = lcName.toLowerCase().str();

    IPropertyTree *root = globalLock->queryRoot();
    if (!root)
        throw MakeStringException(PKG_ACTIVATE_NOT_FOUND, "Unable to retrieve PackageSet information");

    StringBuffer pkgSetId;
    buildPkgSetId(pkgSetId, process);
    VStringBuffer xpath("PackageSet[@id='%s']", pkgSetId.str());
    IPropertyTree *pkgSetTree = root->queryPropTree(xpath);
    if (pkgSetTree)
    {
        IPropertyTree *mapTree = NULL;
        if (!globalScope)
        {
            xpath.clear().appendf("PackageMap[@querySet='%s'][@id='%s::%s']", target, target, name);
            mapTree = pkgSetTree->queryPropTree(xpath);
        }
        if (!mapTree)
        {
            xpath.clear().appendf("PackageMap[@querySet='%s'][@id='%s']", target, name);
            mapTree = pkgSetTree->queryPropTree(xpath);
        }
        if (!mapTree)
            throw MakeStringException(PKG_ACTIVATE_NOT_FOUND, "PackageMap %s not found on target %s", name, target);
        makePackageActive(pkgSetTree, mapTree, target, activate);
    }
}
void addPackageMapInfo(const char *xml, StringArray &filesNotFound, const char *process, const char *target, const char *pmid, const char *packageSetName, const char *lookupDaliIp, const char *srcCluster, const char *prefix, bool activate, bool overWrite, IUserDescriptor* userdesc, bool allowForeignFiles, bool preloadAll)
{
    if (!xml || !*xml)
        throw MakeStringExceptionDirect(PKG_INFO_NOT_DEFINED, "PackageMap info not provided");

    if (srcCluster && *srcCluster)
    {
        if (!isProcessCluster(lookupDaliIp, srcCluster))
            throw MakeStringException(PKG_INVALID_CLUSTER_TYPE, "Process cluster %s not found on %s DALI", srcCluster, lookupDaliIp ? lookupDaliIp : "local");
    }

    Owned<IConstWUClusterInfo> clusterInfo = getTargetClusterInfo(target);
    if (!clusterInfo)
        throw MakeStringException(PKG_TARGET_NOT_DEFINED, "Could not find information about target cluster %s ", target);

    Owned<IPropertyTree> pmTree = createPTreeFromXMLString(xml);
    if (!pmTree)
        throw MakeStringExceptionDirect(PKG_INFO_NOT_DEFINED, "Invalid PackageMap info");

    StringBuffer lcPmid(pmid);
    pmid = lcPmid.toLowerCase().str();
    pmTree->setProp("@id", pmid);

    Owned<IPropertyTreeIterator> iter = pmTree->getElements("Package");
    ForEach(*iter)
    {
        IPropertyTree &item = iter->query();
        if (preloadAll)
            item.setPropBool("@preload", true);
        Owned<IPropertyTreeIterator> superFiles = item.getElements("SuperFile");
        ForEach(*superFiles)
        {
            IPropertyTree &superFile = superFiles->query();
            StringBuffer lc(superFile.queryProp("@id"));
            const char *id = lc.toLowerCase().str();
            if (*id == '~')
                id++;
            superFile.setProp("@id", id);

            Owned<IPropertyTreeIterator> subFiles = superFile.getElements("SubFile");
            ForEach(*subFiles)
            {
                IPropertyTree &subFile = subFiles->query();
                id = subFile.queryProp("@value");
                if (id && *id == '~')
                {
                    StringAttr value(id+1);
                    subFile.setProp("@value", value.get());
                }
            }
        }
    }

    VStringBuffer xpath("PackageMap[@id='%s']", pmid);
    Owned<IRemoteConnection> globalLock = querySDS().connect("/PackageMaps", myProcessSession(), RTM_LOCK_WRITE|RTM_CREATE_QUERY, SDS_LOCK_TIMEOUT);
    IPropertyTree *packageMaps = globalLock->queryRoot();
    IPropertyTree *pmExisting = packageMaps->queryPropTree(xpath);

    xpath.appendf("[@querySet='%s']", target);
    Owned<IPropertyTree> pkgSet = getPkgSetRegistry(process, false);
    IPropertyTree *psEntry = pkgSet->queryPropTree(xpath);

    if (!overWrite && (psEntry || pmExisting))
        throw MakeStringException(PKG_NAME_EXISTS, "Package name %s already exists, either delete it or specify overwrite", pmid);

    cloneFileInfoToDali(filesNotFound, pmTree, lookupDaliIp, clusterInfo, srcCluster, prefix, overWrite, userdesc, allowForeignFiles);

    if (pmExisting)
        packageMaps->removeTree(pmExisting);
    packageMaps->addPropTree("PackageMap", pmTree.getClear());

    if (!psEntry)
    {
        psEntry = pkgSet->addPropTree("PackageMap", createPTree("PackageMap"));
        psEntry->setProp("@id", pmid);
        psEntry->setProp("@querySet", target);
    }
    makePackageActive(pkgSet, psEntry, target, activate);
}