bool FastMultipleConnect(unsigned n,HRPCmodule **modules,bool *done,int timeout) { CriticalSection sect; IPointerArrayOf<ISocket> sockets; SocketEndpointArray eps; unsigned i; for (i=0;i<n;i++) { SocketEndpoint ep; if (!getTcpTarget(modules[i]->queryTransport(),ep)) return false; eps.append(ep); done[i] = false; } multiConnect(eps,sockets,60*1000); assertex(n==sockets.ordinality()); bool ret = true; for (i=0;i<n;i++) { ISocket *sock = sockets.item(i); if (sock) { modules[i]->AttachConnect(sock,true); done[i] = true; } else { StringBuffer epstr; eps.item(i).getUrlStr(epstr); //ERRLOG("Failed to connect to %s",epstr.str()); ret = false; } } return ret; }
bool updateDaliEnv(IPropertyTree *env, bool forceGroupUpdate, const char *daliIp) { Owned<IPropertyTreeIterator> dalis = env->getElements("Software/DaliServerProcess/Instance"); if (!dalis||!dalis->first()) { fprintf(stderr,"Could not find DaliServerProcess\n"); return false; } SocketEndpoint daliep; loop { const char *ps = dalis->get().queryProp("@port"); unsigned port = ps?atoi(ps):0; if (!port) port = DALI_SERVER_PORT; daliep.set(dalis->get().queryProp("@netAddress"),port); if (daliIp && *daliIp) { SocketEndpoint testep; testep.set(daliIp,DALI_SERVER_PORT); if (testep.equals(daliep)) break; daliep.set(NULL,0); } if (!dalis->next()) break; if (!daliep.isNull()) { fprintf(stderr,"Ambiguous DaliServerProcess instance\n"); return false; } } if (daliep.isNull()) { fprintf(stderr,"Could not find DaliServerProcess instance\n"); return false; } SocketEndpointArray epa; epa.append(daliep); Owned<IGroup> group = createIGroup(epa); bool ret = true; initClientProcess(group, DCR_Util); StringBuffer response; if (querySDS().updateEnvironment(env, forceGroupUpdate, response)) { StringBuffer tmp; PROGLOG("Environment and node groups updated in dali at %s",daliep.getUrlStr(tmp).str()); } else ret = false; if (response.length()) WARNLOG("%s", response.str()); closedownClientProcess(); return ret; }
static void appendNodeEndpoint(IPropertyTree& node,SocketEndpointArray &eps) { const char *computer = node.queryProp("@computer"); CMachineEntryPtr *m = machinemap.getValue(computer); if (!m) { ERRLOG("Computer name %s not found",computer); return; } SocketEndpoint ep = (*m)->ep; if (ep.port==0) ep.port = getDaliServixPort(); eps.append(ep); }
static bool getCluster(const char *clustername,SocketEndpointArray &eps) { Owned<IGroup> grp = queryNamedGroupStore().lookup(clustername); if (grp.get()==NULL) return false; unsigned n = grp->ordinality(); unsigned short p = getDaliServixPort(); for (unsigned i=0;i<n;i++) { SocketEndpoint ep(p,grp->queryNode(i).endpoint()); eps.append(ep); } return eps.ordinality()!=0; }
static void test2() { const size32_t recsize = 17; printf("Test DFS\n"); StringBuffer s; unsigned i; unsigned n; unsigned t; queryNamedGroupStore().remove("daregress_group"); queryDistributedFileDirectory().removeEntry("daregress::superfile1"); SocketEndpointArray epa; for (n=0;n<400;n++) { s.clear().append("192.168.").append(n/256).append('.').append(n%256); SocketEndpoint ep(s.str()); epa.append(ep); } Owned<IGroup> group = createIGroup(epa); queryNamedGroupStore().add("daregress_group",group,true); if (!queryNamedGroupStore().find(group,s.clear())) ERROR("Created logical group not found"); if (stricmp(s.str(),"daregress_group")!=0) ERROR("Created logical group found with wrong name"); group.setown(queryNamedGroupStore().lookup("daregress_group")); if (!group) ERROR("named group lookup failed"); printf("Named group created - 400 nodes\n"); for (i=0;i<100;i++) { Owned<IPropertyTree> pp = createPTree("Part"); Owned<IFileDescriptor>fdesc = createFileDescriptor(); fdesc->setDefaultDir("c:\\thordata\\regress"); n = 9; for (unsigned k=0;k<400;k++) { s.clear().append("192.168.").append(n/256).append('.').append(n%256); Owned<INode> node = createINode(s.str()); pp->setPropInt64("@size",(n*777+i)*recsize); s.clear().append("daregress_test").append(i).append("._").append(n+1).append("_of_400"); fdesc->setPart(n,node,s.str(),pp); n = (n+9)%400; } fdesc->queryProperties().setPropInt("@recordSize",17); s.clear().append("daregress::test").append(i); queryDistributedFileDirectory().removeEntry(s.str()); StringBuffer cname; Owned<IDistributedFile> dfile = queryDistributedFileDirectory().createNew(fdesc); if (stricmp(dfile->getClusterName(0,cname),"daregress_group")!=0) ERROR1("Cluster name wrong %d",i); s.clear().append("daregress::test").append(i); dfile->attach(s.str()); } printf("DFile create done - 100 files\n"); unsigned samples = 5; t = 33; for (i=0;i<100;i++) { s.clear().append("daregress::test").append(t); if (!queryDistributedFileDirectory().exists(s.str())) ERROR1("Could not find %s",s.str()); Owned<IDistributedFile> dfile = queryDistributedFileDirectory().lookup(s.str()); if (!dfile) { ERROR1("Could not find %s",s.str()); continue; } offset_t totsz = 0; n = 11; for (unsigned k=0;k<400;k++) { Owned<IDistributedFilePart> part = dfile->getPart(n); if (!part) { ERROR2("part not found %d %d",t,n); continue; } s.clear().append("192.168.").append(n/256).append('.').append(n%256); Owned<INode> node = createINode(s.str()); if (!node->equals(part->queryNode())) ERROR2("part node mismatch %d, %d",t,n); if (part->getFileSize(false,false)!=(n*777+t)*recsize) ERROR4("size node mismatch %d, %d, %d, %d",t,n,(unsigned)part->getFileSize(false,false),(n*777+t)*recsize); s.clear().append("daregress_test").append(t).append("._").append(n+1).append("_of_400"); /* ** TBD if (stricmp(s.str(),part->queryPartName())!=0) ERROR4("part name mismatch %d, %d '%s' '%s'",t,n,s.str(),part->queryPartName()); */ totsz += (n*777+t)*recsize; if ((samples>0)&&(i+n+t==k)) { samples--; RemoteFilename rfn; part->getFilename(rfn,samples%2); StringBuffer fn; rfn.getRemotePath(fn); printf("SAMPLE: %d,%d %s\n",t,n,fn.str()); } n = (n+11)%400; } if (totsz!=dfile->getFileSize(false,false)) ERROR1("total size mismatch %d",t); t = (t+33)%100; } printf("DFile lookup done - 100 files\n"); // check iteration __int64 crctot = 0; unsigned np = 0; unsigned totrows = 0; Owned<IDistributedFileIterator> fiter = queryDistributedFileDirectory().getIterator("daregress::*",false); Owned<IDistributedFilePartIterator> piter; ForEach(*fiter) { piter.setown(fiter->query().getIterator()); ForEach(*piter) { RemoteFilename rfn; StringBuffer s; piter->query().getFilename(rfn,0); rfn.getRemotePath(s); piter->query().getFilename(rfn,1); rfn.getRemotePath(s); crctot += crc32(s.str(),s.length(),0); np++; totrows += (unsigned)(piter->query().getFileSize(false,false)/fiter->query().queryProperties().getPropInt("@recordSize",-1)); } } piter.clear(); fiter.clear(); printf("DFile iterate done - %d parts, %d rows, CRC sum %"I64F"d\n",np,totrows,crctot); Owned<IDistributedSuperFile> sfile; sfile.setown(queryDistributedFileDirectory().createSuperFile("daregress::superfile1",true)); for (i = 0;i<100;i++) { s.clear().append("daregress::test").append(i); sfile->addSubFile(s.str()); } sfile.clear(); sfile.setown(queryDistributedFileDirectory().lookupSuperFile("daregress::superfile1")); if (!sfile) { ERROR("Could not find added superfile"); return; } __int64 savcrc = crctot; crctot = 0; np = 0; totrows = 0; size32_t srs = (size32_t)sfile->queryProperties().getPropInt("@recordSize",-1); if (srs!=17) ERROR1("Superfile does not match subfile row size %d",srs); piter.setown(sfile->getIterator()); ForEach(*piter) { RemoteFilename rfn; StringBuffer s; piter->query().getFilename(rfn,0); rfn.getRemotePath(s); piter->query().getFilename(rfn,1); rfn.getRemotePath(s); crctot += crc32(s.str(),s.length(),0); np++; totrows += (unsigned)(piter->query().getFileSize(false,false)/srs); } piter.clear(); printf("Superfile iterate done - %d parts, %d rows, CRC sum %"I64F"d\n",np,totrows,crctot); if (crctot!=savcrc) ERROR("SuperFile does not match sub files"); unsigned tr = (unsigned)(sfile->getFileSize(false,false)/srs); if (totrows!=tr) ERROR1("Superfile size does not match part sum %d",tr); sfile->detach(); sfile.clear(); sfile.setown(queryDistributedFileDirectory().lookupSuperFile("daregress::superfile1")); if (sfile) ERROR("Superfile deletion failed"); t = 37; for (i=0;i<100;i++) { s.clear().append("daregress::test").append(t); if (i%1) { Owned<IDistributedFile> dfile = queryDistributedFileDirectory().lookup(s.str()); if (!dfile) ERROR1("Could not find %s",s.str()); dfile->detach(); } else queryDistributedFileDirectory().removeEntry(s.str()); t = (t+37)%100; } printf("DFile removal complete\n"); t = 39; for (i=0;i<100;i++) { if (queryDistributedFileDirectory().exists(s.str())) ERROR1("Found %s after deletion",s.str()); Owned<IDistributedFile> dfile = queryDistributedFileDirectory().lookup(s.str()); if (dfile) ERROR1("Found %s after deletion",s.str()); t = (t+39)%100; } printf("DFile removal check complete\n"); queryNamedGroupStore().remove("daregress_group"); if (queryNamedGroupStore().lookup("daregress_group")) ERROR("Named group not removed"); }
bool SortSlaveMP::marshall(ISortSlaveMP &slave, ICommunicator* comm, mptag_t tag) { CMessageBuffer mb; rank_t sender; comm->recv(mb,0,tag,&sender); // NB only recv from master if (mb.length()==0) { PROGLOG("Stopping SortSlaveMP::marshall"); return false; } byte fn; mb.read(fn); CMessageBuffer mbout; mbout.init(mb.getSender(),tag,mb.getReplyTag()); byte okout=1; mbout.append(okout); #ifdef FULLTRACE StringBuffer tmp1; PROGLOG(">SortSlaveMP::marshall(%d) got %d from %s tag %d replytag %d",(int)fn, mb.length(), mb.getSender().getUrlStr(tmp1).str(),tag,mb.getReplyTag()); #endif bool replydone = false; Owned<IException> err; try { switch ((MPSlaveFunctions)(int)fn) { case FN_Connect: { unsigned _part; unsigned _numnodes; mb.read(_part).read(_numnodes); bool ret = slave.Connect(_part,_numnodes); mbout.append(ret); } break; case FN_StartGather: { slave.StartGather(); } break; case FN_GetGatherInfo: { bool hasserializer; mb.read(hasserializer); rowcount_t numlocal; unsigned overflowscale; offset_t totalsize; slave.GetGatherInfo(numlocal,totalsize,overflowscale,hasserializer); mbout.append(numlocal).append(totalsize).append(overflowscale); } break; case FN_GetMinMax: { size32_t keybuffsize; void *keybuff; size32_t avrecsize; rowcount_t ret = slave.GetMinMax(keybuffsize,keybuff,avrecsize); serializeblk(mbout,keybuffsize,keybuff).append(avrecsize).append(ret); free(keybuff); } break; case FN_GetMultiMidPointStart: { replydone = true; comm->reply(mbout); size32_t lkeybuffsize; void * lkeybuff; size32_t hkeybuffsize; void * hkeybuff; deserializeblk(mb,lkeybuffsize,lkeybuff); deserializeblk(mb,hkeybuffsize,hkeybuff); slave.GetMultiMidPointStart(lkeybuffsize,lkeybuff,hkeybuffsize,hkeybuff); free(lkeybuff); free(hkeybuff); } break; case FN_MultiBinChopStop: { unsigned num; mb.read(num); void *out = mbout.reserveTruncate(num*sizeof(rowcount_t)); slave.MultiBinChopStop(num,(rowcount_t *)out); } break; case FN_GetMultiMidPointStop: { size32_t mkeybuffsize=0; void * mkeybuff = NULL; slave.GetMultiMidPointStop(mkeybuffsize,mkeybuff); serializeblk(mbout,mkeybuffsize,mkeybuff); free(mkeybuff); } break; case FN_MultiBinChopStart: { replydone = true; comm->reply(mbout); size32_t keybuffsize; void * keybuff; deserializeblk(mb,keybuffsize,keybuff); byte cmpfn; mb.read(cmpfn); slave.MultiBinChopStart(keybuffsize,(const byte *)keybuff,cmpfn); free(keybuff); } break; case FN_MultiBinChop: { size32_t keybuffsize; void * keybuff; deserializeblk(mb,keybuffsize,keybuff); unsigned num; byte cmpfn; mb.read(num).read(cmpfn); void *out = mbout.reserveTruncate(num*sizeof(rowcount_t)); slave.MultiBinChop(keybuffsize,(const byte *)keybuff,num,(rowcount_t *)out,cmpfn); free(keybuff); } break; case FN_OverflowAdjustMapStart: { replydone = true; comm->reply(mbout); unsigned mapsize; mb.read(mapsize); const void * map = mb.readDirect(mapsize*sizeof(rowcount_t)); size32_t keybuffsize; void * keybuff; deserializeblk(mb,keybuffsize,keybuff); byte cmpfn; mb.read(cmpfn); bool useaux; mb.read(useaux); slave.OverflowAdjustMapStart(mapsize,(rowcount_t *)map,keybuffsize,(const byte *)keybuff,cmpfn,useaux); free(keybuff); } break; case FN_OverflowAdjustMapStop: { unsigned mapsize; mb.read(mapsize); rowcount_t ret=0; size32_t retofs = mbout.length(); mbout.append(ret); void *map=mbout.reserveTruncate(mapsize*sizeof(rowcount_t)); ret = slave.OverflowAdjustMapStop(mapsize,(rowcount_t *)map); // could avoid copy here if passed mb mbout.writeDirect(retofs,sizeof(ret),&ret); } break; case FN_MultiMerge: { replydone = true; comm->reply(mbout); unsigned mapsize; mb.read(mapsize); const void *map = mb.readDirect(mapsize*sizeof(rowcount_t)); unsigned num; mb.read(num); SocketEndpointArray epa; for (unsigned i=0;i<num;i++) { SocketEndpoint ep; ep.deserialize(mb); epa.append(ep); } slave.MultiMerge(mapsize,(rowcount_t *)map,num,epa.getArray()); } break; case FN_MultiMergeBetween: { replydone = true; comm->reply(mbout); unsigned mapsize; mb.read(mapsize); const void *map = mb.readDirect(mapsize*sizeof(rowcount_t)); const void *mapupper = mb.readDirect(mapsize*sizeof(rowcount_t)); unsigned num; mb.read(num); SocketEndpointArray epa; for (unsigned i=0;i<num;i++) { SocketEndpoint ep; ep.deserialize(mb); epa.append(ep); } slave.MultiMergeBetween(mapsize,(rowcount_t *)map,(rowcount_t *)mapupper,num,epa.getArray()); } break; case FN_SingleMerge: { replydone = true; comm->reply(mbout); // async slave.SingleMerge(); } break; case FN_FirstRowOfFile: { StringAttr filename; mb.read(filename); size32_t rowbufsize = 0; byte *rowbuf = NULL; bool ret = slave.FirstRowOfFile(filename,rowbufsize,rowbuf); serializeblk(mbout,rowbufsize,rowbuf); free(rowbuf); mbout.append(ret); } break; case FN_GetMultiNthRow: { unsigned numsplits; mb.read(numsplits); size32_t mkeybuffsize = 0; void * mkeybuf = NULL; slave.GetMultiNthRow(numsplits,mkeybuffsize,mkeybuf); serializeblk(mbout,mkeybuffsize,mkeybuf); free(mkeybuf); } break; case FN_StartMiniSort: { replydone = true; rowcount_t totalrows; mb.read(totalrows); comm->reply(mbout); // async slave.StartMiniSort(totalrows); } break; case FN_Close: { replydone = true; comm->reply(mbout); // async slave.Close(); } break; case FN_CloseWait: { slave.CloseWait(); } break; case FN_Disconnect: { comm->reply(mbout); // async replydone = true; slave.Disconnect(); } // fall through return false; default: throw MakeStringException(-1,"unknown function %d",(int)fn); } } catch (IException *e) { EXCLOG(e,"SortSlaveMP::marshall"); if (!replydone) { mbout.clear(); okout = 0; mbout.append(okout); int err = e->errorCode(); mbout.append(err); StringBuffer outs; e->errorMessage(outs); mbout.append(outs.str()); } err.setown(e); } if (!replydone) { #ifdef FULLTRACE StringBuffer tmp1; PROGLOG("<SortSlaveMP::marshall(%d) send %d to %s tag %d",(int)fn, mbout.length(), mbout.getSender().getUrlStr(tmp1).str(),mbout.getReplyTag()); #endif comm->reply(mbout); } if (err.get()) throw err.getClear(); return true; }
int main(int argc, const char *argv[]) { InitModuleObjects(); int ret = 0; bool dryRun = false; bool offline = false; StringAttr daliServer, envPath; enum CmdType { cmd_none, cmd_swap, cmd_auto, cmd_history, cmd_email, cmd_swapped, cmd_reset, cmd_resetspares, cmd_addspares, cmd_removespares, cmd_resethistory }; CmdType cmd = cmd_none; ArgvIterator iter(argc, argv); try { bool stop=false; StringArray params; for (; !ret&&!iter.done(); iter.next()) { const char *arg = iter.query(); if ('-' == *arg) { bool value; if (iter.matchFlag(value, "-dryrun")) dryRun = value; else if (iter.matchFlag(value, "-offline")) offline = value; else { PROGLOG("Unknown option"); ret = 2; usage(); break; } } else { switch (cmd) { case cmd_none: if (strieq("swap", arg)) cmd = cmd_swap; else if (strieq("auto", arg)) cmd = cmd_auto; else if (strieq("history", arg)) cmd = cmd_history; else if (strieq("email", arg)) cmd = cmd_email; else if (strieq("swapped", arg)) cmd = cmd_swapped; else if (strieq("reset", arg)) cmd = cmd_reset; else if (strieq("resetspares", arg)) cmd = cmd_resetspares; else if (strieq("addspares", arg)) cmd = cmd_addspares; else if (strieq("removespares", arg)) cmd = cmd_removespares; else if (strieq("resethistory", arg)) cmd = cmd_resethistory; else { PROGLOG("Unknown command"); usage(); ret = 2; } break; default: params.append(iter.query()); break; } } } unsigned requiredParams=UINT_MAX; switch (cmd) { case cmd_swap: requiredParams = 4; break; case cmd_addspares: case cmd_removespares: requiredParams = 3; break; case cmd_auto: case cmd_history: case cmd_email: case cmd_swapped: case cmd_reset: case cmd_resetspares: case cmd_resethistory: requiredParams = 2; break; } if (params.ordinality() < requiredParams) { usage(); ret = 2; } else { StringAttr daliServer = params.item(0); StringAttr clusterName = params.item(1); DaliClient dclient(daliServer); StringBuffer logname; splitFilename(argv[0], NULL, NULL, &logname, NULL); addFileTimestamp(logname, true); logname.append(".log"); StringBuffer lf; openLogFile(lf, logname.str(),0,false,true); queryStderrLogMsgHandler()->setMessageFields(MSGFIELD_prefix); Owned<IRemoteConnection> conn = querySDS().connect("/Environment", myProcessSession(), RTM_LOCK_READ, SDS_LOCK_TIMEOUT); IPropertyTree *environment = conn->queryRoot(); StringBuffer xpath("Software/ThorCluster[@name=\""); xpath.append(clusterName).append("\"]"); IPropertyTree *cluster = environment->queryPropTree(xpath.str()); if (!cluster) { PROGLOG("Unknown cluster: %s", clusterName.get()); ret = 3; } if (!ret) { Owned<IPropertyTree> options = createPTreeFromIPT(cluster); conn.clear(); if (options&&options->getPropBool("@enableSysLog",true)) UseSysLogForOperatorMessages(); switch (cmd) { case cmd_auto: { if (!autoSwapNode(clusterName, dryRun)) ret = 3; break; } case cmd_swap: { const char *oldip=params.item(2); const char *newip=params.item(3); if (!swapNode(clusterName, oldip, newip)) ret = 3; break; } case cmd_history: case cmd_swapped: case cmd_email: { unsigned days = params.isItem(2) ? atoi(params.item(2)) : 0; // for history or swapped switch (cmd) { case cmd_history: swapNodeHistory(clusterName, days, NULL); break; case cmd_swapped: swappedList(clusterName, days, NULL); break; case cmd_email: { bool sendSwapped = false; bool sendHistory = false; if (params.isItem(2)) { if (strieq("swapped", params.item(2))) sendSwapped = true; else if (strieq("history", params.item(2))) sendHistory = true; } emailSwap(clusterName, NULL, true, sendSwapped, sendHistory); break; } } break; } case cmd_reset: case cmd_resetspares: { StringBuffer response; if (!resetClusterGroup(clusterName, "ThorCluster", cmd==cmd_resetspares, response)) { WARNLOG("%s", response.str()); ret = 3; } break; } case cmd_addspares: case cmd_removespares: { SocketEndpointArray allEps; unsigned p=2; do { const char *ipOrRange = params.item(p); SocketEndpointArray epa; epa.fromText(ipOrRange, 0); ForEachItemIn(e, epa) allEps.append(epa.item(e)); p++; } while (p<params.ordinality()); StringBuffer response; bool res; if (cmd == cmd_addspares) res = addClusterSpares(clusterName, "ThorCluster", allEps, response); else res = removeClusterSpares(clusterName, "ThorCluster", allEps, response); if (!res) { WARNLOG("%s", response.str()); ret = 3; } break; } case cmd_resethistory: { Owned<IRemoteConnection> conn = querySDS().connect("/SwapNode", myProcessSession(), RTM_LOCK_WRITE, SDS_LOCK_TIMEOUT); if (conn) { StringBuffer groupName; getClusterGroupName(*options, groupName); VStringBuffer xpath("Thor[@group=\"%s\"]", groupName.str()); if (conn->queryRoot()->removeProp(xpath.str())) PROGLOG("SwapNode info for cluster %s removed", clusterName.get()); else PROGLOG("SwapNode info for cluster %s not found", clusterName.get()); } break; } } } } UseSysLogForOperatorMessages(false); } catch (IException *e) { EXCLOG(e,"SWAPNODE"); e->Release(); ret = -1; } ExitModuleObjects(); return ret; }
void Do(unsigned i) { ISocket *sock = sockets.item(i); StringBuffer epstr; SocketEndpoint ep = eps.item(i); ep.getUrlStr(epstr); // PROGLOG("T.1 %s %x",epstr.str(),(unsigned)sock); StringBuffer verstr; unsigned rver=0; if (sock) { rver = getRemoteVersion(sock, verstr); switch (mode) { case AMcheck: if (rver!=0) return; case AMver: { CriticalBlock block(sect); result.append(ep); StringBuffer ln; ln.append(rver).append(",\"").append(verstr).append('"'); resultstr.append(* new StringAttrItem(ln.str())); } return; case AMstopver: case AMcheckver: case AMcheckvermajor: { // compares versions up to the '-' const char *rv = verstr.str(); const char *v = remoteServerVersionString(); if (mode!=AMcheckvermajor) { while (*v&&(*v!='-')&&(*v==*rv)) { v++; rv++; } } if ((*rv==*v)&&(rver==ver)) return; while (*rv&&(*rv!='-')) rv++; verstr.setLength(rv-verstr.str()); if ((mode==AMcheckver)||(mode==AMcheckvermajor)) break; } // fall through case AMstop: { unsigned err = stopRemoteServer(sock); if (err!=0) { ERRLOG("Could not stop server on %s, %d returned",epstr.str(),err); if (mode!=AMstopver) return; // even though failed to stop - still return code } else Sleep(1000); // let stop } break; default: return; } } CriticalBlock block(sect); result.append(ep); if ((mode!=AMver)&&(mode!=AMcheckver)&&(mode!=AMcheckvermajor)&&(mode!=AMstopver)) resultstr.append(* new StringAttrItem("")); else resultstr.append(* new StringAttrItem(verstr.str())); }
unsigned applyNodes(const char *grpip, ApplyMode mode, unsigned ver, bool isdali, bool quiet) { SocketEndpointArray eps; if (isdali&&(stricmp(grpip,"all")==0)) { Owned<IRemoteConnection> conn = querySDS().connect("/Environment/Software", myProcessSession(), RTM_LOCK_READ, SDS_CONNECT_TIMEOUT); if (!conn) return 0; IPropertyTree* root = conn->queryRoot(); Owned<IPropertyTreeIterator> clusters= root->getElements("ThorCluster"); unsigned ret = 0; if (clusters->first()) { do { IPropertyTree &cluster = clusters->query(); ret += applyNodes(cluster.queryProp("@name"),mode,ver,true,quiet); } while (clusters->next()); } return ret; } SocketEndpointArray result; StringAttrArray resultstr; if (!isdali||!getCluster(grpip,eps)) { SocketEndpoint ep(grpip); if (ep.isNull()) { ERRLOG("%s is not a group name or ip",grpip); return 0; } if (ep.port==0) ep.port = getDaliServixPort(); eps.append(ep); } PointerIArrayOf<ISocket> sockets; unsigned to=10*1000; unsigned n=eps.ordinality(); // use approx log scale (timeout is long but only for failure situation) while (n>1) { n/=2; to+=10*1000; } if (!quiet&&(n>1)) PROGLOG("Scanning %s...",grpip); multiConnect(eps,sockets,to); CriticalSection sect; class casyncfor: public CAsyncFor { SocketEndpointArray &eps; PointerIArrayOf<ISocket> &sockets; ApplyMode mode; unsigned ver; SocketEndpointArray &result; StringAttrArray &resultstr; CriticalSection § public: casyncfor(ApplyMode _mode, unsigned _ver,SocketEndpointArray &_eps,PointerIArrayOf<ISocket> &_sockets,SocketEndpointArray &_result, StringAttrArray &_resultstr,CriticalSection &_sect) : eps(_eps), sockets(_sockets), result(_result), resultstr(_resultstr), sect(_sect) { mode = _mode; ver = _ver; } void Do(unsigned i) { ISocket *sock = sockets.item(i); StringBuffer epstr; SocketEndpoint ep = eps.item(i); ep.getUrlStr(epstr); // PROGLOG("T.1 %s %x",epstr.str(),(unsigned)sock); StringBuffer verstr; unsigned rver=0; if (sock) { rver = getRemoteVersion(sock, verstr); switch (mode) { case AMcheck: if (rver!=0) return; case AMver: { CriticalBlock block(sect); result.append(ep); StringBuffer ln; ln.append(rver).append(",\"").append(verstr).append('"'); resultstr.append(* new StringAttrItem(ln.str())); } return; case AMstopver: case AMcheckver: case AMcheckvermajor: { // compares versions up to the '-' const char *rv = verstr.str(); const char *v = remoteServerVersionString(); if (mode!=AMcheckvermajor) { while (*v&&(*v!='-')&&(*v==*rv)) { v++; rv++; } } if ((*rv==*v)&&(rver==ver)) return; while (*rv&&(*rv!='-')) rv++; verstr.setLength(rv-verstr.str()); if ((mode==AMcheckver)||(mode==AMcheckvermajor)) break; } // fall through case AMstop: { unsigned err = stopRemoteServer(sock); if (err!=0) { ERRLOG("Could not stop server on %s, %d returned",epstr.str(),err); if (mode!=AMstopver) return; // even though failed to stop - still return code } else Sleep(1000); // let stop } break; default: return; } } CriticalBlock block(sect); result.append(ep); if ((mode!=AMver)&&(mode!=AMcheckver)&&(mode!=AMcheckvermajor)&&(mode!=AMstopver)) resultstr.append(* new StringAttrItem("")); else resultstr.append(* new StringAttrItem(verstr.str())); } } afor(mode,ver,eps,sockets,result,resultstr,sect); afor.For(eps.ordinality(), 10, false, true); if (result.ordinality()==0) return 0; switch (mode) { case AMstopver: case AMcheckver: case AMcheckvermajor: if (!quiet) { StringBuffer epstr; ForEachItemIn(i,result) { result.item(i).getUrlStr(epstr.clear()); StringAttrItem &attr = resultstr.item(i); if (attr.text.length()==0) ERRLOG("%s: %s not running DAFILESRV",grpip,epstr.str()); else ERRLOG("%s: %s %s running DAFILESRV version %s",grpip,(mode==AMstopver)?"was":"is",epstr.str(),attr.text.get()); } unsigned numok = eps.ordinality()-result.ordinality(); if (mode==AMcheckvermajor) PROGLOG("%s: %d node%s running version %.1f of DAFILESRV",grpip,numok,(numok!=1)?"s":"",((double)FILESRV_VERSION)/10.0); else { StringBuffer vs; const char *v = remoteServerVersionString(); while (*v&&(*v!='-')) vs.append(*(v++)); PROGLOG("%s: %d node%s running version %s of DAFILESRV",grpip,numok,(numok!=1)?"s":"",vs.str()); } }