#include "gb-include.h" #include "TcpSocket.h" #include "HttpServer.h" #include "Pages.h" #include "Indexdb.h" #include "sort.h" #include "Users.h" static int defaultSort ( const void *i1, const void *i2 ); static int pingSort1 ( const void *i1, const void *i2 ); static int pingSort2 ( const void *i1, const void *i2 ); static int pingAgeSort ( const void *i1, const void *i2 ); static int pingMaxSort ( const void *i1, const void *i2 ); static int slowDiskSort ( const void *i1, const void *i2 ); static int splitTimeSort ( const void *i1, const void *i2 ); static int flagSort ( const void *i1, const void *i2 ); static int resendsSort ( const void *i1, const void *i2 ); static int errorsSort ( const void *i1, const void *i2 ); static int tryagainSort ( const void *i1, const void *i2 ); static int dgramsToSort ( const void *i1, const void *i2 ); static int dgramsFromSort ( const void *i1, const void *i2 ); //static int loadAvgSort ( const void *i1, const void *i2 ); static int memUsedSort ( const void *i1, const void *i2 ); static int cpuUsageSort ( const void *i1, const void *i2 ); static int diskUsageSort ( const void *i1, const void *i2 ); int32_t generatePingMsg( Host *h, int64_t nowms, char *buffer ); // . returns false if blocked, true otherwise // . sets errno on error // . make a web page displaying the config of this host // . call g_httpServer.sendDynamicPage() to send it bool sendPageHosts ( TcpSocket *s , HttpRequest *r ) { // don't allow pages bigger than 128k in cache char buf [ 64*1024 ]; //char *p = buf; //char *pend = buf + 64*1024; SafeBuf sb(buf, 64*1024); // XML OR JSON char format = r->getReplyFormat(); // if ( format == FORMAT_XML || format == FORMAT_JSON ) // return sendPageHostsInXmlOrJson( s , r ); // check for a sort request int32_t sort = r->getLong ( "sort", -1 ); // sort by hostid with dead on top by default if ( sort == -1 ) sort = 16; char *coll = r->getString ( "c" ); //char *pwd = r->getString ( "pwd" ); // check for setnote command int32_t setnote = r->getLong("setnote", 0); int32_t setsparenote = r->getLong("setsparenote", 0); // check for replace host command int32_t replaceHost = r->getLong("replacehost", 0); // check for sync host command int32_t syncHost = r->getLong("synchost", 0); // set note... if ( setnote == 1 ) { // get the host id to change int32_t host = r->getLong("host", -1); if ( host == -1 ) goto skipReplaceHost; // get the note to set int32_t noteLen; char *note = r->getString("note", ¬eLen, "", 0); // set the note g_hostdb.setNote(host, note, noteLen); } // set spare note... if ( setsparenote == 1 ) { // get the host id to change int32_t spare = r->getLong("spare", -1); if ( spare == -1 ) goto skipReplaceHost; // get the note to set int32_t noteLen; char *note = r->getString("note", ¬eLen, "", 0); // set the note g_hostdb.setSpareNote(spare, note, noteLen); } // replace host... if ( replaceHost == 1 ) { // get the host ids to swap int32_t rhost = r->getLong("rhost", -1); int32_t rspare = r->getLong("rspare", -1); if ( rhost == -1 || rspare == -1 ) goto skipReplaceHost; // replace g_hostdb.replaceHost(rhost, rspare); } // sync host... if ( syncHost == 1 ) { // get the host id to sync int32_t syncHost = r->getLong("shost", -1); if ( syncHost == -1 ) goto skipReplaceHost; // call sync g_hostdb.syncHost(syncHost, false); //g_syncdb.syncHost ( syncHost ); } if ( syncHost == 2 ) { // get the host id to sync int32_t syncHost = r->getLong("shost", -1); if ( syncHost == -1 ) goto skipReplaceHost; // call sync g_hostdb.syncHost(syncHost, true); //g_syncdb.syncHost ( syncHost ); } skipReplaceHost: int32_t refreshRate = r->getLong("rr", 0); if(refreshRate > 0 && format == FORMAT_HTML ) sb.safePrintf("", refreshRate); // ignore //char *username = g_users.getUsername ( r ); //char *password = NULL; //User *user = NULL; //if ( username ) user = g_users.getUser (username ); //if ( user ) password = user->m_password; //if ( ! password ) password = ""; //if ( ! username ) username = ""; // print standard header // char *pp = sb.getBuf(); // char *ppend = sb.getBufEnd(); // if ( pp ) { if ( format == FORMAT_HTML ) g_pages.printAdminTop ( &sb , s , r ); // sb.incrementLength ( pp - sb.getBuf() ); // } char *colspan = "30"; //char *shotcol = ""; char shotcol[1024]; shotcol[0] = '\0'; char *cs = coll; if ( ! cs ) cs = ""; if ( g_conf.m_useShotgun && format == FORMAT_HTML ) { colspan = "31"; //shotcol = "ip2"; sprintf ( shotcol, "" "ping2", cs); } // print host table if ( format == FORMAT_HTML ) sb.safePrintf ( "" "" "" "" "" "" "" // mirror # within the shard // i don't remember the last time i used this, so let's // just comment it out to save space //"" //"" //"" //"" // this is now more or less obsolete //"" //"" "" // this is now obsolete since ide channel is. it was used // so that only the guy with the token could merge, // and it made sure that only one merge per ide channel // and per group was going on at any one time for performance // reasons. //"" //"" //"" //"" // this is now fairly obsolete //"" //"" "" //"" //"" "" "" /* MDW: take out for adding new stuff "" "" "" "" */ // "" // "" // "" //"" "" "" "" "" "" "" "" "" "" "" //"" "" "%s"// "" //"", //"" //"" "", TABLE_STYLE , colspan , cs, sort, DARK_BLUE , cs, cs, cs, cs, cs, cs, cs, cs, cs, cs, cs, shotcol ); // loop through each host we know and print it's stats int32_t nh = g_hostdb.getNumHosts(); // should we reset resends, errorsRecvd and ETRYAGAINS recvd? if ( r->getLong("resetstats",0) ) { for ( int32_t i = 0 ; i < nh ; i++ ) { // get the ith host (hostId) Host *h = g_hostdb.getHost ( i ); h->m_pingInfo.m_totalResends = 0; h->m_errorReplies = 0; h->m_pingInfo.m_etryagains = 0; h->m_dgramsTo = 0; h->m_dgramsFrom = 0; h->m_splitTimes = 0; h->m_splitsDone = 0; h->m_pingInfo.m_slowDiskReads =0; } } // sort hosts if needed int32_t hostSort [ MAX_HOSTS ]; for ( int32_t i = 0 ; i < nh ; i++ ) hostSort [ i ] = i; switch ( sort ) { case 1: gbsort ( hostSort, nh, sizeof(int32_t), pingSort1 ); break; case 2: gbsort ( hostSort, nh, sizeof(int32_t), pingSort2 ); break; case 3: gbsort ( hostSort, nh, sizeof(int32_t), resendsSort ); break; case 4: gbsort ( hostSort, nh, sizeof(int32_t), errorsSort ); break; case 5: gbsort ( hostSort, nh, sizeof(int32_t), tryagainSort ); break; case 6: gbsort ( hostSort, nh, sizeof(int32_t), dgramsToSort ); break; case 7: gbsort ( hostSort, nh, sizeof(int32_t), dgramsFromSort ); break; //case 8: gbsort ( hostSort, nh, sizeof(int32_t), loadAvgSort ); break; case 9: gbsort ( hostSort, nh, sizeof(int32_t), memUsedSort ); break; case 10:gbsort ( hostSort, nh, sizeof(int32_t), cpuUsageSort ); break; case 11:gbsort ( hostSort, nh, sizeof(int32_t), pingAgeSort ); break; case 12:gbsort ( hostSort, nh, sizeof(int32_t), flagSort ); break; case 13:gbsort ( hostSort, nh, sizeof(int32_t), splitTimeSort ); break; case 14:gbsort ( hostSort, nh, sizeof(int32_t), pingMaxSort ); break; case 15:gbsort ( hostSort, nh, sizeof(int32_t), slowDiskSort ); break; case 16:gbsort ( hostSort, nh, sizeof(int32_t), defaultSort ); break; case 17:gbsort ( hostSort, nh, sizeof(int32_t), diskUsageSort ); break; } // we are the only one that uses these flags, so set them now /* static char s_properSet = 0; if ( ! s_properSet ) { s_properSet = 1; g_hostdb.setOnProperSwitchFlags(); } */ if ( format == FORMAT_XML ) { sb.safePrintf("\n"); sb.safePrintf("\t0\n"); sb.safePrintf("\tSuccess\n"); } if ( format == FORMAT_JSON ) { sb.safePrintf("{\"response\":{\n"); sb.safePrintf("\t\"statusCode\":0,\n"); sb.safePrintf("\t\"statusMsg\":\"Success\",\n"); } int64_t nowmsLocal = gettimeofdayInMillisecondsLocal(); // compute majority gb version so we can highlight bad out of sync // gb versions in red below int32_t majorityHash32 = 0; int32_t lastCount = 0; // get majority gb version for ( int32_t si = 0 ; si < nh ; si++ ) { int32_t i = hostSort[si]; // get the ith host (hostId) Host *h = g_hostdb.getHost ( i ); char *vbuf = h->m_pingInfo.m_gbVersionStr;//gbVersionStrBuf; int32_t vhash32 = hash32n ( vbuf ); if ( vhash32 == majorityHash32 ) lastCount++; else lastCount--; if ( lastCount < 0 ) majorityHash32 = vhash32; } // print it //int32_t ng = g_hostdb.getNumGroups(); for ( int32_t si = 0 ; si < nh ; si++ ) { int32_t i = hostSort[si]; // get the ith host (hostId) Host *h = g_hostdb.getHost ( i ); // get avg/stdDev msg roundtrip times in ms for ith host //int32_t avg , stdDev; //g_hostdb.getTimes ( i , &avg , &stdDev ); char ptr[256]; int32_t pingAge = generatePingMsg(h, nowmsLocal, ptr); char pms[64]; if ( h->m_pingMax < 0 ) sprintf(pms,"???"); else sprintf(pms,"%"INT32"ms",h->m_pingMax); // the sync status ascii-ized char syncStatus = h->m_syncStatus; char *ptr2; if (syncStatus==0) ptr2 ="N"; else if (syncStatus==1) ptr2 ="Y"; else ptr2 ="?"; char ipbuf1[64]; char ipbuf2[64]; strcpy(ipbuf1,iptoa(h->m_ip)); strcpy(ipbuf2,iptoa(h->m_ipShotgun)); /* char hdbuf[128]; char *hp = hdbuf; for ( int32_t k = 0 ; k < 4 ; k++ ) { int32_t temp = h->m_hdtemps[k]; if ( temp > 50 && format == FORMAT_HTML ) hp += sprintf(hp,"%"INT32"" "", temp); else hp += sprintf(hp,"%"INT32"",temp); if ( k < 3 ) *hp++ = '/'; *hp = '\0'; } */ char *vbuf = h->m_pingInfo.m_gbVersionStr;//m_gbVersionStrBuf; // get hash int32_t vhash32 = hash32n ( vbuf ); char *vbuf1 = ""; char *vbuf2 = ""; if ( vhash32 != majorityHash32 ) { vbuf1 = ""; vbuf2 = ""; } //int32_t switchGroup = 0; //if ( g_hostdb.m_indexSplits > 1 ) // switchGroup = h->m_group%g_hostdb.m_indexSplits; // the switch id match //char tmpN[256]; //if ( ! h->m_onProperSwitch ) // sprintf(tmpN, "%"INT32"", // (int32_t)h->m_switchId); //else // sprintf(tmpN, "%"INT32"", (int32_t)h->m_switchId); // host can have 2 ip addresses, get the one most // similar to that of the requester int32_t eip = g_hostdb.getBestIp ( h , s->m_ip ); char ipbuf3[64]; strcpy(ipbuf3,iptoa(eip)); char *fontTagFront = ""; char *fontTagBack = ""; if ( h->m_pingInfo.m_percentMemUsed >= 98.0 && format == FORMAT_HTML ) { fontTagFront = ""; fontTagBack = ""; } float cpu = h->m_pingInfo.m_cpuUsage; if ( cpu > 100.0 ) cpu = 100.0; if ( cpu < 0.0 ) cpu = -1.0; char diskUsageMsg[64]; sprintf(diskUsageMsg,"%.1f%%",h->m_pingInfo.m_diskUsage); if ( h->m_pingInfo.m_diskUsage < 0.0 ) sprintf(diskUsageMsg,"???"); if ( h->m_pingInfo.m_diskUsage>=98.0 && format == FORMAT_HTML ) sprintf(diskUsageMsg,"%.1f%%" "",h->m_pingInfo.m_diskUsage); // split time, don't divide by zero! int32_t splitTime = 0; if ( h->m_splitsDone ) splitTime = h->m_splitTimes / h->m_splitsDone; //char flagString[32]; char tmpfb[64]; SafeBuf fb(tmpfb,64); //char *fs = flagString; //*fs = '\0'; // does its hosts.conf file disagree with ours? if ( h->m_pingInfo.m_hostsConfCRC && format == FORMAT_HTML && h->m_pingInfo.m_hostsConfCRC != g_hostdb.getCRC() ) fb.safePrintf("H" ""); if ( h->m_pingInfo.m_hostsConfCRC && format != FORMAT_HTML && h->m_pingInfo.m_hostsConfCRC != g_hostdb.getCRC() ) fb.safePrintf("Hosts.conf in disagreement with ours"); int32_t flags = h->m_pingInfo.m_flags; if ( format == FORMAT_HTML ) { // use these new ones for now int n = h->m_pingInfo.m_numCorruptDiskReads; if ( n ) fb.safePrintf("" "C" "%"INT32"" "" , n ); n = h->m_pingInfo.m_numOutOfMems; if ( n ) fb.safePrintf("" "O" "%"INT32"" "" , n ); n = h->m_pingInfo.m_socketsClosedFromHittingLimit; if ( n ) fb.safePrintf("" "K" "%"INT32"" "" , n ); if ( flags & PFLAG_OUTOFSYNC ) fb.safePrintf("" "N" "" ); } // recovery mode? reocvered from coring? if ((flags & PFLAG_RECOVERYMODE)&& format == FORMAT_HTML ) { fb.safePrintf("x"); // this is only 8-bits at the moment so it's capped // at 255. this level is 1 the first time we core // and are restarted. if ( h->m_pingInfo.m_recoveryLevel > 1 ) fb.safePrintf("%"INT32"", (int32_t) h->m_pingInfo.m_recoveryLevel); } if ((flags & PFLAG_RECOVERYMODE)&& format != FORMAT_HTML ) fb.safePrintf("Recovered from core"); // rebalancing? if ( (flags & PFLAG_REBALANCING)&& format == FORMAT_HTML ) fb.safePrintf("R"); if ( (flags & PFLAG_REBALANCING)&& format != FORMAT_HTML ) fb.safePrintf("Currently rebalancing"); // has recs that should be in another shard? indicates // we need to rebalance or there is a bad hosts.conf if ((flags & PFLAG_FOREIGNRECS) && format == FORMAT_HTML ) fb.safePrintf("F" ""); if ((flags & PFLAG_FOREIGNRECS) && format != FORMAT_HTML ) fb.safePrintf("Foreign data detected. " "Needs rebalance."); // if it has spiders going on say "S" with # as the superscript if ((flags & PFLAG_HASSPIDERS) && format == FORMAT_HTML ) fb.safePrintf ( "S" "%"INT32"" "" ,h->m_pingInfo.m_currentSpiders ); if ( format == FORMAT_HTML && h->m_pingInfo.m_udpSlotsInUseIncoming ) { char *f1 = ""; char *f2 = ""; // MAXUDPSLOTS in Spider.cpp is 300 right now if ( h->m_pingInfo.m_udpSlotsInUseIncoming >= 300 ) { f1 = ""; f2 = ""; } if ( h->m_pingInfo.m_udpSlotsInUseIncoming >= 400 ) { f1 = ""; f2 = ""; } fb.safePrintf("" "%s" "U" "%"INT32"" "%s" "" ,f1 ,h->m_pingInfo.m_udpSlotsInUseIncoming ,f2 ); } if ( format == FORMAT_HTML && h->m_pingInfo.m_tcpSocketsInUse){ char *f1 = ""; char *f2 = ""; if ( h->m_pingInfo.m_tcpSocketsInUse >= 100 ) { f1 = ""; f2 = ""; } if ( h->m_pingInfo.m_tcpSocketsInUse >= 200 ) { f1 = ""; f2 = ""; } fb.safePrintf("" "%s" "T" "%"INT32"" "%s" "" ,f1 ,h->m_pingInfo.m_tcpSocketsInUse ,f2 ); } if ((flags & PFLAG_HASSPIDERS) && format != FORMAT_HTML ) fb.safePrintf ( "Spidering"); // say "M" if merging if ( (flags & PFLAG_MERGING) && format == FORMAT_HTML ) fb.safePrintf ( "M"); if ( (flags & PFLAG_MERGING) && format != FORMAT_HTML ) fb.safePrintf ( "Merging"); // say "D" if dumping if ( (flags & PFLAG_DUMPING) && format == FORMAT_HTML ) fb.safePrintf ( "D"); if ( (flags & PFLAG_DUMPING) && format != FORMAT_HTML ) fb.safePrintf ( "Dumping"); // say "y" if doing the daily merge if ( !(flags & PFLAG_MERGEMODE0) ) fb.safePrintf ( "y"); if ( format == FORMAT_HTML && !h->m_spiderEnabled) { fb.safePrintf("S"); } if ( format == FORMAT_HTML && !h->m_queryEnabled) { fb.safePrintf("Q"); } // clear it if it is us, this is invalid if ( ! h->m_gotPingReply ) { fb.reset(); fb.safePrintf("??"); } if ( fb.length() == 0 && format == FORMAT_HTML ) fb.safePrintf(" "); fb.nullTerm(); char *bg = LIGHT_BLUE; if ( h->m_ping >= g_conf.m_deadHostTimeout ) bg = "ffa6a6"; // // BEGIN XML OUTPUT // if ( format == FORMAT_XML ) { sb.safePrintf("\t\n" "\t\tm_hostname); sb.safePrintf("]]>\n"); sb.safePrintf("\t\t%"INT32"\n", (int32_t)h->m_shardNum); sb.safePrintf("\t\t%"INT32"\n", h->m_stripe); sb.safePrintf("\t\t%s\n", iptoa(h->m_ip)); sb.safePrintf("\t\t%s\n", iptoa(h->m_ipShotgun)); sb.safePrintf("\t\t%"INT32"\n", (int32_t)h->m_httpPort); sb.safePrintf("\t\t%"INT32"\n", (int32_t)h->m_port); sb.safePrintf("\t\t%"INT32"\n", (int32_t)h->m_dnsClientPort); //sb.safePrintf("\t\t%s\n",hdbuf); sb.safePrintf("\t\t%s\n",vbuf); sb.safePrintf("\t\t%"INT32"\n", h->m_pingInfo.m_totalResends); /* MDW: take out for new stuff sb.safePrintf("\t\t%"INT32"\n", h->m_errorReplies); */ sb.safePrintf("\t\t%"INT32"" "\n", h->m_pingInfo.m_etryagains); sb.safePrintf("\t\t%"INT32"" "\n", h->m_pingInfo.m_udpSlotsInUseIncoming); sb.safePrintf("\t\t%"INT32"" "\n", h->m_pingInfo.m_tcpSocketsInUse); /* sb.safePrintf("\t\t%"INT64"\n", h->m_dgramsTo); sb.safePrintf("\t\t%"INT64"\n", h->m_dgramsFrom); */ sb.safePrintf("\t\t%"INT32"" "\n" ,h->m_pingInfo.m_numCorruptDiskReads); sb.safePrintf("\t\t%"INT32"" "\n" ,h->m_pingInfo.m_numOutOfMems); sb.safePrintf("\t\t%"INT32"" "\n" ,h->m_pingInfo. m_socketsClosedFromHittingLimit); sb.safePrintf("\t\t%"INT32"" "\n" ,h->m_pingInfo.m_currentSpiders ); sb.safePrintf("\t\t%"INT32"\n", splitTime); sb.safePrintf("\t\t%"INT32"\n", h->m_splitsDone); sb.safePrintf("\t\t\n", fb.getBufStart()); sb.safePrintf("\t\t%"INT32"" "\n", h->m_pingInfo.m_slowDiskReads); sb.safePrintf("\t\t%"INT32"" "\n", h->m_pingInfo.m_totalDocsIndexed); sb.safePrintf("\t\t%.1f%%" "", h->m_pingInfo.m_percentMemUsed); // float sb.safePrintf("\t\t%.1f%%" "", cpu ); sb.safePrintf("\t\t" "", diskUsageMsg); sb.safePrintf("\t\t%s\n", pms ); sb.safePrintf("\t\t%"INT32"ms\n", pingAge ); sb.safePrintf("\t\t%s\n", ptr ); sb.safePrintf("\t\t%s\n", h->m_note ); sb.safePrintf("\t\t%"INT32"\n", (int32_t)h->m_spiderEnabled ); sb.safePrintf("\t\t%"INT32"\n", (int32_t)h->m_queryEnabled ); sb.safePrintf("\t\n"); continue; } // // END XML OUTPUT // // // BEGIN JSON OUTPUT // if ( format == FORMAT_JSON ) { sb.safePrintf("\t\"host\":{\n"); sb.safePrintf("\t\t\"name\":\"%s\",\n",h->m_hostname); sb.safePrintf("\t\t\"shard\":%"INT32",\n", (int32_t)h->m_shardNum); sb.safePrintf("\t\t\"mirror\":%"INT32",\n", h->m_stripe); sb.safePrintf("\t\t\"ip1\":\"%s\",\n",iptoa(h->m_ip)); sb.safePrintf("\t\t\"ip2\":\"%s\",\n", iptoa(h->m_ipShotgun)); sb.safePrintf("\t\t\"httpPort\":%"INT32",\n", (int32_t)h->m_httpPort); sb.safePrintf("\t\t\"udpPort\":%"INT32",\n", (int32_t)h->m_port); sb.safePrintf("\t\t\"dnsPort\":%"INT32",\n", (int32_t)h->m_dnsClientPort); //sb.safePrintf("\t\t\"hdTemp\":\"%s\",\n",hdbuf); sb.safePrintf("\t\t\"gbVersion\":\"%s\",\n",vbuf); sb.safePrintf("\t\t\"resends\":%"INT32",\n", h->m_pingInfo.m_totalResends); /* sb.safePrintf("\t\t\"errorReplies\":%"INT32",\n", h->m_errorReplies); */ sb.safePrintf("\t\t\"errorTryAgains\":%"INT32",\n", h->m_pingInfo.m_etryagains); sb.safePrintf("\t\t\"udpSlotsInUse\":%"INT32",\n", h->m_pingInfo.m_udpSlotsInUseIncoming); sb.safePrintf("\t\t\"tcpSocketsInUse\":%"INT32",\n", h->m_pingInfo.m_tcpSocketsInUse); /* sb.safePrintf("\t\t\"dgramsTo\":%"INT64",\n", h->m_dgramsTo); sb.safePrintf("\t\t\"dgramsFrom\":%"INT64",\n", h->m_dgramsFrom); */ sb.safePrintf("\t\t\"numCorruptDiskReads\":%"INT32",\n" ,h->m_pingInfo.m_numCorruptDiskReads); sb.safePrintf("\t\t\"numOutOfMems\":%"INT32",\n" ,h->m_pingInfo.m_numOutOfMems); sb.safePrintf("\t\t\"numClosedSockets\":%"INT32",\n" ,h->m_pingInfo. m_socketsClosedFromHittingLimit); sb.safePrintf("\t\t\"numOutstandingSpiders\":%"INT32"" ",\n" ,h->m_pingInfo.m_currentSpiders ); sb.safePrintf("\t\t\"splitTime\":%"INT32",\n", splitTime); sb.safePrintf("\t\t\"splitsDone\":%"INT32",\n", h->m_splitsDone); sb.safePrintf("\t\t\"status\":\"%s\",\n", fb.getBufStart()); sb.safePrintf("\t\t\"slowDiskReads\":%"INT32",\n", h->m_pingInfo.m_slowDiskReads); sb.safePrintf("\t\t\"docsIndexed\":%"INT32",\n", h->m_pingInfo.m_totalDocsIndexed); sb.safePrintf("\t\t\"percentMemUsed\":\"%.1f%%\",\n", h->m_pingInfo.m_percentMemUsed); // float sb.safePrintf("\t\t\"cpuUsage\":\"%.1f%%\",\n",cpu); sb.safePrintf("\t\t\"percentDiskUsed\":\"%s\",\n", diskUsageMsg); sb.safePrintf("\t\t\"maxPing1\":\"%s\",\n",pms); sb.safePrintf("\t\t\"maxPingAge1\":\"%"INT32"ms\",\n", pingAge ); sb.safePrintf("\t\t\"ping1\":\"%s\",\n", ptr ); sb.safePrintf("\t\t\"note\":\"%s\"\n", h->m_note ); sb.safePrintf("\t\t\"spider\":\"%"INT32"\"\n", (int32_t)h->m_spiderEnabled ); sb.safePrintf("\t\t\"query\":\"%"INT32"\"\n", (int32_t)h->m_queryEnabled ); sb.safePrintf("\t},\n"); continue; } // // END JSON OUTPUT // sb.safePrintf ( "" "" "" // hostname "" // group "" // stripe //"" // group mask //"" // ip1 //"" // ip2 //"" // port //"" // client port "" // http port //"" // token group num //"" // switch group //"" // tmpN //"" // ide channel // hd temps // no, this is gb version now "" // resends "" // error replies //"" // etryagains "" // # dgrams sent to //"" // # dgrams recvd from //"" // loadavg //"" // split time "" // splits done "" // flags "" // slow disk reads "" // docs indexed "" // percent mem used "" // cpu usage "" // disk usage "" // ping max "" // ping age "" // ping "" //"" //"" "" "" , bg,//LIGHT_BLUE , ipbuf3, h->m_httpPort, cs, sort, i , h->m_hostname, (int32_t)h->m_shardNum,//group, h->m_stripe, // group mask is not looked at a lot and is // really only for indexdb and a few other rdbs //g_hostdb.makeGroupId(i,ng) , //ipbuf1, //ipbuf2, //h->m_port , //h->m_dnsClientPort , h->m_httpPort , //h->m_tokenGroupNum, //switchGroup , //tmpN, //h->m_ideChannel, vbuf1, vbuf,//hdbuf, vbuf2, h->m_pingInfo.m_totalResends, // h->m_errorReplies, h->m_pingInfo.m_etryagains, // h->m_dgramsTo, // h->m_dgramsFrom, //h->m_loadAvg, // double splitTime, h->m_splitsDone, fb.getBufStart(),//flagString, h->m_pingInfo.m_slowDiskReads, h->m_pingInfo.m_totalDocsIndexed, fontTagFront, h->m_pingInfo.m_percentMemUsed, // float fontTagBack, cpu, // float diskUsageMsg, // ping max pms, // ping age pingAge, //avg , //stdDev, //ping, ptr , //ptr2 , h->m_note ); } if ( format == FORMAT_XML ) { sb.safePrintf("\n"); return g_httpServer.sendDynamicPage ( s , sb.getBufStart(), sb.length() , 0, false, "text/xml"); } if ( format == FORMAT_JSON ) { // remove last \n, from json host{} sb.m_length -= 2; sb.safePrintf("\n}\n}"); return g_httpServer.sendDynamicPage ( s , sb.getBufStart(), sb.length() , 0, false, "application/json"); } // end the table now sb.safePrintf ( "
" //"" "Hosts " "(" "reset)" //"" "
" "hostIdhost ipshardmirrorgroup maskip1ip2udp portpriority udp portdns client porthttp porttoken groupbest switch idactual switch idswitch idide channelHD temps (C)GB versionresends senterrors recvdtry agains sent" "dgrams resent" "errors recvd" "ETRY AGAINS recvd" "dgrams to" "dgrams from" // "corrupts" // "# ooms" // "socks closed" //"loadavg" "avg split timesplits done" "status" "slow readsdocs indexed" "mem used" "cpu used" "disk used" "max ping1" "ping1 ageip1" "ping1ip2inSyncavg roundtripstd. dev.
note
%"INT32"%s%"INT32"%"INT32"0x%08"XINT32"%s%s%hi%hi%hi%"INT32"%"INT32"%s%"INT32"%s%s%s%"INT32"%"INT32"%"INT32"%"INT64"%"INT64"%.2f%"INT32"%"INT32"%s%"INT32"%"INT32"%s%.1f%%%s%.1f%%%s%s%"INT32"ms%s%s%"INT32"ms%s

\n" ); if( g_hostdb.m_numSpareHosts ) { // print spare hosts table sb.safePrintf ( "" "" "" "" "" "" "" //"" //"" //"" "" //"" // this is now fairly obsolete //"" "", TABLE_STYLE, DARK_BLUE ); for ( int32_t i = 0; i < g_hostdb.m_numSpareHosts; i++ ) { // get the ith host (hostId) Host *h = g_hostdb.getSpare ( i ); char ipbuf1[64]; char ipbuf2[64]; strcpy(ipbuf1,iptoa(h->m_ip)); strcpy(ipbuf2,iptoa(h->m_ipShotgun)); // print it sb.safePrintf ( "" "" "" "" "" //"" //"" // priority udp port //"" "" //"" // switch id //"" // ide channel "" "" , LIGHT_BLUE, i , h->m_hostname, ipbuf1, ipbuf2, //h->m_port , //h->m_port2 , //h->m_dnsClientPort , h->m_httpPort , //h->m_switchId, //h->m_ideChannel , h->m_note ); } sb.safePrintf ( "
" //"" "Spares" //"" "
spareIdhost nameip1ip2udp portpriority udp portdns client porthttp portswitch idide channelnote
%"INT32"%s%s%s%hi%hi%hi%hi%i%"INT32"%s

" ); } /* // print proxy hosts table sb.safePrintf ( "" "" "" "" "" "" "" "" //"" //"" //"" "" //"" "" "" "" //"" // this is now fairly obsolete //"" "", TABLE_STYLE, DARK_BLUE ); for ( int32_t i = 0; i < g_hostdb.m_numProxyHosts; i++ ) { // get the ith host (hostId) Host *h = g_hostdb.getProxy ( i ); char ptr[256]; int32_t pingAge = generatePingMsg(h, nowmsLocal, ptr); char ipbuf1[64]; char ipbuf2[64]; strcpy(ipbuf1,iptoa(h->m_ip)); strcpy(ipbuf2,iptoa(h->m_ipShotgun)); // host can have 2 ip addresses, get the one most // similar to that of the requester int32_t eip = g_hostdb.getBestIp ( h , s->m_ip ); char ipbuf3[64]; strcpy(ipbuf3,iptoa(eip)); char pms[64]; if ( h->m_pingMax < 0 ) sprintf(pms,"???"); else sprintf(pms,"%"INT32"ms",h->m_pingMax); // the sync status ascii-ized char *type = "proxy"; if ( h->m_type == HT_QCPROXY ) type = "qcproxy"; if ( h->m_type == HT_SCPROXY ) type = "scproxy"; // print it sb.safePrintf ( "" "" "" "" "" "" //"" //"" // priority udp port //"" "" //"" // switch id "" // ping max "" // ping age "" // ping //"" // ide channel "" "" , LIGHT_BLUE, ipbuf3, h->m_httpPort, cs, i , type, h->m_hostname, ipbuf1, ipbuf2, //h->m_port , //h->m_port2 , //h->m_dnsClientPort , h->m_httpPort , //h->m_switchId, pms, pingAge, ptr, //h->m_ideChannel , h->m_note ); } sb.safePrintf ( "
" //"" "Proxies" //"" "
proxyIdtypehost nameip1ip2udp portpriority udp portdns client porthttp portswitch idmax ping1ping1 ageping1ping2ide channelnote
" "%"INT32"%s%s%s%s%hi%hi%hi%hi%i%s%"INT32"ms%s%"INT32"%s


" ); */ sb.safePrintf( "\n" , LIGHT_BLUE ); // print help table sb.safePrintf ( "" "" "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" /* "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" */ /* "" "" "" "\n" */ "" "" "" "\n" /* "" "" "" "\n" */ "" "" "" "\n" /* "" "" "" "\n" "" "" "" "\n" */ "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" //"" //"" //"" //"\n" "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" /* "" "" "" "\n" */ "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" "" "" "" "\n" , TABLE_STYLE ); sb.safePrintf ( "
" //"" "Key" //"" "
host ipThe primary IP address of the host." "
shard" "The index is split into shards. Which shard does this " "host serve?" "
mirror" "A shard can be mirrored multiple times for " "data redundancy." "
ip2The secondary IP address of the host." "
udp portThe UDP port the host uses to send and receive " "datagrams." "
dns client portThe UDP port used to send and receive dns traffic with." "
http portThe port you can connect a browser to." "
best switch idThe host prefers to be on this switch because it " "needs to send a lot of data to other hosts on this switch. " "Therefore, ideally, the best switch id should match the " "actual switch id for optimal performance." "
switch idHosts that share the same switch id are " "physically on the same switch." "
dgrams resentHow many datagrams have had to be resent to a host " "because it was not ACKed quick enough or because it was " "fully ACKed but the entire request was resent in case " "the host was reset." "
errors recvdHow many errors were received from a host in response " "to a request to retrieve or insert data." "
try agains sentHow many ETRYAGAIN errors " "has this host sent out? they are sent out some times " "in response to a " "request to add data. Usually because the host's memory " "is full and it is dumping its data to disk. This number " "can be relatively high if the host if failing to dump " "the data " "to disk because of some malfunction, and it can therefore " "bottleneck the entire cluster." "
dgrams toHow many datagrams were sent to the host from the " "selected host since startup. Includes ACK datagrams. This " "can actually be higher than the number of dgrams read " "when the selected host is the same as the host in the " "table because of resends. Gigablast will resend datagrams " "that are not promptly ACKknowledged." "
dgrams fromHow many datagrams were received from the host by the " "selected host since startup. Includes ACK datagrams." "
avg split timeAverage time this host took to compute the docids " "for a query. Useful for guaging the slowness of a host " "compare to other hosts." "
splits doneNumber of queries this host completed. Used in " "computation of the avg split time." "
statusStatus flags for the host. See key below." "
slow readsNumber of slow disk reads the host has had. " "When this is big compared to other hosts it is a good " "indicator its drives are relatively slow." "
docs indexedNumber of documents this host has indexed over all " "collections. All hosts should have close to the same " "number in a well-sharded situation." "
loadavg1-minute sliding-window load average from " //"/proc/loadavg." //"
mem usedPercentage of memory currently used." "
cpu usedPercentage of cpu resources in use by the gb process." "
disk usedPercentage of disk in use. When this gets close to " "100%% you need to do something." "
max ping1The worst ping latency from host to host." "
ping1 ageHow long ago the last ping request was sent to " "this host. Let's us know how fresh the ping time is." "
ping1Ping time to this host on the primary network." "
ping2Ping time to this host on the seconday/shotgun " "network. This column is not visible if the shotgun " "network is not enabled in the master controls." "
M (status flag)Indicates host is merging files on disk." "
D (status flag)Indicates host is dumping data to disk." "
S (status flag)Indicates host has outstanding spiders." "
y (status flag)Indicates host is performing the daily merge." "
R (status flag)Indicates host is performing a rebalance operation." "
F (status flag)Indicates host has foreign records and requires " "a rebalance operation." "
x (status flag)Indicates host has abruptly exited due to a fatal " "error (cored) and " "restarted itself. The exponent is how many times it has " "done this. If no exponent, it only did it once." "
C (status flag)Indicates # of corrupted disk reads." "
K (status flag)Indicates # of sockets closed from hitting limit." "
O (status flag)Indicates # of times we ran out of memory." "
N (status flag)Indicates host's clock is NOT in sync with host #0. " "Gigablast should automatically sync on startup, " "so this would be a problem " "if it does not go away. Hosts need to have their clocks " "in sync before they can add data to their index." "
U (status flag)Indicates the number of active UDP transactions " "which are incoming requests. These will pile up if a " "host can't handle them fast enough." "
T (status flag)Indicates the number of active TCP transactions " "which are either outgoing or incoming requests." "


" ); //p = g_pages.printAdminBottom ( p , pend ); // calculate buffer length //int32_t bufLen = p - buf; // . send this page // . encapsulates in html header and tail // . make a Mime return g_httpServer.sendDynamicPage ( s , (char*) sb.getBufStart() , sb.length() ); } int32_t generatePingMsg( Host *h, int64_t nowms, char *buf ) { int32_t ping = h->m_ping; // show ping age first int32_t pingAge = nowms- h->m_lastPing; // if host is us, we don't ping ourselves if ( h->m_hostId == g_hostdb.m_hostId && h == g_hostdb.m_myHost) pingAge = 0; // if last ping is still 0, we haven't pinged it yet if ( h->m_lastPing == 0 ) pingAge = 0; // ping to string sprintf ( buf , "%"INT32"ms", ping ); // ping time ptr // make it "DEAD" if > 6000 if ( ping >= g_conf.m_deadHostTimeout ) { // mark SYNC if doing a sync if ( h->m_doingSync ) sprintf(buf, "SYNC"); else sprintf(buf, "DEAD"); } // for kernel errors else if ( h->m_pingInfo.m_kernelErrors > 0 ){ if ( h->m_pingInfo.m_kernelErrors == ME_IOERR ) sprintf(buf, "IOERR" ""); else if ( h->m_pingInfo.m_kernelErrors == ME_100MBPS ) sprintf(buf, "100MBPS" ""); else sprintf(buf, "KERNELERR" ""); } if ( ! g_conf.m_useShotgun ) return pingAge; char *p = buf + gbstrlen(buf); p += sprintf ( p , "" ); // the second eth port, ip2, the shotgun port int32_t pingB = h->m_pingShotgun; sprintf ( p , "%"INT32"ms", pingB ); if ( pingB >= g_conf.m_deadHostTimeout ) { // mark SYNC if doing a sync if ( h->m_doingSync ) sprintf(p,"SYNC"); else sprintf(p,"DEAD"); return pingAge; } return pingAge; } int defaultSort ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(int32_t*)i1 ); Host *h2 = g_hostdb.getHost ( *(int32_t*)i2 ); PingInfo *p1 = &h1->m_pingInfo; PingInfo *p2 = &h2->m_pingInfo; // float up to the top if the host is reporting kernel errors // even if the ping is normal if ( p1->m_kernelErrors > 0 && p2->m_kernelErrors <= 0 ) return -1; if ( p2->m_kernelErrors > 0 && p1->m_kernelErrors <= 0 ) return 1; if ( p2->m_kernelErrors > 0 && p1->m_kernelErrors > 0 ) { if ( h1->m_hostId < h2->m_hostId ) return -1; return 1; } if ( g_hostdb.isDead(h1) && ! g_hostdb.isDead(h2) ) return -1; if ( g_hostdb.isDead(h2) && ! g_hostdb.isDead(h1) ) return 1; if ( h1->m_hostId < h2->m_hostId ) return -1; return 1; } int pingSort1 ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(int32_t*)i1 ); Host *h2 = g_hostdb.getHost ( *(int32_t*)i2 ); PingInfo *p1 = &h1->m_pingInfo; PingInfo *p2 = &h2->m_pingInfo; // float up to the top if the host is reporting kernel errors // even if the ping is normal if ( p1->m_kernelErrors > 0 ) return -1; if ( p2->m_kernelErrors > 0 ) return 1; if ( h1->m_ping > h2->m_ping ) return -1; if ( h1->m_ping < h2->m_ping ) return 1; return 0; } int pingSort2 ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(int32_t*)i1 ); Host *h2 = g_hostdb.getHost ( *(int32_t*)i2 ); PingInfo *p1 = &h1->m_pingInfo; PingInfo *p2 = &h2->m_pingInfo; // float up to the top if the host is reporting kernel errors // even if the ping is normal if ( p1->m_kernelErrors > 0 ) return -1; if ( p2->m_kernelErrors > 0 ) return 1; if ( h1->m_pingShotgun > h2->m_pingShotgun ) return -1; if ( h1->m_pingShotgun < h2->m_pingShotgun ) return 1; return 0; } int pingMaxSort ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(int32_t*)i1 ); Host *h2 = g_hostdb.getHost ( *(int32_t*)i2 ); if ( h1->m_pingMax > h2->m_pingMax ) return -1; if ( h1->m_pingMax < h2->m_pingMax ) return 1; return 0; } int slowDiskSort ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(int32_t*)i1 ); Host *h2 = g_hostdb.getHost ( *(int32_t*)i2 ); PingInfo *p1 = &h1->m_pingInfo; PingInfo *p2 = &h2->m_pingInfo; if ( p1->m_slowDiskReads > p2->m_slowDiskReads ) return -1; if ( p1->m_slowDiskReads < p2->m_slowDiskReads ) return 1; return 0; } int pingAgeSort ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(int32_t*)i1 ); Host *h2 = g_hostdb.getHost ( *(int32_t*)i2 ); //PingInfo *p1 = &h1->m_pingInfo; //PingInfo *p2 = &h2->m_pingInfo; if ( h1->m_lastPing > h2->m_lastPing ) return -1; if ( h1->m_lastPing < h2->m_lastPing ) return 1; return 0; } int splitTimeSort ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(int32_t*)i1 ); Host *h2 = g_hostdb.getHost ( *(int32_t*)i2 ); int32_t t1 = 0; int32_t t2 = 0; if ( h1->m_splitsDone > 0 ) t1 = h1->m_splitTimes / h1->m_splitsDone; if ( h2->m_splitsDone > 0 ) t2 = h2->m_splitTimes / h2->m_splitsDone; if ( t1 > t2 ) return -1; if ( t1 < t2 ) return 1; return 0; } int flagSort ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(int32_t*)i1 ); Host *h2 = g_hostdb.getHost ( *(int32_t*)i2 ); PingInfo *p1 = &h1->m_pingInfo; PingInfo *p2 = &h2->m_pingInfo; if ( p1->m_flags > p2->m_flags ) return -1; if ( p1->m_flags < p2->m_flags ) return 1; return 0; } int resendsSort ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(int32_t*)i1 ); Host *h2 = g_hostdb.getHost ( *(int32_t*)i2 ); if ( h1->m_pingInfo.m_totalResends > h2->m_pingInfo.m_totalResends ) return -1; if ( h1->m_pingInfo.m_totalResends < h2->m_pingInfo.m_totalResends ) return 1; return 0; } int errorsSort ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(int32_t*)i1 ); Host *h2 = g_hostdb.getHost ( *(int32_t*)i2 ); if ( h1->m_errorReplies > h2->m_errorReplies ) return -1; if ( h1->m_errorReplies < h2->m_errorReplies ) return 1; return 0; } int tryagainSort ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(int32_t*)i1 ); Host *h2 = g_hostdb.getHost ( *(int32_t*)i2 ); if ( h1->m_pingInfo.m_etryagains>h2->m_pingInfo.m_etryagains)return -1; if ( h1->m_pingInfo.m_etryagainsm_pingInfo.m_etryagains)return 1; return 0; } int dgramsToSort ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(int32_t*)i1 ); Host *h2 = g_hostdb.getHost ( *(int32_t*)i2 ); if ( h1->m_dgramsTo > h2->m_dgramsTo ) return -1; if ( h1->m_dgramsTo < h2->m_dgramsTo ) return 1; return 0; } int dgramsFromSort ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(int32_t*)i1 ); Host *h2 = g_hostdb.getHost ( *(int32_t*)i2 ); if ( h1->m_dgramsFrom > h2->m_dgramsFrom ) return -1; if ( h1->m_dgramsFrom < h2->m_dgramsFrom ) return 1; return 0; } /* int loadAvgSort ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(int32_t*)i1 ); Host *h2 = g_hostdb.getHost ( *(int32_t*)i2 ); if ( h1->m_loadAvg > h2->m_loadAvg ) return -1; if ( h1->m_loadAvg < h2->m_loadAvg ) return 1; return 0; } */ int memUsedSort ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(int32_t*)i1 ); Host *h2 = g_hostdb.getHost ( *(int32_t*)i2 ); PingInfo *p1 = &h1->m_pingInfo; PingInfo *p2 = &h2->m_pingInfo; if ( p1->m_percentMemUsed > p2->m_percentMemUsed ) return -1; if ( p1->m_percentMemUsed < p2->m_percentMemUsed ) return 1; return 0; } int cpuUsageSort ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(int32_t*)i1 ); Host *h2 = g_hostdb.getHost ( *(int32_t*)i2 ); PingInfo *p1 = &h1->m_pingInfo; PingInfo *p2 = &h2->m_pingInfo; if ( p1->m_cpuUsage > p2->m_cpuUsage ) return -1; if ( p1->m_cpuUsage < p2->m_cpuUsage ) return 1; return 0; } int diskUsageSort ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(int32_t*)i1 ); Host *h2 = g_hostdb.getHost ( *(int32_t*)i2 ); PingInfo *p1 = &h1->m_pingInfo; PingInfo *p2 = &h2->m_pingInfo; if ( p1->m_diskUsage > p2->m_diskUsage ) return -1; if ( p1->m_diskUsage < p2->m_diskUsage ) return 1; return 0; } //bool sendPageHostsInXmlOrJson ( TcpSocket *s , HttpRequest *r ) { //}