#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 ); long generatePingMsg( Host *h, long long 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 long 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 long setnote = r->getLong("setnote", 0); long setsparenote = r->getLong("setsparenote", 0); // check for replace host command long replaceHost = r->getLong("replacehost", 0); // check for sync host command long syncHost = r->getLong("synchost", 0); // set note... if ( setnote == 1 ) { // get the host id to change long host = r->getLong("host", -1); if ( host == -1 ) goto skipReplaceHost; // get the note to set long 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 long spare = r->getLong("spare", -1); if ( spare == -1 ) goto skipReplaceHost; // get the note to set long 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 long rhost = r->getLong("rhost", -1); long 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 long 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 long syncHost = r->getLong("shost", -1); if ( syncHost == -1 ) goto skipReplaceHost; // call sync g_hostdb.syncHost(syncHost, true); //g_syncdb.syncHost ( syncHost ); } skipReplaceHost: long 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 //"" //"" "" //"" //"" //"" "" "" "" "" "" //"" "" "" "" "" "" "" "" "" "" "" //"" "" "%s"// "" //"", //"" //"" "", TABLE_STYLE , colspan , cs, sort, DARK_BLUE , cs, cs, cs, cs, cs, cs, cs, cs, cs, cs, cs, cs, cs, cs, cs, shotcol ); // loop through each host we know and print it's stats long nh = g_hostdb.getNumHosts(); // should we reset resends, errorsRecvd and ETRYAGAINS recvd? if ( r->getLong("reset",0) ) { for ( long i = 0 ; i < nh ; i++ ) { // get the ith host (hostId) Host *h = g_hostdb.getHost ( i ); h->m_totalResends = 0; h->m_errorReplies = 0; h->m_etryagains = 0; h->m_dgramsTo = 0; h->m_dgramsFrom = 0; } } // sort hosts if needed long hostSort [ MAX_HOSTS ]; for ( long i = 0 ; i < nh ; i++ ) hostSort [ i ] = i; switch ( sort ) { case 1: gbsort ( hostSort, nh, sizeof(long), pingSort1 ); break; case 2: gbsort ( hostSort, nh, sizeof(long), pingSort2 ); break; case 3: gbsort ( hostSort, nh, sizeof(long), resendsSort ); break; case 4: gbsort ( hostSort, nh, sizeof(long), errorsSort ); break; case 5: gbsort ( hostSort, nh, sizeof(long), tryagainSort ); break; case 6: gbsort ( hostSort, nh, sizeof(long), dgramsToSort ); break; case 7: gbsort ( hostSort, nh, sizeof(long), dgramsFromSort ); break; //case 8: gbsort ( hostSort, nh, sizeof(long), loadAvgSort ); break; case 9: gbsort ( hostSort, nh, sizeof(long), memUsedSort ); break; case 10:gbsort ( hostSort, nh, sizeof(long), cpuUsageSort ); break; case 11:gbsort ( hostSort, nh, sizeof(long), pingAgeSort ); break; case 12:gbsort ( hostSort, nh, sizeof(long), flagSort ); break; case 13:gbsort ( hostSort, nh, sizeof(long), splitTimeSort ); break; case 14:gbsort ( hostSort, nh, sizeof(long), pingMaxSort ); break; case 15:gbsort ( hostSort, nh, sizeof(long), slowDiskSort ); break; case 16:gbsort ( hostSort, nh, sizeof(long), defaultSort ); break; case 17:gbsort ( hostSort, nh, sizeof(long), 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"); } long long nowmsLocal = gettimeofdayInMillisecondsLocal(); // compute majority gb version so we can highlight bad out of sync // gb versions in red below long majorityHash32 = 0; long lastCount = 0; // get majority gb version for ( long si = 0 ; si < nh ; si++ ) { long i = hostSort[si]; // get the ith host (hostId) Host *h = g_hostdb.getHost ( i ); char *vbuf = h->m_gbVersionStrBuf; long vhash32 = hash32n ( vbuf ); if ( vhash32 == majorityHash32 ) lastCount++; else lastCount--; if ( lastCount < 0 ) majorityHash32 = vhash32; } // print it //long ng = g_hostdb.getNumGroups(); for ( long si = 0 ; si < nh ; si++ ) { long 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 //long avg , stdDev; //g_hostdb.getTimes ( i , &avg , &stdDev ); char ptr[256]; long pingAge = generatePingMsg(h, nowmsLocal, ptr); char pms[64]; if ( h->m_pingMax < 0 ) sprintf(pms,"???"); else sprintf(pms,"%lims",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 ( long k = 0 ; k < 4 ; k++ ) { long temp = h->m_hdtemps[k]; if ( temp > 50 && format == FORMAT_HTML ) hp += sprintf(hp,"%li" "", temp); else hp += sprintf(hp,"%li",temp); if ( k < 3 ) *hp++ = '/'; *hp = '\0'; } */ char *vbuf = h->m_gbVersionStrBuf; // get hash long vhash32 = hash32n ( vbuf ); char *vbuf1 = ""; char *vbuf2 = ""; if ( vhash32 != majorityHash32 ) { vbuf1 = ""; vbuf2 = ""; } //long 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, "%li", // (long)h->m_switchId); //else // sprintf(tmpN, "%li", (long)h->m_switchId); // host can have 2 ip addresses, get the one most // similar to that of the requester long eip = g_hostdb.getBestIp ( h , s->m_ip ); char ipbuf3[64]; strcpy(ipbuf3,iptoa(eip)); char *fontTagFront = ""; char *fontTagBack = ""; if ( h->m_percentMemUsed >= 98.0 && format == FORMAT_HTML ) { fontTagFront = ""; fontTagBack = ""; } float cpu = h->m_cpuUsage; if ( cpu > 100.0 ) cpu = 100.0; if ( cpu < 0.0 ) cpu = -1.0; char diskUsageMsg[64]; sprintf(diskUsageMsg,"%.1f%%",h->m_diskUsage); if ( h->m_diskUsage < 0.0 ) sprintf(diskUsageMsg,"???"); if ( h->m_diskUsage >= 98.0 && format == FORMAT_HTML ) sprintf(diskUsageMsg,"%.1f%%" "",h->m_diskUsage); // split time, don't divide by zero! long 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_hostsConfCRC && format == FORMAT_HTML && h->m_hostsConfCRC != g_hostdb.getCRC() ) fb.safePrintf("H" ""); if ( h->m_hostsConfCRC && format != FORMAT_HTML && h->m_hostsConfCRC != g_hostdb.getCRC() ) fb.safePrintf("Hosts.conf in disagreement with ours"); // recovery mode? reocvered from coring? if ((h->m_flags & PFLAG_RECOVERYMODE)&& format == FORMAT_HTML ) fb.safePrintf("x"); if ((h->m_flags & PFLAG_RECOVERYMODE)&& format != FORMAT_HTML ) fb.safePrintf("Recovered from core"); // rebalancing? if ( (h->m_flags & PFLAG_REBALANCING)&& format == FORMAT_HTML ) fb.safePrintf("R"); if ( (h->m_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 ((h->m_flags & PFLAG_FOREIGNRECS) && format == FORMAT_HTML ) fb.safePrintf("F" ""); if ((h->m_flags & PFLAG_FOREIGNRECS) && format != FORMAT_HTML ) fb.safePrintf("Foreign data detected. " "Needs rebalance."); // if it has spiders going on say "S" if ((h->m_flags & PFLAG_HASSPIDERS) && format == FORMAT_HTML ) fb.safePrintf ( "S"); if ((h->m_flags & PFLAG_HASSPIDERS) && format != FORMAT_HTML ) fb.safePrintf ( "Spidering"); // say "M" if merging if ( (h->m_flags & PFLAG_MERGING) && format == FORMAT_HTML ) fb.safePrintf ( "M"); if ( (h->m_flags & PFLAG_MERGING) && format != FORMAT_HTML ) fb.safePrintf ( "Merging"); // say "D" if dumping if ( (h->m_flags & PFLAG_DUMPING) && format == FORMAT_HTML ) fb.safePrintf ( "D"); if ( (h->m_flags & PFLAG_DUMPING) && format != FORMAT_HTML ) fb.safePrintf ( "Dumping"); // say "y" if doing the daily merge if ( !(h->m_flags & PFLAG_MERGEMODE0) ) fb.safePrintf ( "y"); // 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%li\n", h->m_shardNum); sb.safePrintf("\t\t%li\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%li\n", (long)h->m_httpPort); sb.safePrintf("\t\t%li\n", (long)h->m_port); sb.safePrintf("\t\t%li\n", (long)h->m_dnsClientPort); //sb.safePrintf("\t\t%s\n",hdbuf); sb.safePrintf("\t\t%s\n",vbuf); sb.safePrintf("\t\t%li\n", h->m_totalResends); sb.safePrintf("\t\t%li\n", h->m_errorReplies); sb.safePrintf("\t\t%li" "\n", h->m_etryagains); sb.safePrintf("\t\t%lli\n", h->m_dgramsTo); sb.safePrintf("\t\t%lli\n", h->m_dgramsFrom); sb.safePrintf("\t\t%li\n", splitTime); sb.safePrintf("\t\t%li\n", h->m_splitsDone); sb.safePrintf("\t\t\n", fb.getBufStart()); sb.safePrintf("\t\t%li" "\n", h->m_slowDiskReads); sb.safePrintf("\t\t%li" "\n", h->m_docsIndexed); sb.safePrintf("\t\t%.1f%%" "", h->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%lims\n", pingAge ); sb.safePrintf("\t\t%s\n", ptr ); sb.safePrintf("\t\t%s\n", h->m_note ); 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\":%li,\n", h->m_shardNum); sb.safePrintf("\t\t\"mirror\":%li,\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\":%li,\n", (long)h->m_httpPort); sb.safePrintf("\t\t\"udpPort\":%li,\n", (long)h->m_port); sb.safePrintf("\t\t\"dnsPort\":%li,\n", (long)h->m_dnsClientPort); //sb.safePrintf("\t\t\"hdTemp\":\"%s\",\n",hdbuf); sb.safePrintf("\t\t\"gbVersion\":\"%s\",\n",vbuf); sb.safePrintf("\t\t\"resends\":%li,\n", h->m_totalResends); sb.safePrintf("\t\t\"errorReplies\":%li,\n", h->m_errorReplies); sb.safePrintf("\t\t\"errorTryAgains\":%li,\n", h->m_etryagains); sb.safePrintf("\t\t\"dgramsTo\":%lli,\n", h->m_dgramsTo); sb.safePrintf("\t\t\"dgramsFrom\":%lli,\n", h->m_dgramsFrom); sb.safePrintf("\t\t\"splitTime\":%li,\n", splitTime); sb.safePrintf("\t\t\"splitsDone\":%li,\n", h->m_splitsDone); sb.safePrintf("\t\t\"status\":\"%s\",\n", fb.getBufStart()); sb.safePrintf("\t\t\"slowDiskReads\":%li,\n", h->m_slowDiskReads); sb.safePrintf("\t\t\"docsIndexed\":%li,\n", h->m_docsIndexed); sb.safePrintf("\t\t\"percentMemUsed\":\"%.1f%%\",\n", h->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\":\"%lims\",\n", pingAge ); sb.safePrintf("\t\t\"ping1\":\"%s\",\n", ptr ); sb.safePrintf("\t\t\"note\":\"%s\"\n", h->m_note ); 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, 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_totalResends, h->m_errorReplies, h->m_etryagains, h->m_dgramsTo, h->m_dgramsFrom, //h->m_loadAvg, // double splitTime, h->m_splitsDone, fb.getBufStart(),//flagString, h->m_slowDiskReads, h->m_docsIndexed, fontTagFront, h->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 recvdETRYAGAINS recvd" "dgrams resent" "errors recvd" "ETRY AGAINS recvd" "dgrams to" "dgrams from" //"loadavg" "avg split timesplits done" "status" "slow readsdocs indexed" "mem used" "cpu used" "disk used" "max ping1" "ping1 ageip1" "ping1ip2inSyncavg roundtripstd. dev.
note
%li%s%li%li0x%08lx%s%s%hi%hi%hi%li%li%s%li%s%s%s%li%li%li%lli%lli%.2f%li%li%s%li%li%s%.1f%%%s%.1f%%%s%s%lims%s%s%lims%s

\n" ); /* // print spare hosts table sb.safePrintf ( "" "" "" "" "" "" "" //"" //"" //"" "" //"" // this is now fairly obsolete //"" "", TABLE_STYLE, DARK_BLUE ); for ( long 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
%li%s%s%s%hi%hi%hi%hi%i%li%s

" ); */ /* // print proxy hosts table sb.safePrintf ( "" "" "" "" "" "" "" "" //"" //"" //"" "" //"" "" "" "" //"" // this is now fairly obsolete //"" "", TABLE_STYLE, DARK_BLUE ); for ( long i = 0; i < g_hostdb.m_numProxyHosts; i++ ) { // get the ith host (hostId) Host *h = g_hostdb.getProxy ( i ); char ptr[256]; long 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 long 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,"%lims",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
" "%li%s%s%s%s%hi%hi%hi%hi%i%s%ldms%s%li%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" , 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 recieve " "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 swtich. " "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." "
ETRYAGAINS recvdHow many ETRYAGAIN were received 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 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." "


" ); //p = g_pages.printAdminBottom ( p , pend ); // calculate buffer length //long 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() ); } long generatePingMsg( Host *h, long long nowms, char *buf ) { long ping = h->m_ping; // show ping age first long 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 , "%lims", 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_kernelErrors > 0 ){ if ( h->m_kernelErrors == ME_IOERR ) sprintf(buf, "IOERR" ""); else if ( h->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 long pingB = h->m_pingShotgun; sprintf ( p , "%lims", 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 ( *(long*)i1 ); Host *h2 = g_hostdb.getHost ( *(long*)i2 ); // float up to the top if the host is reporting kernel errors // even if the ping is normal if ( h1->m_kernelErrors > 0 && h2->m_kernelErrors <= 0 ) return -1; if ( h2->m_kernelErrors > 0 && h1->m_kernelErrors <= 0 ) return 1; if ( h2->m_kernelErrors > 0 && h1->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 ( *(long*)i1 ); Host *h2 = g_hostdb.getHost ( *(long*)i2 ); // float up to the top if the host is reporting kernel errors // even if the ping is normal if ( h1->m_kernelErrors > 0 ) return -1; if ( h2->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 ( *(long*)i1 ); Host *h2 = g_hostdb.getHost ( *(long*)i2 ); // float up to the top if the host is reporting kernel errors // even if the ping is normal if ( h1->m_kernelErrors > 0 ) return -1; if ( h2->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 ( *(long*)i1 ); Host *h2 = g_hostdb.getHost ( *(long*)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 ( *(long*)i1 ); Host *h2 = g_hostdb.getHost ( *(long*)i2 ); if ( h1->m_slowDiskReads > h2->m_slowDiskReads ) return -1; if ( h1->m_slowDiskReads < h2->m_slowDiskReads ) return 1; return 0; } int pingAgeSort ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(long*)i1 ); Host *h2 = g_hostdb.getHost ( *(long*)i2 ); 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 ( *(long*)i1 ); Host *h2 = g_hostdb.getHost ( *(long*)i2 ); long t1 = 0; long 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 ( *(long*)i1 ); Host *h2 = g_hostdb.getHost ( *(long*)i2 ); if ( h1->m_flags > h2->m_flags ) return -1; if ( h1->m_flags < h2->m_flags ) return 1; return 0; } int resendsSort ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(long*)i1 ); Host *h2 = g_hostdb.getHost ( *(long*)i2 ); if ( h1->m_totalResends > h2->m_totalResends ) return -1; if ( h1->m_totalResends < h2->m_totalResends ) return 1; return 0; } int errorsSort ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(long*)i1 ); Host *h2 = g_hostdb.getHost ( *(long*)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 ( *(long*)i1 ); Host *h2 = g_hostdb.getHost ( *(long*)i2 ); if ( h1->m_etryagains > h2->m_etryagains ) return -1; if ( h1->m_etryagains < h2->m_etryagains ) return 1; return 0; } int dgramsToSort ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(long*)i1 ); Host *h2 = g_hostdb.getHost ( *(long*)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 ( *(long*)i1 ); Host *h2 = g_hostdb.getHost ( *(long*)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 ( *(long*)i1 ); Host *h2 = g_hostdb.getHost ( *(long*)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 ( *(long*)i1 ); Host *h2 = g_hostdb.getHost ( *(long*)i2 ); if ( h1->m_percentMemUsed > h2->m_percentMemUsed ) return -1; if ( h1->m_percentMemUsed < h2->m_percentMemUsed ) return 1; return 0; } int cpuUsageSort ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(long*)i1 ); Host *h2 = g_hostdb.getHost ( *(long*)i2 ); if ( h1->m_cpuUsage > h2->m_cpuUsage ) return -1; if ( h1->m_cpuUsage < h2->m_cpuUsage ) return 1; return 0; } int diskUsageSort ( const void *i1, const void *i2 ) { Host *h1 = g_hostdb.getHost ( *(long*)i1 ); Host *h2 = g_hostdb.getHost ( *(long*)i2 ); if ( h1->m_diskUsage > h2->m_diskUsage ) return -1; if ( h1->m_diskUsage < h2->m_diskUsage ) return 1; return 0; } //bool sendPageHostsInXmlOrJson ( TcpSocket *s , HttpRequest *r ) { //}