static IConstWorkUnit *getWorkunit(ICodeContext * ctx)
{
    StringAttr wuid;
    wuid.setown(ctx->getWuid());
    // One assumes we have read access to our own wu
    return getWorkunit(ctx, wuid);
}
 virtual int run()
 {
     int access = 0;
     int total = 0, mint = -1, maxt = 0;
     for(int i = 0; i < m_rounds; i++)
     {
         time_t start, stop;
         time(&start);
         {
             //synchronized block(m_mutex);
             Owned<ISecUser> usr = m_secmgr->createUser(m_user.get());
             usr->credentials().setPassword(m_passwd.get());
             //access = m_secmgr->authorizeFileScope(*usr, m_resource.get());
             access = m_secmgr->authorizeEx(m_rtype, *usr, m_resource.get());
         }
         time(&stop);
         int span = (int)(stop - start);
         total += span;
         if(mint == -1 || mint > span)
             mint = span;
         if(maxt < span)
             maxt = span;
         if((i+1)%100 == 0)
             DBGLOG("Finished %d times\n", i+1);
     }
     DBGLOG("Permission: %d, min: %d, max: %d, average:%f", access, mint, maxt, total*1.0/m_rounds);
     return 0;
 }
static IConstWorkUnit * getWorkunit(ICodeContext * ctx)
{
    Owned<IWorkUnitFactory> factory = getWorkUnitFactory();
    StringAttr wuid;
    wuid.setown(ctx->getWuid());
    return factory->openWorkUnit(wuid, false);
}
Example #4
0
void splitXmlTagNamesFromXPath(const char *xpath, StringAttr &inner, StringAttr *outer=NULL)
{
    if (!xpath || !xpath)
        return;

    StringBuffer s1;
    StringBuffer s2;

    appendNextXpathName(s1, xpath);
    if (outer && xpath)
        appendNextXpathName(s2, ++xpath);
    if (xpath) //xpath too deep
        return;

    if (!s2.length())
        inner.set(s1.str());
    else
    {
        inner.set(s2.str());
        outer->set(s1.str());
    }
    if (!inner.get())
        inner.set("");
    if (outer && !outer->get())
        outer->set("");
}
Example #5
0
    bool finalizeOptions(IProperties *globals)
    {
        if (optInput.length())
        {
            const char *in = optInput.get();
            while (*in && isspace(*in)) in++;
            if (*in!='<')
            {
                StringBuffer content;
                content.loadFile(in);
                optInput.set(content.str());
            }
        }

        if (optESDLDefID.isEmpty())
            throw MakeStringException( 0, "ESDL definition ID must be provided!" );

        if (optESDLService.isEmpty())
            throw MakeStringException( 0, "ESDL service definition name must be provided!" );

        if(optTargetESPProcName.isEmpty())
            throw MakeStringException( 0, "Name of Target ESP process must be provided!" );

        if (optPortOrName.isEmpty())
            throw MakeStringException( 0, "Either the target ESP service port of name must be provided!" );
        else
        {
            const char * portorname =  optPortOrName.get();
            isdigit(*portorname) ? optTargetPort.set(portorname) : optService.set(portorname);
        }

        return EsdlPublishCmdCommon::finalizeOptions(globals);
    }
Example #6
0
static void splitGitFileName(const char *fullName, StringAttr &gitDir, StringAttr &revision, StringAttr &relPath)
{
    assertex(fullName);
    const char *git = strstr(fullName, ".git" PATHSEPSTR "{" );
    assertex(git);
    const char *tail = git+5;
    gitDir.set(fullName, tail-fullName);
    assertex (*tail=='{');
    tail++;
    const char *end = strchr(tail, '}');
    if (!end)
        throw MakeStringException(0, "Invalid git repository filename - no matching } found");
    revision.set(tail, end - tail);
    tail = end+1;
    if (*tail==PATHSEPCHAR)
        tail++;
    else if (*tail != 0)
        throw MakeStringException(0, "Invalid git repository filename - " PATHSEPSTR " expected after }");
    if (tail && *tail)
    {
        StringBuffer s(tail);
        s.replace(PATHSEPCHAR, '/');
        relPath.set(s);
    }
    else
        relPath.clear();
    // Check it's a valid git repository
    StringBuffer configName(gitDir);
    configName.append("config");
    if (!checkFileExists(configName.str()))
        throw MakeStringException(0, "Invalid git repository - config file %s not found", configName.str());
}
Example #7
0
static void splitArchivedFileName(const char *fullName, StringAttr &container, StringAttr &option, StringAttr &relPath)
{
    const char *tail = splitName(fullName);
    assertex(tail);
    size_t containerLen = tail-fullName;
    if (fullName[containerLen-1]==PATHSEPCHAR)
        containerLen--;
    container.set(fullName, containerLen);
    if (*tail=='{')
    {
        tail++;
        const char *end = strchr(tail, '}');
        if (!end)
            throw MakeStringException(0, "Invalid archive-embedded filename - no matching } found");
        option.set(tail, end - tail);
        tail = end+1;
        if (*tail==PATHSEPCHAR)
            tail++;
        else if (*tail != 0)
            throw MakeStringException(0, "Invalid archive-embedded filename - " PATHSEPSTR " expected after }");
    }
    else
        option.clear();
    if (tail && *tail)
    {
        StringBuffer s(tail);
        s.replace(PATHSEPCHAR, '/');
        relPath.set(s);
    }
    else
        relPath.clear();
}
Example #8
0
eclCmdOptionMatchIndicator EclCmdCommon::matchCommandLineOption(ArgvIterator &iter, bool finalAttempt)
{
    bool boolValue;
    if (iter.matchFlag(boolValue, ECLOPT_VERSION))
    {
        fprintf(stdout, "%s\n", BUILD_TAG);
        return EclCmdOptionCompletion;
    }
    if (iter.matchOption(optServer, ECLOPT_SERVER)||iter.matchOption(optServer, ECLOPT_SERVER_S))
        return EclCmdOptionMatch;
    if (iter.matchOption(optPort, ECLOPT_PORT))
        return EclCmdOptionMatch;
    if (iter.matchOption(optUsername, ECLOPT_USERNAME)||iter.matchOption(optUsername, ECLOPT_USERNAME_S))
        return EclCmdOptionMatch;
    if (iter.matchOption(optPassword, ECLOPT_PASSWORD)||iter.matchOption(optPassword, ECLOPT_PASSWORD_S))
        return EclCmdOptionMatch;
    if (iter.matchFlag(optVerbose, ECLOPT_VERBOSE) || iter.matchFlag(optVerbose, ECLOPT_VERBOSE_S))
        return EclCmdOptionMatch;

    StringAttr tempArg;
    if (iter.matchOption(tempArg, "-brk"))
    {
#if defined(_WIN32) && defined(_DEBUG)
        unsigned id = atoi(tempArg.sget());
        if (id == 0)
            DebugBreak();
        else
            _CrtSetBreakAlloc(id);
#endif
        return EclCmdOptionMatch;
    }
    if (finalAttempt)
        fprintf(stderr, "\n%s option not recognized\n", iter.query());
    return EclCmdOptionNoMatch;
}
Example #9
0
bool connectionRemoteMachine(const StringBuffer& sPath, IConstEnvironment* pConstEnv)
{
  bool rc = true;
  if (sPath.length() > 2 && sPath[0] == '\\' && sPath[1] == '\\')
  {
    const char* spath = sPath.str();
    const char* cpos = strchr(spath + 2, '\\');
    int pos = cpos? cpos - spath : -1;

    if (pos != -1)
    {
      char szComp[128];
      strncpy(szComp, spath + 2, pos);
      StringBuffer computer(szComp);
      StringAttr userid;
      StringAttr pswd;

      try {
        //if computer is defined in hardware section then use its associated
        //login information, if any
        getAccountInfo(computer, userid, pswd, pConstEnv);
      } catch (...)
      {
        userid.clear();
        pswd.clear();
      }
    }
  }
  return rc;
}
Example #10
0
 void getHeader(StringBuffer & header) const
 {
     header.append(senderHeader).append(sender.get()).append("\r\n");
     header.append(toHeader).append(to.str()).append("\r\n");
     header.append(subjectHeader).append(subject.get()).append("\r\n");
     header.append("MIME-Version: 1.0\r\n");
 }
Example #11
0
    bool parseCommandLineOptions(ArgvIterator &iter)
    {
        if (iter.done())
        {
            usage();
            return false;
        }

        //First 5 parameter order is fixed.
        for (int cur = 0; cur < 5 && !iter.done(); cur++)
        {
           const char *arg = iter.query();
           if (*arg != '-')
           {
               switch (cur)
               {
                case 0:
                    optTargetESPProcName.set(arg);
                    break;
                case 1:
                    optBindingName.set(arg);
                    break;
                case 2:
                    optService.set(arg);
                    break;
                case 3:
                    optVersionStr.set(arg);
                    break;
                case 4:
                    optMethod.set(arg);
                    break;
                default:
                    fprintf(stderr, "\nUnrecognized positional argument detected : %s\n", arg);
                    usage();
                    return false;
               }
           }
           else
           {
               fprintf(stderr, "\noption detected before required arguments: %s\n", arg);
               usage();
               return false;
           }

           iter.next();
        }

        for (; !iter.done(); iter.next())
        {
            if (parseCommandLineOption(iter))
                continue;

            if (matchCommandLineOption(iter, true)!=EsdlCmdOptionMatch)
                return false;
        }

        return true;
    }
 CPermissionCheckThread(ISecManager* secmgr, const char* user, const char* passwd, const char* r, SecResourceType rtype, int rounds)
 {
     m_secmgr = secmgr;
     m_user.set(user);
     m_passwd.set(passwd);
     m_resource.set(r);
     m_rtype = rtype;
     m_rounds = rounds;
 }
Example #13
0
    virtual bool finalizeOptions(IProperties *globals)
    {
        if (optWSProcAddress.isEmpty())
            throw MakeStringException( 0, "Server address of WsESDLConfig process server must be provided" );

        if (optWSProcPort.isEmpty())
            throw MakeStringException( 0, "Port on which WsESDLConfig is listening must be provided" );

        return true;
    }
Example #14
0
void SplitIpPort(StringAttr & ip, unsigned & port, const char * address)
{
    const char * colon = strchr(address, ':');
    if (colon)
    {
        ip.set(address,colon-address);
        port = atoi(colon+1);
    }
    else
        ip.set(address);
}
Example #15
0
IHqlRemoteScope * XmlEclRepository::resolveScope(IProperties *props, const char * modname, bool deleteIfExists, bool createIfMissing)
{
    Owned<IHqlRemoteScope> parentScope = LINK(rootScope);
    
    const char * item = modname;
    const char * dot;
    do
    {
        dot = strchr(item, '.');
        _ATOM moduleName;
        StringAttr fullName;
        if (dot)
        {
            moduleName = createIdentifierAtom(item, dot-item);
            fullName.set(modname, dot - modname);
            item = dot + 1;
        }
        else
        {
            moduleName = createIdentifierAtom(item);
            fullName.set(modname);
        }

        //nested module already exist in parent scope?
        Owned<IHqlRemoteScope> rScope = parentScope->lookupRemoteModule(moduleName);

        if (!rScope && !createIfMissing)
            return NULL;

        if (rScope && deleteIfExists && !dot)
        {
            rScope->noteTextModified();
            if (rScope->isEmpty())
                parentScope->removeNestedScope(moduleName);
            return NULL;
        }

        if (!rScope)
        {
            rScope.setown(createRemoteScope(moduleName, fullName, this, dot ? NULL : props, NULL, true));

            int flags = props->getPropInt("@flags", 0);
            parentScope->addNestedScope(rScope->queryScope(), flags);
        }
        else
            rScope->invalidateParsed();

        parentScope.set(rScope);
    } while (dot);
    if (parentScope)
        parentScope->noteTextModified();
    return parentScope.getLink();
}
Example #16
0
void SplitIpPort(StringAttr & ip, unsigned & port, const char * address)
{
  const char * colon = strchr(address, ':');
  if (colon)
  {
    ip.set(address,colon-address);
    if (strcmp(ip, ".")==0)
        ip.set(GetCachedHostName());
    port = atoi(colon+1);
  }
  else
    ip.set(address);
}
 CMethodInfo(const char * label, const char * req, const char * resp) //, const char *sectag, const char *optag,const char* minver=NULL, const char* maxver=NULL)
 {
     m_label.set(label);
     m_requestLabel.set(req);
     m_responseLabel.set(resp);
     /*
     if (sectag)
         m_securityTag.append(sectag);
     if (optag)
         m_optionalTag.append(optag);
     m_minVer = (minver)?atof(minver):-1;
     m_maxVer = (maxver)?atof(maxver):-1;
     */
 };
 bool doSwap(const char *oldip, const char *newip)
 {
     Owned<INode> newNode = createINode(newip);
     Owned<INode> oldNode = createINode(oldip);
     if (!group->isMember(oldNode)) {
         ERRLOG("Node %s is not part of group %s", oldip, groupName.get());
         return false;
     }
     if (group->isMember(newNode)) {
         ERRLOG("Node %s is already part of group %s", newip, groupName.get());
         return false;
     }
     queryNamedGroupStore().swapNode(oldNode->endpoint(),newNode->endpoint());
     return true;
 }
 void setPMID(const char *_target, const char *name, bool globalScope)
 {
     if (!name || !*name)
         throw MakeStringExceptionDirect(PKG_MISSING_PARAM, "PackageMap name parameter required");
     if (!globalScope)
     {
         target.set(_target);
         if (target.isEmpty())
             throw MakeStringExceptionDirect(PKG_MISSING_PARAM, "Target cluster parameter required");
         ensureClusterInfo();
         pmid.append(target).append("::");
     }
     pmid.append(name);
     pmid.toLowerCase();
 }
Example #20
0
    int processCMD()
    {
        Owned<IClientWsESDLConfig> esdlConfigClient = EsdlCmdHelper::getWsESDLConfigSoapService(optWSProcAddress, optWSProcPort, optUser, optPass);
        Owned<IClientPublishESDLBindingRequest> request = esdlConfigClient->createPublishESDLBindingRequest();

        fprintf(stdout,"\nAttempting to configure ESDL Service: '%s'\n", optESDLService.get());

        request->setEspProcName(optTargetESPProcName);
        request->setEspPort(optTargetPort);
        request->setEspServiceName(optService);
        request->setEsdlServiceName(optESDLService);
        request->setEsdlDefinitionID(optESDLDefID);
        request->setConfig(optInput);
        request->setOverwrite(optOverWrite);

        if (optVerbose)
            fprintf(stdout,"\nMethod config: %s\n", optInput.get());

        Owned<IClientPublishESDLBindingResponse> resp = esdlConfigClient->PublishESDLBinding(request);

        if (resp->getExceptions().ordinality()>0)
        {
            EsdlCmdHelper::outputMultiExceptions(resp->getExceptions());
            return 1;
        }

        fprintf(stdout, "\n %s.\n", resp->getStatus().getDescription());

        return 0;
    }
Example #21
0
 bool testPath(const char *path) const
 {
     if (!dir) // if no dir in filter, match any
         return true;
     else
         return startsWith(path, dir.get());
 }
Example #22
0
    bool parseCommandLineOption(ArgvIterator &iter)
    {
        StringAttr oneOption;
        if (iter.matchOption(oneOption, ESDLOPT_INCLUDE_PATH) || iter.matchOption(oneOption, ESDLOPT_INCLUDE_PATH_S))
        {
            if(optIncludePath.length() > 0)
                optIncludePath.append(ENVSEPSTR);
            optIncludePath.append(oneOption.get());
            return true;
        }

        if (EsdlPublishCmdCommon::parseCommandLineOption(iter))
            return true;

        return false;
    }
Example #23
0
void RemoteDataSourceServer::doCmdCreateWorkunit(MemoryBuffer & in, MemoryBuffer & out)
{
    SessionId session;
    StringAttr wuid, username, password;
    unsigned sequence;
    StringAttr name;

    in.read(session);
    in.read(username).read(password);
    in.read(wuid);
    in.read(sequence);
    in.read(name);

    DBGLOG("RemoteFileView:CreateWorkunit('%s',%d,'%s') by[%s:%" I64F "d", wuid.get(), sequence, name ? name.get() : "", username.get(), session);
    Owned<IConstWUResult> wuResult = resolveResult(wuid, sequence, name);
    Owned<IFvDataSource> ds = createDataSource(wuResult, wuid, username, password);
    unique_id_t id = addDataSource(session, ds);

    out.append((unsigned short)CurRemoteVersion);
    out.append(id);
    out.append(ds->numRows(false));
    ds->queryMetaData()->serialize(out);
    out.append(ds->isIndex());

    DBGLOG("RemoteFileView:CreateWorkunit returns %" I64F "d", id);
}
    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));
    }
Example #25
0
//---------------------------------------------------------------------------
//  getAccountInfo
//---------------------------------------------------------------------------
void getAccountInfo(const char* computer, StringAttr& user, StringAttr& pwd, IConstEnvironment* pConstEnv) 
{
  if (!pConstEnv)
    throw MakeStringException(-1, "No environment is available!");

  Owned<IConstMachineInfo> machine = pConstEnv->getMachine(computer);
  if (!machine)
  {
    StringBuffer sComputer(computer);
    StringBuffer sExtra;
    if (sExtra.length() == 0)
      machine.setown( pConstEnv->getMachineByAddress(computer) );

    if (!machine)
      throw MakeStringException(-1, "The computer '%s' is undefined!", computer);
  }

  Owned<IConstDomainInfo> domain = machine->getDomain();
  if (!domain)
    throw MakeStringException(-1, "The computer '%s' does not have any domain information!", computer);

  StringBuffer x;
  domain->getName(StringBufferAdaptor(x));
  if (x.length()) 
    x.append(PATHSEPCHAR);
  domain->getAccountInfo(StringBufferAdaptor(x), StringAttrAdaptor(pwd));
  user.set(x.str());
}
Example #26
0
    void read()
    {
        try
        {
            socket->read(inbuff,1,sizeof(inbuff),inlen);
            //MORE: the following is somewhat primitive and not RFC compliant (see bug 25951) - but it is a lot better than nothing
            if((*inbuff == '4') || (*inbuff == '5'))
            {
                StringBuffer b;
                b.append("Negative reply from mail server at ").append(mailServer.get()).append(":").append(port).append(" after writing ").append(lastAction.str()).append(" in SendEmail*: ").append(inlen, inbuff).clip();
                WARNLOG("%s", b.str());
                if (warnings)
                    warnings->append(b.str());
            }
#ifdef SMTP_TRACE
            else
            {
                StringBuffer b(inlen, inbuff);
                b.clip();
                DBGLOG("SMTP read: [%s]", b.str());
            }
#endif
        }
        catch(IException * e)
        {
            int code = e->errorCode();
            StringBuffer buff;
            e->errorMessage(buff);
            e->Release();
            throw MakeStringException(MSGAUD_operator, 0, "Exception %d (%s) in SendEmail* while reading from mail server %s:%u following %s", code, buff.str(), mailServer.get(), port, lastAction.str());
        }
    }
Example #27
0
    void processOption(const char *option, const char *value, StringBuffer &eclccCmd, StringBuffer &eclccProgName, IPipeProcess &pipe, bool isLocal)
    {
        if (memicmp(option, "eclcc-", 6) == 0 || *option=='-')
        {
            //Allow eclcc-xx-<n> so that multiple values can be passed through for the same named debug symbol
            const char * start = option + (*option=='-' ? 1 : 6);
            const char * dash = strchr(start, '-');     // position of second dash, if present
            StringAttr optName;
            if (dash)
                optName.set(start, dash-start);
            else
                optName.set(start);

            if (stricmp(optName, "hook") == 0)
            {
                if (isLocal)
                    throw MakeStringException(0, "eclcc-hook option can not be set per-workunit");  // for security reasons
                eclccProgName.set(value);
            }
            else if (stricmp(optName, "compileOption") == 0)
                eclccCmd.appendf(" -Wc,%s", value);
            else if (stricmp(optName, "includeLibraryPath") == 0)
                eclccCmd.appendf(" -I%s", value);
            else if (stricmp(optName, "libraryPath") == 0)
                eclccCmd.appendf(" -L%s", value);
            else if (stricmp(start, "-allow")==0)
            {
                if (isLocal)
                    throw MakeStringException(0, "eclcc-allow option can not be set per-workunit");  // for security reasons
                eclccCmd.appendf(" -%s=%s", start, value);
            }
            else
                eclccCmd.appendf(" -%s=%s", start, value);
        }
        else if (strchr(option, '-'))
        {
            StringBuffer envVar;
            if (isLocal)
                envVar.append("WU_");
            envVar.append(option);
            envVar.toUpperCase();
            envVar.replace('-','_');
            pipe.setenv(envVar, value);
        }
        else
            eclccCmd.appendf(" -f%s=%s", option, value);
    }
Example #28
0
    bool parseCommandLineOptions(ArgvIterator &iter)
    {
        if (iter.done())
        {
            usage();
            return false;
        }

        //First 4 parameter's order is fixed.
        //TargetESPProcessName
        //TargetESPBindingPort | TargetESPServiceName
        //ESDLDefinitionId
        //ESDLServiceName
        for (int cur = 0; cur < 4 && !iter.done(); cur++)
        {
           const char *arg = iter.query();
           if (*arg != '-')
           {
               switch (cur)
               {
                case 0:
                    optTargetESPProcName.set(arg);
                    break;
                case 1:
                    optPortOrName.set(arg);
                    break;
                case 2:
                    optESDLDefID.set(arg);
                    break;
                case 3:
                    optESDLService.set(arg);
                    break;
                default:
                    fprintf(stderr, "\nUnrecognized positional argument detected : %s\n", arg);
                    usage();
                    return false;
               }
           }
           else
           {
               fprintf(stderr, "\nOption detected before required arguments: %s\n", arg);
               usage();
               return false;
           }

           iter.next();
        }

        for (; !iter.done(); iter.next())
        {
            if (parseCommandLineOption(iter))
                continue;

            if (matchCommandLineOption(iter, true)!=EsdlCmdOptionMatch)
                return false;
        }

        return true;
    }
Example #29
0
    CMailInfo(char const * _to, char const * _subject, char const * _mailServer, unsigned _port, char const * _sender, StringArray *_warnings) 
        : subject(_subject), mailServer(_mailServer), port(_port), sender(_sender), lastAction("process initialization"), inlen(0)
    {
        warnings = _warnings;
        CSMTPValidator validator;
        if(strlen(senderHeader) + sender.length() > 998)
            throw MakeStringException(0, "email sender address too long: %" I64F "u characters",  static_cast<__uint64>(sender.length()));
        validator.validateAddress(sender.get(), "email sender address");

        getRecipients(validator, _to);
        if(strlen(toHeader) + to.length() > 998)
            throw MakeStringException(0, "Email recipient address list too long: %u characters", to.length());

        if(strlen(subjectHeader) + subject.length() > 998)
            throw MakeStringException(0, "Email subject too long: %" I64F "u characters",  static_cast<__uint64>(subject.length()));
        validator.validateValue(subject.get(), "email subject");
    }
Example #30
0
    virtual void init()
    {
        CMasterActivity::init();
        helper = (IHThorKeyPatchArg *)queryHelper();
        OwnedRoxieString originalHelperName(helper->getOriginalName());
        OwnedRoxieString patchHelperName(helper->getPatchName());
        OwnedRoxieString outputHelperName(helper->getOutputName());
        StringBuffer expandedFileName;
        queryThorFileManager().addScope(container.queryJob(), originalHelperName, expandedFileName, false);
        originalName.set(expandedFileName);
        queryThorFileManager().addScope(container.queryJob(), patchHelperName, expandedFileName.clear(), false);
        patchName.set(expandedFileName);
        queryThorFileManager().addScope(container.queryJob(), outputHelperName, expandedFileName.clear(), false);
        outputName.set(expandedFileName);

        originalIndexFile.setown(queryThorFileManager().lookup(container.queryJob(), originalHelperName));
        patchFile.setown(queryThorFileManager().lookup(container.queryJob(), patchHelperName));
        
        if (originalIndexFile->numParts() != patchFile->numParts())
            throw MakeActivityException(this, TE_KeyPatchIndexSizeMismatch, "Index %s and patch %s differ in width", originalName.get(), patchName.get());
        if (originalIndexFile->querySuperFile() || patchFile->querySuperFile())
            throw MakeActivityException(this, 0, "Patching super files not supported");
        
        addReadFile(originalIndexFile);
        addReadFile(patchFile);

        width = originalIndexFile->numParts();

        originalDesc.setown(originalIndexFile->getFileDescriptor());
        patchDesc.setown(patchFile->getFileDescriptor());

        Owned<IPartDescriptor> tlkDesc = originalDesc->getPart(originalDesc->numParts()-1);
        const char *kind = tlkDesc->queryProperties().queryProp("@kind");
        local = NULL == kind || 0 != stricmp("topLevelKey", kind);

        if (!local && width > 1)
            width--; // 1 part == No n distributed / Monolithic key
        if (width > container.queryJob().querySlaves())
            throw MakeActivityException(this, 0, "Unsupported: keypatch(%s, %s) - Cannot patch a key that's wider(%d) than the target cluster size(%d)", originalIndexFile->queryLogicalName(), patchFile->queryLogicalName(), width, container.queryJob().querySlaves());

        IArrayOf<IGroup> groups;
        fillClusterArray(container.queryJob(), outputName, clusters, groups);
        newIndexDesc.setown(queryThorFileManager().create(container.queryJob(), outputName, clusters, groups, 0 != (KDPoverwrite & helper->getFlags()), 0, !local, width));
        if (!local)
            newIndexDesc->queryPart(newIndexDesc->numParts()-1)->queryProperties().setProp("@kind", "topLevelKey");
    }