3
A brief file description
5
@section license License
7
Licensed to the Apache Software Foundation (ASF) under one
8
or more contributor license agreements. See the NOTICE file
9
distributed with this work for additional information
10
regarding copyright ownership. The ASF licenses this file
11
to you under the Apache License, Version 2.0 (the
12
"License"); you may not use this file except in compliance
13
with the License. You may obtain a copy of the License at
15
http://www.apache.org/licenses/LICENSE-2.0
17
Unless required by applicable law or agreed to in writing, software
18
distributed under the License is distributed on an "AS IS" BASIS,
19
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
See the License for the specific language governing permissions and
21
limitations under the License.
24
/****************************************************************************
26
* WebOverview.cc - code to overview page
29
****************************************************************************/
31
#include "ink_platform.h"
32
#include "ink_unused.h" /* MAGIC_EDITING_TAG */
34
#include "WebOverview.h"
35
#include "WebGlobals.h"
36
#include "WebHttpRender.h"
37
#include "WebHttpTree.h"
38
#include "WebMgmtUtils.h"
41
#include "ClusterCom.h"
44
#include "CLIlineBuffer.h"
47
// Make this pointer to avoid nasty destruction
48
// problems do to alarm
49
// fork, execl, exit squences
50
overviewPage *overviewGenerator;
52
overviewRecord::overviewRecord(unsigned long inet_addr, bool local, ClusterPeerInfo * cpi)
55
char *name_l; // hostname looked up from node record
57
struct in_addr nameFailed;
62
this->localNode = local;
64
// If this is the local node, there is no cluster peer info
65
// record. Remote nodes require a cluster peer info record
66
ink_assert((local == false && cpi != NULL)
67
|| (local == true && cpi == NULL));
69
// Set up the copy of the records array and initialize it
71
node_rec_data.num_recs = 0;
72
node_rec_data.recs = NULL;
74
node_rec_first_ix = 0;
76
node_rec_data.num_recs = cpi->node_rec_data.num_recs;
77
recordArraySize = node_rec_data.num_recs * sizeof(RecRecord);
78
node_rec_data.recs = new RecRecord[recordArraySize];
79
memcpy(node_rec_data.recs, cpi->node_rec_data.recs, recordArraySize);
81
// Recaculate the old relative index
82
RecGetRecordOrderAndId(node_rec_data.recs[0].name, &node_rec_first_ix, NULL);
86
// Query for the name of the node. If it is not there, some
87
// their cluster ip address
88
name_l = this->readString("proxy.node.hostname_FQ", &name_found);
89
if (name_found == false || name_l == NULL) {
90
nameFailed.s_addr = inetAddr;
91
mgmt_log("[overviewRecord::overviewRecord] Unable to find hostname for %s\n", inet_ntoa(nameFailed));
92
xfree(name_l); // about to overwrite name_l, so we need to free it first
93
name_l = xstrdup(inet_ntoa(nameFailed));
96
const size_t hostNameLen = strlen(name_l) + 1;
97
this->hostname = new char[hostNameLen];
98
ink_strncpy(this->hostname, name_l, hostNameLen);
102
overviewRecord::~overviewRecord()
109
for (a = nodeAlarms.pop(); a != NULL; a = nodeAlarms.pop()) {
113
if (localNode == false) {
114
delete[]node_rec_data.recs;
118
// void overviewRecord::getStatus(char**, PowerLampState* , bool*, bool*)
119
// Retrieves information about the node
121
// hostname - *hostname is set to point to a string containing the hostname
122
// for the node represented by the record The storage for
123
// this string belongs to this class instance and should
124
// not be freed by the caller
126
// *up - set to true if the node's manager is up
127
// Set to false otherwise
129
// *alarms - set to true if there are any pending alarms for this
130
// this node. Set to false if there are no pending
133
// *proxyUp - set to true is the proxy is up on the node and
137
overviewRecord::getStatus(char **hostnamePtr, bool * upPtr, bool * alarms, PowerLampState * proxyUpPtr)
140
*hostnamePtr = this->hostname;
143
if (this->up != true) {
144
*proxyUpPtr = LAMP_OFF;
146
if (this->readInteger("proxy.node.proxy_running", &found) != 1) {
147
*proxyUpPtr = LAMP_OFF;
149
if (this->localNode == true) {
150
// For the local node, make sure all the cluster connections
151
// are up. If not issue a warning lamp
152
if (lmgmt->clusterOk() == false) {
153
*proxyUpPtr = LAMP_WARNING;
155
*proxyUpPtr = LAMP_ON;
158
// We can not currently check remote node
160
*proxyUpPtr = LAMP_ON;
165
if (nodeAlarms.head == NULL) {
172
// void overviewRecord::updateStatus(time_t, ClusterPeerInfo*)
173
// updates up/down status based on the cluster peer info record
175
// currentTime is the value of localtime(time()) - sent in as
176
// a parameter so we do not have to make repetitive system calls.
177
// overviewPage::checkForUpdates can just make one call
179
// cpi - is a pointer to a structure we got from ClusterCom that represnets
180
// information about this node
182
// a machine is up if we have heard from it in the last 15 seconds
185
overviewRecord::updateStatus(time_t currentTime, ClusterPeerInfo * cpi)
188
// Update if the node is up or down
189
if (currentTime - cpi->idle_ticks > 15) {
195
// Update the node records by copying them from cpi
196
// (remote nodes only)
197
if (localNode == false) {
198
memcpy(node_rec_data.recs, cpi->node_rec_data.recs, recordArraySize);
199
RecGetRecordOrderAndId(node_rec_data.recs[0].name, &node_rec_first_ix, NULL);
203
// adds a new alarm to the list of current alarms for the node
205
overviewRecord::addAlarm(alarm_t type, char *ip, char *desc)
208
AlarmListable *alarm;
210
alarm = new AlarmListable;
214
nodeAlarms.push(alarm);
217
// adds a new alarm to the list of current alarms for the node
219
overviewRecord::addAlarm(AlarmListable * newAlarm)
221
nodeAlarms.push(newAlarm);
224
// bool overviewRecord::ipMatch(char* ipStr)
226
// Returns true if the passed in string matches
227
// the ip address for this node
229
overviewRecord::ipMatch(char *ipStr)
231
if (inet_addr(ipStr) == inetAddr) {
238
// Runs throught the list of current alarms on the node
239
// and asks the Alarms class if it is valid. If the alarm
240
// is expired it is removed from the alarm list
242
overviewRecord::checkAlarms()
245
AlarmListable *current;
248
current = nodeAlarms.head;
249
while (current != NULL) {
251
next = current->link.next;
253
if (!lmgmt->alarm_keeper->isCurrentAlarm(current->type, current->ip)) {
254
// The alarm is no longer current. Dispose of it
255
nodeAlarms.remove(current);
263
// overview::readCounter, overview::readInteger
264
// overview::readFloat, overview::readString
266
// Accessor functions for node records. For remote node,
267
// we get the value in the node_data array we maintain
268
// in this object. For the node, we do not maintain any data
269
// and rely on lmgmt->record_data for both the retrieval
270
// code and the records array
272
// Locking should be done by overviewPage::accessLock.
273
// CALLEE is responsible for obtaining and releasing the lock
276
overviewRecord::readCounter(const char *name, bool * found)
279
int rec_status = REC_ERR_OKAY;
281
if (localNode == false) {
282
rec_status = RecGetRecordOrderAndId(name, &order, NULL);
283
if (rec_status == REC_ERR_OKAY) {
284
order -= node_rec_first_ix; // Offset
285
ink_release_assert(order < node_rec_data.num_recs);
286
ink_debug_assert(order < node_rec_data.num_recs);
287
rec = node_rec_data.recs[order].data.rec_counter;
289
mgmt_log(stderr, "node variables '%s' not found!\n");
294
*found = (rec_status == REC_ERR_OKAY);
296
mgmt_log(stderr, "node variables '%s' not found!\n");
302
overviewRecord::readInteger(const char *name, bool * found)
305
int rec_status = REC_ERR_OKAY;
307
if (localNode == false) {
308
rec_status = RecGetRecordOrderAndId(name, &order, NULL);
309
if (rec_status == REC_ERR_OKAY) {
310
order -= node_rec_first_ix; // Offset
311
ink_release_assert(order < node_rec_data.num_recs);
312
ink_debug_assert(order < node_rec_data.num_recs);
313
rec = node_rec_data.recs[order].data.rec_int;
316
rec_status = RecGetRecordInt(name, &rec);
320
*found = (rec_status == REC_ERR_OKAY);
322
mgmt_log(stderr, "node variables '%s' not found!\n");
328
overviewRecord::readFloat(const char *name, bool * found)
331
int rec_status = REC_ERR_OKAY;
333
if (localNode == false) {
334
rec_status = RecGetRecordOrderAndId(name, &order, NULL);
335
if (rec_status == REC_ERR_OKAY) {
336
order -= node_rec_first_ix; // Offset
337
ink_release_assert(order < node_rec_data.num_recs);
338
ink_debug_assert(order < node_rec_data.num_recs);
339
rec = node_rec_data.recs[order].data.rec_float;
342
rec_status = RecGetRecordFloat(name, &rec);
346
*found = (rec_status == REC_ERR_OKAY);
348
mgmt_log(stderr, "node variables '%s' not found!\n");
354
overviewRecord::readString(const char *name, bool * found)
356
RecString rec = NULL;
357
int rec_status = REC_ERR_OKAY;
359
if (localNode == false) {
360
rec_status = RecGetRecordOrderAndId(name, &order, NULL);
361
if (rec_status == REC_ERR_OKAY) {
362
order -= node_rec_first_ix; // Offset
363
ink_release_assert(order < node_rec_data.num_recs);
364
ink_debug_assert(order < node_rec_data.num_recs);
365
rec = xstrdup(node_rec_data.recs[order].data.rec_string);
368
rec_status = RecGetRecordString_Xmalloc(name, &rec);
372
*found = (rec_status == REC_ERR_OKAY);
374
mgmt_log(stderr, "node variables '%s' not found!\n");
379
// bool overviewRecord::varStrFromName (char*, char*bufVal, char*, int)
381
// Accessor function for node records. Looks up varName for
382
// this node and if found, turns it value into a string
383
// and places it in bufVal
385
// return true if bufVal was succefully set
386
// and false otherwise
388
// EVIL ALERT: varStrFromName in WebMgmtUtils.cc is extremely
389
// similar to this function except in how it gets it's
390
// data. Changes to this fuction must be propogated
391
// to its twin. Cut and Paste sucks but there is not
392
// an easy way to merge the functions
395
overviewRecord::varStrFromName(const char *varNameConst, char *bufVal, int bufLen)
398
RecDataT varDataType;
401
char formatOption = '\0';
405
MgmtIntCounter counter_data; /* Data */
407
MgmtFloat float_data;
408
MgmtString string_data;
411
// Check to see if there is a \ option on the end of variable
412
// \ options indicate that we need special formatting
413
// of the results. Supported \ options are
415
/// b - bytes. Ints and Counts only. Amounts are
416
// transformed into one of GB, MB, KB, or B
418
varName = xstrdup(varNameConst);
419
varNameLen = strlen(varName);
420
if (varNameLen > 3 && varName[varNameLen - 2] == '\\') {
421
formatOption = varName[varNameLen - 1];
423
// Now that we know the format option, terminate the string
424
// to make the option disappear
425
varName[varNameLen - 2] = '\0';
427
// Return not found for unknown format options
428
if (formatOption != 'b' && formatOption != 'm' && formatOption != 'c' && formatOption != 'p') {
433
if (RecGetRecordDataType(varName, &varDataType) == REC_ERR_FAIL) {
438
switch (varDataType) {
440
data.int_data = this->readInteger(varName, &found);
441
if (formatOption == 'b') {
442
bytesFromInt(data.int_data, bufVal);
443
} else if (formatOption == 'm') {
444
MbytesFromInt(data.int_data, bufVal);
445
} else if (formatOption == 'c') {
446
commaStrFromInt(data.int_data, bufVal);
448
sprintf(bufVal, "%" PRId64 "", data.int_data);
452
data.counter_data = this->readCounter(varName, &found);
453
if (formatOption == 'b') {
454
bytesFromInt((MgmtInt) data.counter_data, bufVal);
455
} else if (formatOption == 'm') {
456
MbytesFromInt((MgmtInt) data.counter_data, bufVal);
457
} else if (formatOption == 'c') {
458
commaStrFromInt(data.counter_data, bufVal);
460
sprintf(bufVal, "%" PRId64 "", data.counter_data);
464
data.float_data = this->readFloat(varName, &found);
465
if (formatOption == 'p') {
466
percentStrFromFloat(data.float_data, bufVal);
468
snprintf(bufVal, bufLen, "%.2f", data.float_data);
472
data.string_data = this->readString(varName, &found);
473
if (data.string_data == NULL) {
475
} else if (strlen(data.string_data) < (size_t) (bufLen - 1)) {
476
ink_strncpy(bufVal, data.string_data, bufLen);
478
ink_strncpy(bufVal, data.string_data, bufLen);
480
xfree(data.string_data);
493
overviewRecord::varCounterFromName(const char *name, MgmtIntCounter * value)
498
*value = readCounter((char *) name, &found);
503
overviewRecord::varIntFromName(const char *name, MgmtInt * value)
508
*value = readInteger((char *) name, &found);
513
overviewRecord::varFloatFromName(const char *name, MgmtFloat * value)
518
*value = readFloat((char *) name, &found);
523
overviewPage::overviewPage():sortRecords(10, false)
526
ink_mutex_init(&accessLock, "overviewRecord");
527
nodeRecords = ink_hash_table_create(InkHashTableKeyType_Word);
529
ourAddr = 0; // We will update this when we add the record for
533
overviewPage::~overviewPage()
536
// Since we only have one global object and we never destruct it
537
// do not actually free memeory since it causes problems the
538
// process is vforked, and the child execs something
539
// The below code is DELIBERTLY commented out
541
// ink_mutex_destroy(&accessLock);
542
// ink_hash_table_destroy(nodeRecords);
545
// overviewPage::checkForUpdates - updates node records as to whether peers
548
overviewPage::checkForUpdates()
551
ClusterPeerInfo *tmp;
552
InkHashTableEntry *entry;
553
InkHashTableIteratorState iterator_state;
554
overviewRecord *current;
556
bool newHostAdded = false;
558
// grok through the cluster communication stuff and update information
559
// about hosts in the cluster
561
ink_mutex_acquire(&accessLock);
562
ink_mutex_acquire(&(lmgmt->ccom->mutex));
563
currentTime = time(NULL);
564
for (entry = ink_hash_table_iterator_first(lmgmt->ccom->peers, &iterator_state);
565
entry != NULL; entry = ink_hash_table_iterator_next(lmgmt->ccom->peers, &iterator_state)) {
567
tmp = (ClusterPeerInfo *) ink_hash_table_entry_value(lmgmt->ccom->peers, entry);
569
if (ink_hash_table_lookup(nodeRecords, (InkHashTableKey) tmp->inet_address, (InkHashTableValue *) & current) == 0) {
570
this->addRecord(tmp);
573
current->updateStatus(currentTime, tmp);
576
ink_mutex_release(&lmgmt->ccom->mutex);
578
// Now check to see if our alarms up to date
579
for (int i = 0; i < numHosts; i++) {
580
current = (overviewRecord *) sortRecords[i];
581
current->checkAlarms();
584
// If we added a new host we must resort sortRecords
589
ink_mutex_release(&accessLock);
593
// overrviewPage::sortHosts()
595
// resorts sortRecords, but always leaves the local node
596
// as the first record
598
// accessLock must be held by callee
600
overviewPage::sortHosts()
602
void **array = sortRecords.getArray();
604
qsort(array + 1, numHosts - 1, sizeof(void *), hostSortFunc);
607
// overviewPage::addRecord(ClusterPerrInfo* cpi)
608
// Adds a new node record
609
// Assuems that this->accessLock is already held
612
overviewPage::addRecord(ClusterPeerInfo * cpi)
615
overviewRecord *newRec;
617
AlarmListable *current;
620
ink_assert(cpi != NULL);
622
newRec = new overviewRecord(cpi->inet_address, false, cpi);
623
newRec->updateStatus(time(NULL), cpi);
625
ink_hash_table_insert(nodeRecords, (InkHashTableKey) cpi->inet_address, (InkHashTableEntry *) newRec);
627
// Check to see if we have alarms that need to be added
629
// This an inefficient linear search, however there should
630
// never be a large number of alarms that do not
631
// nodes yet. This should only happen at start up
633
current = notFoundAlarms.head;
634
while (current != NULL) {
636
next = current->link.next;
638
if (newRec->ipMatch(current->ip) == true) {
639
// The alarm belongs to this record, remove it and
640
// add it to the record
641
notFoundAlarms.remove(current);
642
newRec->addAlarm(current);
648
sortRecords.addEntry(newRec);
652
// adds a record to nodeRecords for the local machine.
653
// gets IP addr from lmgmt->ccom so cluster communtication
654
// must be intialized before calling this function
658
overviewPage::addSelfRecord()
661
overviewRecord *newRec;
662
AlarmListable *current;
665
ink_mutex_acquire(&accessLock);
667
// We should not have been called before
668
ink_assert(ourAddr == 0);
670
// Find out what our cluster addr is from
672
this->ourAddr = lmgmt->ccom->getIP();
674
newRec = new overviewRecord(ourAddr, true);
677
ink_hash_table_insert(nodeRecords, (InkHashTableKey) this->ourAddr, (InkHashTableEntry *) newRec);
679
// Check to see if we have alarms that need to be added
680
// They would be listed for IP zero since the alarm
681
// manager knows ip address for the local node as NULL
683
current = notFoundAlarms.head;
684
while (current != NULL) {
686
next = current->link.next;
688
if (current->ip == NULL) {
689
// The alarm belongs to this record, remove it and
690
// add it to the record
691
notFoundAlarms.remove(current);
692
newRec->addAlarm(current);
698
sortRecords.addEntry(newRec);
700
ink_mutex_release(&accessLock);
703
// adds alarm to the node specified by the ip address
704
// if ip is NULL, the node is local machine
706
overviewPage::addAlarm(alarm_t type, char *ip, char *desc)
709
unsigned long inetAddr;
710
InkHashTableValue lookup;
711
overviewRecord *node;
712
AlarmListable *alarm;
714
ink_mutex_acquire(&accessLock);
719
inetAddr = inet_addr(ip);
722
if (ink_hash_table_lookup(nodeRecords, (InkHashTableKey) inetAddr, &lookup)) {
723
// We found our entry
724
node = (overviewRecord *) lookup;
725
node->addAlarm(type, ip, desc);
728
Debug("dashboard", "[overviewRecord::addAlarm] Alarm for node that we have not seen %s\n", ip);
730
// If we have not seen the node, queue the alarm. The node
731
// should appear eventually
732
alarm = new AlarmListable;
736
notFoundAlarms.push(alarm);
739
ink_mutex_release(&accessLock);
742
// void overviewPage::generateAlarmsTable(textBuffer* output)
744
// places an HTML table containing
746
// resolve hostname alarm_description into output
749
overviewPage::generateAlarmsTable(WebHttpContext * whc)
752
overviewRecord *current;
753
AlarmListable *curAlarm;
756
// char *alarm_query;
759
textBuffer *output = whc->response_bdy;
761
ink_mutex_acquire(&accessLock);
763
// Iterate through each host
765
for (int i = 0; i < numHosts; i++) {
766
current = (overviewRecord *) sortRecords[i];
768
// Iterate through the list of alarms
769
curAlarm = current->nodeAlarms.head;
771
while (curAlarm != NULL) {
772
HtmlRndrTrOpen(output, HTML_CSS_NONE, HTML_ALIGN_LEFT);
774
// Hostname is an entry
775
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_TOP, NULL, NULL, 0);
776
output->copyFrom(current->hostname, strlen(current->hostname));
777
HtmlRndrTdClose(output);
779
// Alarm description is an entry
780
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_TOP, NULL, NULL, 0);
781
if (curAlarm->desc != NULL) {
782
output->copyFrom(curAlarm->desc, strlen(curAlarm->desc));
784
const char *alarmText = lmgmt->alarm_keeper->getAlarmText(curAlarm->type);
785
output->copyFrom(alarmText, strlen(alarmText));
787
HtmlRndrTdClose(output);
789
// the name of each checkbox is : "alarm:<alarm_count>"
790
// the value of each checkbox is: "<alarmId>:<ip addr>"
791
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_CENTER, HTML_VALIGN_NONE, NULL, NULL, 0);
792
if (curAlarm->ip == NULL)
793
snprintf(numBuf, sizeof(numBuf), "%d:local", curAlarm->type);
795
snprintf(numBuf, sizeof(numBuf), "%d:%s", curAlarm->type, curAlarm->ip);
796
snprintf(name, sizeof(name), "alarm:%d", alarm_count);
797
HtmlRndrInput(output, HTML_CSS_NONE, HTML_TYPE_CHECKBOX, name, numBuf, NULL, NULL);
798
HtmlRndrTdClose(output);
800
HtmlRndrTrClose(output);
801
curAlarm = curAlarm->link.next;
808
ink_mutex_release(&accessLock);
810
// check if we didn't find any alarms
811
if (alarm_count == 0) {
812
HtmlRndrTrOpen(output, HTML_CSS_NONE, HTML_ALIGN_NONE);
813
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 3);
814
HtmlRndrSpace(output, 2);
815
HtmlRndrText(output, whc->lang_dict_ht, HTML_ID_NO_ACTIVE_ALARMS);
816
HtmlRndrTdClose(output);
817
HtmlRndrTrClose(output);
823
overviewPage::generateAlarmsTableCLI(textBuffer * output)
825
overviewRecord *current;
826
AlarmListable *curAlarm;
828
char alarmtypeBuf[32] = "";
829
// char tmpBuf[256] = "";
830
CLIlineBuffer *Obuf = NULL;
831
char *out_buf = NULL;
832
const char *field1 = " Alarm Id";
833
const char *field2 = "Host";
834
const char *field3 = "Alarm";
836
ink_mutex_acquire(&accessLock);
838
// Create Alarm header
839
Obuf = new CLIlineBuffer(10);
840
Obuf->addField("%-*s", field1, 21);
841
Obuf->addField("%-*s", field2, 21);
842
Obuf->addField("%-*s", field3, 30);
843
out_buf = Obuf->getline();
845
output->copyFrom(out_buf, strlen(out_buf));
850
output->copyFrom(CLI_globals::sep1, strlen(CLI_globals::sep1));
852
// Iterate through each host
853
for (int i = 0; i < numHosts; i++) {
854
current = (overviewRecord *) sortRecords[i];
856
// Iterate through the list of alarms
857
curAlarm = current->nodeAlarms.head;
858
while (curAlarm != NULL) {
860
// The resolve input is <alarmId>:<ip addr>
862
if (curAlarm->ip == NULL)
863
snprintf(ipBuf, sizeof(ipBuf), "%s", "local");
865
snprintf(ipBuf, sizeof(ipBuf), "%s", curAlarm->ip);
867
snprintf(alarmtypeBuf, sizeof(alarmtypeBuf), "%d", curAlarm->type);
868
// alarm id field is 21
869
Obuf->addField("%*s", alarmtypeBuf, 3);
870
Obuf->addField("%-*s", ":", 1);
871
Obuf->addField("%-*s", ipBuf, 16);
872
Obuf->addField("%*s", " ", 1);
874
// Hostname is an entry
875
Obuf->addField("%-*s", current->hostname, 20);
876
Obuf->addField("%*s", " ", 1);
878
// Alarm description is an entry
879
if (curAlarm->desc != NULL) { // Desc field is 30
880
Obuf->addField("%-*s", curAlarm->desc, 30);
882
const char *alarmText = lmgmt->alarm_keeper->getAlarmText(curAlarm->type);
883
Obuf->addField("%-*s", alarmText, 20);
886
out_buf = Obuf->getline(); // get formatted output
887
if (out_buf) { // copy to output buffer
888
output->copyFrom(out_buf, strlen(out_buf));
889
delete[]out_buf; // need to free this every time
892
Obuf->reset(); // reset every time i.e. reuse
894
curAlarm = curAlarm->link.next;
901
ink_mutex_release(&accessLock);
902
} // end generateAlarmsTableCLI()
905
// void overviewPage::generateAlarmsSummary(textBuffer* output)
907
// alarm summary information (Alarm! [X pending])
910
overviewPage::generateAlarmsSummary(WebHttpContext * whc)
913
overviewRecord *current;
914
AlarmListable *curAlarm;
919
textBuffer *output = whc->response_bdy;
921
ink_mutex_acquire(&accessLock);
923
// Iterate through each host
925
for (int i = 0; i < numHosts; i++) {
926
current = (overviewRecord *) sortRecords[i];
927
// Iterate through the list of alarms
928
curAlarm = current->nodeAlarms.head;
929
while (curAlarm != NULL) {
931
curAlarm = curAlarm->link.next;
935
ink_mutex_release(&accessLock);
937
if (alarm_count > 0) {
938
HtmlRndrTableOpen(output, "100%", 0, 0, 0);
940
HtmlRndrTrOpen(output, HTML_CSS_ALARM_COLOR, HTML_ALIGN_NONE);
941
HtmlRndrTdOpen(output, HTML_CSS_GREY_LINKS, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, "30", 0);
942
alarm_link = WebHttpGetLink_Xmalloc(HTML_ALARM_FILE);
943
HtmlRndrAOpen(output, HTML_CSS_NONE, alarm_link, NULL);
945
HtmlRndrSpace(output, 2);
946
HtmlRndrText(output, whc->lang_dict_ht, HTML_ID_ALARM);
947
snprintf(buf, sizeof(buf), "! [%d ", alarm_count);
948
output->copyFrom(buf, strlen(buf));
949
HtmlRndrText(output, whc->lang_dict_ht, HTML_ID_PENDING);
950
snprintf(buf, sizeof(buf), "]");
951
output->copyFrom(buf, strlen(buf));
952
HtmlRndrAClose(output);
953
HtmlRndrTdClose(output);
954
HtmlRndrTrClose(output);
956
HtmlRndrTrOpen(output, HTML_CSS_NONE, HTML_ALIGN_NONE);
957
HtmlRndrTdOpen(output, HTML_CSS_TERTIARY_COLOR, HTML_ALIGN_NONE, HTML_VALIGN_NONE, "1", "1", 0);
958
HtmlRndrDotClear(output, 1, 1);
959
HtmlRndrTdClose(output);
961
HtmlRndrTrClose(output);
963
HtmlRndrTableClose(output);
968
// generates the table for the overview page
970
// the entries are hostname, on/off, alarm
973
overviewPage::generateTable(WebHttpContext * whc)
976
// Varariables for finding out information about a specific node
977
overviewRecord *current;
982
PowerLampState proxyUp;
983
bool sslEnabled = false;
984
const char refFormat[] = "%s://%s:%d%s";
985
char refBuf[256]; // Buffer for link to other nodes
986
char *domainStart; // pointer to domain name part of hostna,e
987
int hostLen; // length of the host only portion of the hostname
989
MgmtInt objs, t_hit, t_miss;
990
MgmtFloat ops, hits, mbps;
993
textBuffer *output = whc->response_bdy;
994
MgmtHashTable *dict_ht = whc->lang_dict_ht;
996
// Check to see if SSL is enabled. Do one check, and record
997
// the info since it can change from under us in the pContext
998
// structure and we at least want to be able to give a
1000
if (whc->server_state & WEB_HTTP_SERVER_STATE_SSL_ENABLED) {
1004
ink_mutex_acquire(&accessLock);
1005
for (int i = 0; i < numHosts; i++) {
1006
current = (overviewRecord *) sortRecords[i];
1007
current->getStatus(&hostName, &up, &alarm, &proxyUp);
1009
// no longer need 'if (alarm)' since we have the alarm bar now
1011
//HtmlRndrTrOpen(output, HTML_CSS_ALARM_COLOR, HTML_ALIGN_CENTER);
1013
HtmlRndrTrOpen(output, HTML_CSS_NONE, HTML_ALIGN_CENTER);
1015
// Make the hostname non-qualified if we have a host name and not
1017
if (isdigit(*hostName))
1020
domainStart = strchr(hostName, '.');
1022
if (domainStart == NULL)
1023
hostLen = strlen(hostName);
1025
hostLen = domainStart - hostName;
1027
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1028
// INKqa01119 - remove the up check since we are currently
1029
// not sending heartbeat packets when the proxy is off
1030
// if (up == true && current->localNode == false) {
1031
if (current->localNode == false) {
1032
char *link = WebHttpGetLink_Xmalloc(HTML_DEFAULT_MONITOR_FILE);
1033
if (sslEnabled == false) {
1034
// coverity[non_const_printf_format_string]
1035
snprintf(refBuf, sizeof(refBuf), refFormat, "http", hostName, wGlobals.webPort, link);
1037
// coverity[non_const_printf_format_string]
1038
snprintf(refBuf, sizeof(refBuf), refFormat, "https", hostName, wGlobals.webPort, link);
1040
HtmlRndrAOpen(output, HTML_CSS_GRAPH, refBuf, NULL);
1041
output->copyFrom(hostName, hostLen);
1042
HtmlRndrAClose(output);
1045
output->copyFrom(hostName, hostLen);
1047
HtmlRndrTdClose(output);
1050
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1053
HtmlRndrText(output, dict_ht, HTML_ID_ON);
1056
HtmlRndrText(output, dict_ht, HTML_ID_OFF);
1059
HtmlRndrText(output, dict_ht, HTML_ID_WARNING);
1062
HtmlRndrTdClose(output);
1065
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1066
current->varIntFromName("proxy.node.user_agents_total_documents_served", &objs);
1067
snprintf(outBuf, sizeof(outBuf), "%.10lld", objs);
1068
output->copyFrom(outBuf, strlen(outBuf));
1069
HtmlRndrTdClose(output);
1073
ops = current->readFloat("proxy.node.user_agent_xacts_per_second", &found);
1075
// Always report zero for down nodes
1079
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1080
snprintf(outBuf, 16, "%.2f", ops);
1081
output->copyFrom(outBuf, strlen(outBuf));
1082
HtmlRndrTdClose(output);
1085
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1086
current->varFloatFromName("proxy.node.cache_hit_ratio_avg_10s", &hits);
1087
snprintf(outBuf, sizeof(outBuf), "%.2f%% ", hits * 100.0);
1088
output->copyFrom(outBuf, strlen(outBuf));
1089
HtmlRndrTdClose(output);
1092
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1093
current->varFloatFromName("proxy.node.client_throughput_out", &mbps);
1094
snprintf(outBuf, sizeof(outBuf), "%.2f", mbps);
1095
output->copyFrom(outBuf, strlen(outBuf));
1096
HtmlRndrTdClose(output);
1099
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1100
current->varIntFromName("proxy.node.http.transaction_msec_avg_10s.hit_fresh", &t_hit);
1101
snprintf(outBuf, sizeof(outBuf), "%" PRId64 "", t_hit);
1102
output->copyFrom(outBuf, strlen(outBuf));
1103
HtmlRndrTdClose(output);
1106
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1107
current->varIntFromName("proxy.node.http.transaction_msec_avg_10s.miss_cold", &t_miss);
1108
snprintf(outBuf, sizeof(outBuf), "%" PRId64 "", t_miss);
1109
output->copyFrom(outBuf, strlen(outBuf));
1110
HtmlRndrTdClose(output);
1113
HtmlRndrTrClose(output);
1115
// show the 'details' section on the dashboard
1116
if (whc->request_state & WEB_HTTP_STATE_MORE_DETAIL) {
1117
this->addHostPanel(whc, current);
1122
ink_mutex_release(&accessLock);
1126
// generates the table for the dashboard page for CLI
1129
overviewPage::generateTableCLI(textBuffer * output)
1131
// Varariables for finding out information about a specific node
1132
overviewRecord *current;
1137
PowerLampState proxyUp;
1140
const char sformat[] = "%-3d %-15s %-8s %-6s %12s %12s";
1141
const char nameFormat[] = "%s";
1142
const char nodeFormat[] = "%s";
1143
const char alarmFormat[] = "%s";
1147
char docCountBuf[32];
1148
char loadMetricBuf[32];
1150
char *domainStart; // pointer to domain name part of hostname
1151
int hostLen; // length of the host only portion of the hostname
1153
// This determine is 'details' is displayed
1154
//moreInfo = this->moreInfoButton(submission, output);
1156
// acquire overviewPage
1157
ink_mutex_acquire(&accessLock);
1159
// for each host we know about
1160
for (int i = 0; i < numHosts; i++) { // get host status
1161
current = (overviewRecord *) sortRecords[i];
1162
current->getStatus(&hostName, &up, &alarm, &proxyUp);
1164
// Make the hostname non-qualified if we have
1165
// a host name and not an ip address
1166
if (isdigit(*hostName))
1169
domainStart = strchr(hostName, '.');
1171
if (domainStart == NULL)
1172
hostLen = strlen(hostName);
1174
hostLen = domainStart - hostName;
1176
snprintf(namebuf, hostLen + 1, nameFormat, hostName);
1177
namebuf[hostLen] = '\0';
1179
// Add On/Off/Down status
1182
// coverity[non_const_printf_format_string]
1183
snprintf(nodebuf, sizeof(nodebuf), nodeFormat, "ON");
1186
// coverity[non_const_printf_format_string]
1187
snprintf(nodebuf, sizeof(nodebuf), nodeFormat, "OFF");
1189
case LAMP_WARNING: // means node is down and not clustering
1190
// coverity[non_const_printf_format_string]
1191
snprintf(nodebuf, sizeof(nodebuf), nodeFormat, "DOWN");
1197
if (alarm == true) {
1198
// coverity[non_const_printf_format_string]
1199
snprintf(alarmbuf, sizeof(alarmbuf), alarmFormat, "ALARM");
1201
// coverity[non_const_printf_format_string]
1202
snprintf(alarmbuf, sizeof(alarmbuf), alarmFormat, "-");
1205
// Add document count
1206
docCount = current->readInteger("proxy.node.user_agents_total_documents_served", &found);
1208
if (false == found) {
1211
// Transactions per/sec
1213
loadMetric = (MgmtInt)
1214
current->readFloat("proxy.node.user_agent_xacts_per_second", &found);
1216
// Always report zero for down nodes
1221
snprintf(docCountBuf, sizeof(docCountBuf), "%" PRId64 "", docCount);
1222
snprintf(loadMetricBuf, sizeof(loadMetricBuf), "%" PRId64 "", loadMetric);
1224
// create output status line
1225
// coverity[non_const_printf_format_string]
1226
snprintf(tmpbuf, sizeof(tmpbuf), sformat, i, namebuf, nodebuf, alarmbuf, docCountBuf, loadMetricBuf);
1227
output->copyFrom(tmpbuf, strlen(tmpbuf));
1229
output->copyFrom("\n", strlen("\n"));
1232
// Add the Virtual IP Panel in the more detailed display
1234
ink_mutex_release(&accessLock);
1235
} // end generateTableCLI()
1237
// overviewPage::addHostPanel
1239
// Inserts stats entries for the host referenced by parameter host
1240
// Called by overviewPage::generateTable
1243
overviewPage::addHostPanel(WebHttpContext * whc, overviewRecord * host)
1246
const char errorStr[] = "loading...";
1251
textBuffer *output = whc->response_bdy;
1252
MgmtHashTable *dict_ht = whc->lang_dict_ht;
1254
//-----------------------------------------------------------------------
1255
// SET 1: CACHE TRANSACTION SUMMARY
1256
//-----------------------------------------------------------------------
1258
HtmlRndrTrOpen(output, HTML_CSS_NONE, HTML_ALIGN_LEFT);
1259
HtmlRndrTdOpen(output, HTML_CSS_NONE, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 8);
1261
MgmtFloat hits, hit_f, hit_r;
1262
MgmtFloat errs, abts, f;
1266
if (host->varFloatFromName("proxy.node.http.transaction_frac_avg_10s.errors.pre_accept_hangups", &f))
1268
if (host->varFloatFromName("proxy.node.http.transaction_frac_avg_10s.errors.empty_hangups", &f))
1270
if (host->varFloatFromName("proxy.node.http.transaction_frac_avg_10s.errors.early_hangups", &f))
1272
if (host->varFloatFromName("proxy.node.http.transaction_frac_avg_10s.errors.aborts", &f))
1277
if (host->varFloatFromName("proxy.node.http.transaction_frac_avg_10s.errors.connect_failed", &f))
1279
if (host->varFloatFromName("proxy.node.http.transaction_frac_avg_10s.errors.other", &f))
1283
hits = hit_f = hit_r = 0;
1284
if (host->varFloatFromName("proxy.node.http.transaction_frac_avg_10s.hit_fresh", &hit_f))
1286
if (host->varFloatFromName("proxy.node.http.transaction_frac_avg_10s.hit_revalidated", &hit_r))
1289
host->varFloatFromName("proxy.node.cache_hit_ratio_avg_10s", &hits);
1290
#endif /* !OLD_WAY */
1292
#define SEPARATOR output->copyFrom(" - ", 13)
1294
HtmlRndrTableOpen(output, NULL, 0, 0, 0);
1296
HtmlRndrTrOpen(output, HTML_CSS_NONE, HTML_ALIGN_LEFT);
1297
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1298
HtmlRndrText(output, dict_ht, HTML_ID_CACHE_HIT_RATE);
1299
HtmlRndrTdClose(output);
1300
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1302
snprintf(tmp, sizeof(tmp), "%.1f%% (%.1f%% ", hits * 100.0, hit_f * 100.0);
1303
output->copyFrom(tmp, strlen(tmp));
1304
HtmlRndrText(output, dict_ht, HTML_ID_FRESH);
1305
snprintf(tmp, sizeof(tmp), ", %.1f%% ", hit_r * 100.0);
1306
output->copyFrom(tmp, strlen(tmp));
1307
HtmlRndrText(output, dict_ht, HTML_ID_REFRESH);
1308
output->copyFrom(")", 1);
1309
HtmlRndrTdClose(output);
1310
HtmlRndrTrClose(output);
1312
HtmlRndrTrOpen(output, HTML_CSS_NONE, HTML_ALIGN_LEFT);
1313
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1314
HtmlRndrText(output, dict_ht, HTML_ID_ERRORS);
1315
HtmlRndrTdClose(output);
1316
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1318
snprintf(tmp, sizeof(tmp), "%.1f%%", errs * 100.0);
1319
output->copyFrom(tmp, strlen(tmp));
1320
HtmlRndrTdClose(output);
1321
HtmlRndrTrClose(output);
1323
HtmlRndrTrOpen(output, HTML_CSS_NONE, HTML_ALIGN_LEFT);
1324
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1325
HtmlRndrText(output, dict_ht, HTML_ID_ABORTS);
1326
HtmlRndrTdClose(output);
1327
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1329
snprintf(tmp, sizeof(tmp), "%.1f%%", abts * 100.0);
1330
output->copyFrom(tmp, strlen(tmp));
1331
HtmlRndrTdClose(output);
1332
HtmlRndrTrClose(output);
1334
//-----------------------------------------------------------------------
1335
// SET 2: ACTIVE CONNECTIONS
1336
//-----------------------------------------------------------------------
1338
MgmtInt clients, servers;
1340
clients = servers = 0;
1342
host->varIntFromName("proxy.node.current_client_connections", &clients);
1343
host->varIntFromName("proxy.node.current_server_connections", &servers);
1345
HtmlRndrTrOpen(output, HTML_CSS_NONE, HTML_ALIGN_LEFT);
1346
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1347
HtmlRndrText(output, dict_ht, HTML_ID_ACTIVE_CLIENTS);
1348
HtmlRndrTdClose(output);
1349
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1351
snprintf(tmp, sizeof(tmp), "%" PRId64 "", clients);
1352
output->copyFrom(tmp, strlen(tmp));
1353
HtmlRndrTdClose(output);
1354
HtmlRndrTrClose(output);
1356
HtmlRndrTrOpen(output, HTML_CSS_NONE, HTML_ALIGN_LEFT);
1357
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1358
HtmlRndrText(output, dict_ht, HTML_ID_ACTIVE_SERVERS);
1359
HtmlRndrTdClose(output);
1360
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1362
snprintf(tmp, sizeof(tmp), "%" PRId64 "", servers);
1363
output->copyFrom(tmp, strlen(tmp));
1364
HtmlRndrTdClose(output);
1365
HtmlRndrTrClose(output);
1367
//-----------------------------------------------------------------------
1368
// SET 3: CLUSTER ADDRESS
1369
//-----------------------------------------------------------------------
1371
HtmlRndrTrOpen(output, HTML_CSS_NONE, HTML_ALIGN_LEFT);
1372
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1373
HtmlRndrText(output, dict_ht, HTML_ID_NODE_IP_ADDRESS);
1374
HtmlRndrTdClose(output);
1375
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1377
ip.s_addr = host->inetAddr;
1378
ip_str = inet_ntoa(ip);
1379
output->copyFrom(ip_str, strlen(ip_str));
1380
HtmlRndrTdClose(output);
1381
HtmlRndrTrClose(output);
1383
//-----------------------------------------------------------------------
1385
//-----------------------------------------------------------------------
1387
if (host->varStrFromName("proxy.node.cache.bytes_free\\b", tmp, 256) == false) {
1388
ink_strncpy(tmp, errorStr, sizeof(tmp));
1390
HtmlRndrTrOpen(output, HTML_CSS_NONE, HTML_ALIGN_LEFT);
1391
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1392
HtmlRndrText(output, dict_ht, HTML_ID_CACHE_FREE_SPACE);
1393
HtmlRndrTdClose(output);
1394
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1396
output->copyFrom(tmp, strlen(tmp));
1397
HtmlRndrTdClose(output);
1398
HtmlRndrTrClose(output);
1400
if (host->varStrFromName("proxy.node.hostdb.hit_ratio_avg_10s\\p", tmp, 256) == false) {
1401
ink_strncpy(tmp, errorStr, sizeof(tmp));
1403
HtmlRndrTrOpen(output, HTML_CSS_NONE, HTML_ALIGN_LEFT);
1404
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1405
HtmlRndrText(output, dict_ht, HTML_ID_HOSTDB_HIT_RATE);
1406
HtmlRndrTdClose(output);
1407
HtmlRndrTdOpen(output, HTML_CSS_BODY_TEXT, HTML_ALIGN_NONE, HTML_VALIGN_NONE, NULL, NULL, 0);
1409
output->copyFrom(tmp, strlen(tmp));
1410
HtmlRndrTdClose(output);
1411
HtmlRndrTrClose(output);
1413
HtmlRndrTableClose(output);
1415
HtmlRndrTdClose(output);
1416
HtmlRndrTrClose(output);
1422
// int overviewPage::getClusterHosts(Expanding Array* hosts)
1424
// The names of all the cluster members are inserted
1425
// into parameter hosts. The callee is responsible
1426
// for freeing the strings
1429
overviewPage::getClusterHosts(ExpandingArray * hosts)
1433
overviewRecord *current;
1435
ink_mutex_acquire(&accessLock);
1436
number = sortRecords.getNumEntries();
1438
for (int i = 0; i < number; i++) {
1439
current = (overviewRecord *) sortRecords[i];
1440
hosts->addEntry(xstrdup(current->hostname));
1443
ink_mutex_release(&accessLock);
1447
// overviewRecord* overviewPage::findNodeByName(const char* nodeName)
1449
// Returns a pointer to node name nodeName
1450
// If node name is not found, returns NULL
1452
// CALLEE MUST BE HOLDING this->accessLock
1455
overviewPage::findNodeByName(const char *nodeName)
1457
overviewRecord *current = NULL;
1458
bool nodeFound = false;
1460
// Do a linear search of the nodes for this nodeName.
1461
// Yes, I know this is slow but the current word is ten
1462
// nodes would be a huge cluster so this should not
1465
for (int i = 0; i < numHosts; i++) {
1466
current = (overviewRecord *) sortRecords[i];
1467
if (strcmp(nodeName, current->hostname) == 0) {
1473
if (nodeFound == true) {
1480
// MgmtString overviewPage::readString(const char* nodeName, char* *name, bool *found = NULL)
1482
// Looks up a node record for a specific by nodeName
1483
// CALLEE deallocates the string with free()
1486
overviewPage::readString(const char *nodeName, const char *name, bool * found)
1488
MgmtString r = NULL;
1489
// bool nodeFound = false;
1490
bool valueFound = false;
1491
overviewRecord *node;
1493
ink_mutex_acquire(&accessLock);
1495
node = this->findNodeByName(nodeName);
1498
r = node->readString(name, &valueFound);
1500
ink_mutex_release(&accessLock);
1502
if (found != NULL) {
1503
*found = valueFound;
1509
// MgmtInt overviewPage::readInteger(const char* nodeName, char* *name, bool *found = NULL)
1511
// Looks up a node record for a specific by nodeName
1514
overviewPage::readInteger(const char *nodeName, const char *name, bool * found)
1517
// bool nodeFound = false;
1518
bool valueFound = false;
1519
overviewRecord *node;
1521
ink_mutex_acquire(&accessLock);
1523
node = this->findNodeByName(nodeName);
1526
r = node->readInteger(name, &valueFound);
1528
ink_mutex_release(&accessLock);
1530
if (found != NULL) {
1531
*found = valueFound;
1537
// MgmtFloat overviewPage::readFloat(const char* nodeName, char* *name, bool *found = NULL)
1539
// Looks up a node record for a specific by nodeName
1542
overviewPage::readFloat(const char *nodeName, const char *name, bool * found)
1545
// bool nodeFound = false;
1546
bool valueFound = false;
1547
overviewRecord *node;
1549
ink_mutex_acquire(&accessLock);
1551
node = this->findNodeByName(nodeName);
1554
r = node->readFloat(name, &valueFound);
1556
ink_mutex_release(&accessLock);
1558
if (found != NULL) {
1559
*found = valueFound;
1565
// void overviewPage::agCachePercentFree()
1567
// Updates proxy.cluster.cache.percent_free
1570
overviewPage::agCachePercentFree()
1576
clusterSumInt("proxy.node.cache.bytes_total", &bTotal);
1577
clusterSumInt("proxy.node.cache.bytes_free", &bFree);
1582
pFree = (MgmtFloat) ((double) bFree / (double) bTotal);
1585
ink_assert(varSetFloat("proxy.cluster.cache.percent_free", pFree));
1588
// void overviewPage::agCacheHitRate()
1590
// Updates OLD proxy.cluster.http.cache_hit_ratio
1591
// proxy.cluster.http.cache_total_hits
1593
// NEW proxy.cluster.cache_hit_ratio
1594
// proxy.cluster.cache_total_hits
1597
overviewPage::agCacheHitRate()
1599
static ink_hrtime last_set_time = 0;
1600
const ink_hrtime window = 10 * HRTIME_SECOND; // update every 10 seconds
1601
static StatTwoIntSamples cluster_hit_count = { "proxy.node.cache_total_hits", 0, 0, 0, 0 };
1602
static StatTwoIntSamples cluster_miss_count = { "proxy.node.cache_total_misses", 0, 0, 0, 0 };
1603
static const char *cluster_hit_count_name = "proxy.cluster.cache_total_hits_avg_10s";
1604
static const char *cluster_miss_count_name = "proxy.cluster.cache_total_misses_avg_10s";
1606
MgmtIntCounter totalHits = 0;
1607
MgmtIntCounter totalMisses = 0;
1608
MgmtIntCounter totalAccess = 0;
1609
MgmtFloat hitRate = 0.00;
1611
// get current time and delta to work with
1612
ink_hrtime current_time = ink_get_hrtime();
1613
// ink_hrtime delta = current_time - last_set_time;
1615
///////////////////////////////////////////////////////////////
1616
// if enough time expired, or first time, or wrapped around: //
1617
// (1) scroll current value into previous value //
1618
// (2) calculate new current values //
1619
// (3) only if proper time expired, set derived values //
1620
///////////////////////////////////////////////////////////////
1621
if (((current_time - last_set_time) > window) || // sufficient elapsed time
1622
(last_set_time == 0) || // first time
1623
(last_set_time > current_time)) // wrapped around
1625
////////////////////////////////////////
1626
// scroll values for cluster Hit/Miss //
1627
///////////////////////////////////////
1628
cluster_hit_count.previous_time = cluster_hit_count.current_time;
1629
cluster_hit_count.previous_value = cluster_hit_count.current_value;
1631
cluster_miss_count.previous_time = cluster_miss_count.current_time;
1632
cluster_miss_count.previous_value = cluster_miss_count.current_value;
1634
//////////////////////////
1635
// calculate new values //
1636
//////////////////////////
1637
cluster_hit_count.current_value = -10000;
1638
cluster_hit_count.current_time = ink_get_hrtime();
1639
// TODO: Should we check return value?
1640
clusterSumInt(cluster_hit_count.lm_record_name, &(cluster_hit_count.current_value));
1642
cluster_miss_count.current_value = -10000;
1643
cluster_miss_count.current_time = ink_get_hrtime();
1644
// TODO: Should we check return value?
1645
clusterSumInt(cluster_miss_count.lm_record_name, &(cluster_miss_count.current_value));
1647
////////////////////////////////////////////////
1648
// if not initial or wrap, set derived values //
1649
////////////////////////////////////////////////
1650
if ((current_time - last_set_time) > window) {
1651
RecInt num_hits = 0;
1652
RecInt num_misses = 0;
1655
// generate time window deltas and sum
1656
diff = cluster_hit_count.diff_value();
1657
varSetInt(cluster_hit_count_name, diff);
1660
diff = cluster_miss_count.diff_value();
1661
varSetInt(cluster_miss_count_name, diff);
1664
total = num_hits + num_misses;
1668
hitRate = (MgmtFloat) ((double) num_hits / (double) total);
1670
// Check if more than one cluster node
1672
varIntFromName("proxy.process.cluster.nodes", &num_nodes);
1673
if (1 == num_nodes) {
1674
// Only one node , so grab local value
1675
varFloatFromName("proxy.node.cache_hit_ratio_avg_10s", &hitRate);
1678
varSetFloat("proxy.cluster.cache_hit_ratio_avg_10s", hitRate);
1680
/////////////////////////////////////////////////
1681
// done with a cycle, update the last_set_time //
1682
/////////////////////////////////////////////////
1683
last_set_time = current_time;
1685
// Deal with Lifetime stats
1686
clusterSumInt("proxy.node.cache_total_hits", &totalHits);
1687
clusterSumInt("proxy.node.cache_total_misses", &totalMisses);
1688
totalAccess = totalHits + totalMisses;
1690
if (totalAccess != 0) {
1691
hitRate = (MgmtFloat) ((double) totalHits / (double) totalAccess);
1694
ink_assert(varSetFloat("proxy.cluster.http.cache_hit_ratio", hitRate));
1695
ink_assert(varSetInt("proxy.cluster.http.cache_total_hits", totalHits));
1696
ink_assert(varSetInt("proxy.cluster.http.cache_total_misses", totalMisses));
1699
ink_assert(varSetFloat("proxy.cluster.cache_hit_ratio", hitRate));
1700
ink_assert(varSetInt("proxy.cluster.cache_total_hits", totalHits));
1701
ink_assert(varSetInt("proxy.cluster.cache_total_misses", totalMisses));
1704
// void overviewPage::agHostDBHitRate()
1706
// Updates proxy.cluster.hostdb.hit_ratio
1709
overviewPage::agHostdbHitRate()
1711
static ink_hrtime last_set_time = 0;
1712
const ink_hrtime window = 10 * HRTIME_SECOND; // update every 10 seconds
1713
static StatTwoIntSamples cluster_hostdb_total_lookups = { "proxy.node.hostdb.total_lookups", 0, 0, 0, 0 };
1714
static StatTwoIntSamples cluster_hostdb_hits = { "proxy.node.hostdb.total_hits", 0, 0, 0, 0 };
1715
static const char *cluster_hostdb_total_lookups_name = "proxy.cluster.hostdb.total_lookups_avg_10s";
1716
static const char *cluster_hostdb_hits_name = "proxy.cluster.hostdb.total_hits_avg_10s";
1718
RecInt hostDBtotal = 0;
1719
RecInt hostDBhits = 0;
1720
// RecInt hostDBmisses = 0;
1721
RecInt dnsTotal = 0;
1722
RecFloat hitRate = 0.00;
1724
// get current time and delta to work with
1725
ink_hrtime current_time = ink_get_hrtime();
1726
// ink_hrtime delta = current_time - last_set_time;
1728
///////////////////////////////////////////////////////////////
1729
// if enough time expired, or first time, or wrapped around: //
1730
// (1) scroll current value into previous value //
1731
// (2) calculate new current values //
1732
// (3) only if proper time expired, set derived values //
1733
///////////////////////////////////////////////////////////////
1734
if (((current_time - last_set_time) > window) || // sufficient elapsed time
1735
(last_set_time == 0) || // first time
1736
(last_set_time > current_time)) // wrapped around
1738
////////////////////////////////////////
1739
// scroll values for cluster DNS //
1740
///////////////////////////////////////
1741
cluster_hostdb_total_lookups.previous_time = cluster_hostdb_total_lookups.current_time;
1742
cluster_hostdb_total_lookups.previous_value = cluster_hostdb_total_lookups.current_value;
1744
cluster_hostdb_hits.previous_time = cluster_hostdb_hits.current_time;
1745
cluster_hostdb_hits.previous_value = cluster_hostdb_hits.current_value;
1747
//////////////////////////
1748
// calculate new values //
1749
//////////////////////////
1750
cluster_hostdb_total_lookups.current_value = -10000;
1751
cluster_hostdb_total_lookups.current_time = ink_get_hrtime();
1752
// TODO: Should we check return value?
1753
clusterSumInt(cluster_hostdb_total_lookups.lm_record_name, &(cluster_hostdb_total_lookups.current_value));
1755
cluster_hostdb_hits.current_value = -10000;
1756
cluster_hostdb_hits.current_time = ink_get_hrtime();
1757
// TODO: Should we check return value?
1758
clusterSumInt(cluster_hostdb_hits.lm_record_name, &(cluster_hostdb_hits.current_value));
1760
////////////////////////////////////////////////
1761
// if not initial or wrap, set derived values //
1762
////////////////////////////////////////////////
1763
if ((current_time - last_set_time) > window) {
1764
MgmtInt num_total_lookups = 0;
1765
MgmtInt num_hits = 0;
1768
// generate time window deltas and sum
1769
diff = cluster_hostdb_total_lookups.diff_value();
1770
varSetInt(cluster_hostdb_total_lookups_name, diff);
1771
num_total_lookups = diff;
1773
diff = cluster_hostdb_hits.diff_value();
1774
varSetInt(cluster_hostdb_hits_name, diff);
1777
if (num_total_lookups == 0)
1780
hitRate = (MgmtFloat) ((double) num_hits / (double) num_total_lookups);
1782
// Check if more than one cluster node
1784
varIntFromName("proxy.process.cluster.nodes", &num_nodes);
1785
if (1 == num_nodes) {
1786
// Only one node , so grab local value
1787
varFloatFromName("proxy.node.hostdb.hit_ratio_avg_10s", &hitRate);
1790
varSetFloat("proxy.cluster.hostdb.hit_ratio_avg_10s", hitRate);
1792
/////////////////////////////////////////////////
1793
// done with a cycle, update the last_set_time //
1794
/////////////////////////////////////////////////
1795
last_set_time = current_time;
1798
// Deal with Lifetime stats
1799
clusterSumInt("proxy.node.hostdb.total_lookups", &hostDBtotal);
1800
clusterSumInt("proxy.node.dns.total_dns_lookups", &dnsTotal);
1801
clusterSumInt("proxy.node.hostdb.total_hits", &hostDBhits);
1803
if (hostDBtotal != 0) {
1804
if (hostDBhits < 0) {
1806
mgmt_log(stderr, "truncating hit_ratio from %d to 0\n", hostDBhits);
1808
hitRate = (MgmtFloat) ((double) hostDBhits / (double) hostDBtotal);
1813
ink_assert(hitRate >= 0.0);
1814
ink_assert(varSetFloat("proxy.cluster.hostdb.hit_ratio", hitRate));
1817
// void overviewPage::agBandwidthHitRate()
1819
// Updates proxy.cluster.http.bandwidth_hit_ratio
1822
overviewPage::agBandwidthHitRate()
1824
static ink_hrtime last_set_time = 0;
1825
const ink_hrtime window = 10 * HRTIME_SECOND; // update every 10 seconds
1826
static StatTwoIntSamples cluster_ua_total_bytes = { "proxy.node.user_agent_total_bytes", 0, 0, 0, 0 };
1827
static StatTwoIntSamples cluster_os_total_bytes = { "proxy.node.origin_server_total_bytes", 0, 0, 0, 0 };
1828
static const char *cluster_ua_total_bytes_name = "proxy.cluster.user_agent_total_bytes_avg_10s";
1829
static const char *cluster_os_total_bytes_name = "proxy.cluster.origin_server_total_bytes_avg_10s";
1832
MgmtInt UA_total = 0; // User Agent total
1833
MgmtInt OSPP_total = 0; // Origin Server and Parent Proxy(?)
1835
MgmtInt totalHits = 0;
1836
MgmtInt cacheOn = 1; // on by default
1837
MgmtInt httpCacheOn;
1839
// See if cache is on
1840
ink_assert(varIntFromName("proxy.config.http.cache.http", &httpCacheOn));
1841
cacheOn = httpCacheOn;
1843
// Get total cluster hits first, only calculate bandwith if > 0
1844
varIntFromName("proxy.cluster.http.cache_total_hits", &totalHits);
1849
varIntFromName("proxy.cluster.http.user_agent_total_request_bytes", &bytes);
1851
varIntFromName("proxy.cluster.http.user_agent_total_response_bytes", &bytes);
1855
varIntFromName("proxy.cluster.http.origin_server_total_request_bytes", &bytes);
1856
OSPP_total += bytes;
1857
varIntFromName("proxy.cluster.http.origin_server_total_response_bytes", &bytes);
1858
OSPP_total += bytes;
1859
varIntFromName("proxy.cluster.http.parent_proxy_total_request_bytes", &bytes);
1860
OSPP_total += bytes;
1861
varIntFromName("proxy.cluster.http.parent_proxy_total_response_bytes", &bytes);
1862
OSPP_total += bytes;
1864
// Special negative bandwidth scenario is treated here
1865
// See (Bug INKqa03094) and Ag_Bytes() in 'StatAggregation.cc'
1867
if (UA_total != 0 && totalHits && cacheOn) {
1868
hitRate = ((double) UA_total - (double) OSPP_total) / (double) UA_total;
1870
setBW = false; // negative bandwidth scenario....
1877
ink_assert(varSetFloat("proxy.cluster.http.bandwidth_hit_ratio", hitRate));
1880
ink_assert(varSetFloat("proxy.cluster.bandwidth_hit_ratio", hitRate));
1882
// get current time and delta to work with
1883
ink_hrtime current_time = ink_get_hrtime();
1884
// ink_hrtime delta = current_time - last_set_time;
1886
///////////////////////////////////////////////////////////////
1887
// if enough time expired, or first time, or wrapped around: //
1888
// (1) scroll current value into previous value //
1889
// (2) calculate new current values //
1890
// (3) only if proper time expired, set derived values //
1891
///////////////////////////////////////////////////////////////
1892
if (((current_time - last_set_time) > window) || // sufficient elapsed time
1893
(last_set_time == 0) || // first time
1894
(last_set_time > current_time)) // wrapped around
1896
////////////////////////////////////////
1897
// scroll values for node UA/OS bytes //
1898
///////////////////////////////////////
1899
cluster_ua_total_bytes.previous_time = cluster_ua_total_bytes.current_time;
1900
cluster_ua_total_bytes.previous_value = cluster_ua_total_bytes.current_value;
1902
cluster_os_total_bytes.previous_time = cluster_os_total_bytes.current_time;
1903
cluster_os_total_bytes.previous_value = cluster_os_total_bytes.current_value;
1905
//////////////////////////
1906
// calculate new values //
1907
//////////////////////////
1908
cluster_ua_total_bytes.current_value = -10000;
1909
cluster_ua_total_bytes.current_time = ink_get_hrtime();
1910
// TODO: Should we check return value?
1911
clusterSumInt(cluster_ua_total_bytes.lm_record_name, &(cluster_ua_total_bytes.current_value));
1913
cluster_os_total_bytes.current_value = -10000;
1914
cluster_os_total_bytes.current_time = ink_get_hrtime();
1915
// TODO: Should we check return value?
1916
clusterSumInt(cluster_os_total_bytes.lm_record_name, &(cluster_os_total_bytes.current_value));
1918
////////////////////////////////////////////////
1919
// if not initial or wrap, set derived values //
1920
////////////////////////////////////////////////
1921
if ((current_time - last_set_time) > window) {
1922
RecInt num_ua_total = 0;
1923
RecInt num_os_total = 0;
1926
// generate time window deltas and sum
1927
diff = cluster_ua_total_bytes.diff_value();
1928
varSetInt(cluster_ua_total_bytes_name, diff);
1929
num_ua_total = diff;
1931
diff = cluster_os_total_bytes.diff_value();
1932
varSetInt(cluster_os_total_bytes_name, diff);
1933
num_os_total = diff;
1935
if (num_ua_total == 0 || (num_ua_total < num_os_total))
1938
hitRate = (MgmtFloat) (((double) num_ua_total - (double) num_os_total) / (double) num_ua_total);
1940
// Check if more than one cluster node
1942
varIntFromName("proxy.process.cluster.nodes", &num_nodes);
1943
if (1 == num_nodes) {
1944
// Only one node , so grab local value
1945
varFloatFromName("proxy.node.bandwidth_hit_ratio_avg_10s", &hitRate);
1948
varSetFloat("proxy.cluster.bandwidth_hit_ratio_avg_10s", hitRate);
1950
/////////////////////////////////////////////////
1951
// done with a cycle, update the last_set_time //
1952
/////////////////////////////////////////////////
1953
last_set_time = current_time;
1956
} // end overviewPage::agBandwidthHitRate()
1958
// int overviewPage::clusterSumInt(char* nodeVar, MgmtInt* sum)
1960
// Sums nodeVar for every up node in the cluster and stores the
1961
// sum in *sum. Returns the number of nodes summed over
1963
// CALLEE MUST HOLD this->accessLock
1966
overviewPage::clusterSumInt(const char *nodeVar, RecInt * sum)
1969
int numHosts_local = sortRecords.getNumEntries();
1970
overviewRecord *current;
1973
ink_assert(sum != NULL);
1976
for (int i = 0; i < numHosts_local; i++) {
1977
current = (overviewRecord *) sortRecords[i];
1978
if (current->up == true) {
1980
*sum += current->readInteger(nodeVar, &found);
1981
if (found == false) {
1990
// Updates proxy.cluster.current_client_connections
1991
// Updates proxy.cluster.current_server_connections
1992
// Updates proxy.cluster.current_cache_connections
1995
overviewPage::agConnections()
1997
MgmtInt client_conn = 0;
1998
MgmtInt server_conn = 0;
1999
MgmtInt cache_conn = 0;
2001
clusterSumInt("proxy.node.current_client_connections", &client_conn);
2002
clusterSumInt("proxy.node.current_server_connections", &server_conn);
2003
clusterSumInt("proxy.node.current_cache_connections", &cache_conn);
2005
ink_assert(varSetInt("proxy.cluster.current_client_connections", client_conn));
2006
ink_assert(varSetInt("proxy.cluster.current_server_connections", server_conn));
2007
ink_assert(varSetInt("proxy.cluster.current_cache_connections", cache_conn));
2010
// void overviewPage::clusterAgInt(const char* clusterVar, const char* nodeVar)
2012
// Updates clusterVar with the sum of nodeVar for every node in the
2014
// CALLEE MUST HOLD this->accessLock
2017
overviewPage::clusterAgInt(const char *clusterVar, const char *nodeVar)
2022
numUsed = clusterSumInt(nodeVar, &sum);
2024
ink_assert(varSetInt(clusterVar, sum));
2029
overviewPage::clusterAgIntScale(const char *clusterVar, const char *nodeVar, double factor)
2034
numUsed = clusterSumInt(nodeVar, &sum);
2036
sum = (int) (sum * factor);
2037
ink_assert(varSetInt(clusterVar, sum));
2041
// int overviewPage::clusterSumCounter(char* nodeVar, MgmtIntCounter* sum)
2043
// Sums nodeVar for every up node in the cluster and stores the
2044
// sum in *sum. Returns the number of nodes summed over
2046
// CALLEE MUST HOLD this->accessLock
2049
overviewPage::clusterSumCounter(char *nodeVar, RecInt * sum)
2052
int numHosts_local = sortRecords.getNumEntries();
2053
overviewRecord *current;
2056
ink_assert(sum != NULL);
2059
for (int i = 0; i < numHosts_local; i++) {
2060
current = (overviewRecord *) sortRecords[i];
2061
if (current->up == true) {
2063
*sum += current->readCounter(nodeVar, &found);
2064
if (found == false) {
2072
// int overviewPage::clusterSumFloat(char* nodeVar, MgmtFloat* sum)
2074
// Sums nodeVar for every up node in the cluster and stores the
2075
// sum in *sum. Returns the number of nodes summed over
2077
// CALLEE MUST HOLD this->accessLock
2080
overviewPage::clusterSumFloat(const char *nodeVar, RecFloat * sum)
2083
int numHosts_local = sortRecords.getNumEntries();
2084
overviewRecord *current;
2087
ink_assert(sum != NULL);
2090
for (int i = 0; i < numHosts_local; i++) {
2091
current = (overviewRecord *) sortRecords[i];
2092
if (current->up == true) {
2094
*sum += current->readFloat(nodeVar, &found);
2095
if (found == false) {
2103
// void overviewPage::clusterAgFloat(const char* clusterVar, const char* nodeVar)
2106
// Sums nodeVar for every up node in the cluster and stores the
2109
// CALLEE MUST HOLD this->accessLock
2112
overviewPage::clusterAgFloat(const char *clusterVar, const char *nodeVar)
2117
numUsed = clusterSumFloat(nodeVar, &sum);
2120
ink_assert(varSetFloat(clusterVar, sum));
2124
// int varClusterIntFromName(char* nodeVar, MgmtInt* sum)
2125
// External accessible wrapper for clusterIntFloat.
2126
// It acquires the overveiw access lock, calls the
2127
// clusterIntFloat function and then releases the lock.
2129
overviewPage::varClusterIntFromName(char *nodeVar, RecInt * sum)
2131
ink_mutex_acquire(&accessLock);
2133
RecDataT varDataType;
2135
RecFloat tempFloat = 0.0;
2137
RecGetRecordDataType(nodeVar, &varDataType);
2139
if (varDataType == RECD_INT) {
2140
status = clusterSumInt(nodeVar, &tempInt);
2141
tempFloat = (RecFloat) tempInt;
2142
} else if (varDataType == RECD_FLOAT) {
2143
status = clusterSumFloat(nodeVar, &tempFloat);
2145
*sum = (RecInt) tempFloat;
2146
ink_mutex_release(&accessLock);
2151
overviewPage::varClusterFloatFromName(char *nodeVar, RecFloat * sum)
2153
ink_mutex_acquire(&accessLock);
2155
RecDataT varDataType;
2157
RecFloat tempFloat = 0.0;
2159
RecGetRecordDataType(nodeVar, &varDataType);
2161
if (varDataType == RECD_INT) {
2162
status = clusterSumInt(nodeVar, &tempInt);
2163
tempFloat = (RecFloat) tempInt;
2164
} else if (varDataType == RECD_FLOAT) {
2165
status = clusterSumFloat(nodeVar, &tempFloat);
2169
ink_mutex_release(&accessLock);
2174
overviewPage::varClusterCounterFromName(char *nodeVar, RecInt * sum)
2177
ink_mutex_acquire(&accessLock);
2178
status = clusterSumCounter(nodeVar, sum);
2179
ink_mutex_release(&accessLock);
2183
// void overviewPage::doClusterAg()
2185
// Aggregate data for cluster records
2188
overviewPage::doClusterAg()
2191
ink_mutex_acquire(&accessLock);
2195
clusterAgFloat("proxy.cluster.dns.lookups_per_second", "proxy.node.dns.lookups_per_second");
2196
clusterAgInt("proxy.cluster.dns.total_dns_lookups", "proxy.node.dns.total_dns_lookups");
2198
clusterAgInt("proxy.cluster.http.throughput", "proxy.node.http.throughput");
2200
clusterAgFloat("proxy.cluster.http.user_agent_xacts_per_second", "proxy.node.http.user_agent_xacts_per_second");
2202
clusterAgInt("proxy.cluster.http.user_agent_current_connections_count",
2203
"proxy.node.http.user_agent_current_connections_count");
2204
clusterAgInt("proxy.cluster.http.origin_server_current_connections_count",
2205
"proxy.node.http.origin_server_current_connections_count");
2206
clusterAgInt("proxy.cluster.http.cache_current_connections_count", "proxy.node.http.cache_current_connections_count");
2208
clusterAgInt("proxy.cluster.http.current_parent_proxy_connections",
2209
"proxy.node.http.current_parent_proxy_connections");
2211
clusterAgInt("proxy.cluster.http.user_agent_total_request_bytes", "proxy.node.http.user_agent_total_request_bytes");
2212
clusterAgInt("proxy.cluster.http.user_agent_total_response_bytes", "proxy.node.http.user_agent_total_response_bytes");
2213
clusterAgInt("proxy.cluster.http.origin_server_total_request_bytes",
2214
"proxy.node.http.origin_server_total_request_bytes");
2215
clusterAgInt("proxy.cluster.http.origin_server_total_response_bytes",
2216
"proxy.node.http.origin_server_total_response_bytes");
2217
clusterAgInt("proxy.cluster.http.parent_proxy_total_request_bytes",
2218
"proxy.node.http.parent_proxy_total_request_bytes");
2219
clusterAgInt("proxy.cluster.http.parent_proxy_total_response_bytes",
2220
"proxy.node.http.parent_proxy_total_response_bytes");
2222
clusterAgInt("proxy.cluster.http.user_agents_total_transactions_count",
2223
"proxy.node.http.user_agents_total_transactions_count");
2224
clusterAgInt("proxy.cluster.http.user_agents_total_documents_served",
2225
"proxy.node.http.user_agents_total_documents_served");
2226
clusterAgInt("proxy.cluster.http.origin_server_total_transactions_count",
2227
"proxy.node.http.origin_server_total_transactions_count");
2230
clusterAgInt("proxy.cluster.cache.bytes_free", "proxy.node.cache.bytes_free");
2231
clusterAgIntScale("proxy.cluster.cache.bytes_free_mb", "proxy.node.cache.bytes_free", MB_SCALE);
2232
clusterAgInt("proxy.cluster.cache.contents.num_docs", "proxy.node.cache.contents.num_docs");
2234
this->agHostdbHitRate();
2235
this->agCacheHitRate();
2236
this->agCachePercentFree();
2237
this->agBandwidthHitRate();
2238
this->agConnections();
2241
clusterAgFloat("proxy.cluster.client_throughput_out", "proxy.node.client_throughput_out");
2244
clusterAgFloat("proxy.cluster.user_agent_xacts_per_second", "proxy.node.user_agent_xacts_per_second");
2246
AgFloat_generic_scale_to_int("proxy.cluster.client_throughput_out",
2247
"proxy.cluster.client_throughput_out_kbit", MBIT_TO_KBIT_SCALE);
2248
AgFloat_generic_scale_to_int("proxy.cluster.http.cache_hit_ratio",
2249
"proxy.cluster.http.cache_hit_ratio_int_pct", PCT_TO_INTPCT_SCALE);
2250
AgFloat_generic_scale_to_int("proxy.cluster.cache_hit_ratio",
2251
"proxy.cluster.cache_hit_ratio_int_pct", PCT_TO_INTPCT_SCALE);
2252
AgFloat_generic_scale_to_int("proxy.cluster.http.bandwidth_hit_ratio",
2253
"proxy.cluster.http.bandwidth_hit_ratio_int_pct", PCT_TO_INTPCT_SCALE);
2254
AgFloat_generic_scale_to_int("proxy.cluster.bandwidth_hit_ratio",
2255
"proxy.cluster.bandwidth_hit_ratio_int_pct", PCT_TO_INTPCT_SCALE);
2256
AgFloat_generic_scale_to_int("proxy.cluster.hostdb.hit_ratio",
2257
"proxy.cluster.hostdb.hit_ratio_int_pct", PCT_TO_INTPCT_SCALE);
2258
AgFloat_generic_scale_to_int("proxy.cluster.cache.percent_free",
2259
"proxy.cluster.cache.percent_free_int_pct", PCT_TO_INTPCT_SCALE);
2260
ink_mutex_release(&accessLock);
2263
// char* overviewPage::resolvePeerHostname(char* peerIP)
2265
// A locking interface to overviewPage::resolvePeerHostname_ml
2268
overviewPage::resolvePeerHostname(const char *peerIP)
2272
ink_mutex_acquire(&accessLock);
2273
r = this->resolvePeerHostname_ml(peerIP);
2274
ink_mutex_release(&accessLock);
2279
// char* overviewPage::resolvePeerHostname_ml(char* peerIP)
2281
// Resolves the peer the hostname from its IP address
2282
// The hostname is resolved by finding the overviewRecord
2283
// Associated with the IP address and copying its hostname
2285
// CALLEE frees storage
2286
// CALLEE is responsible for locking
2289
overviewPage::resolvePeerHostname_ml(const char *peerIP)
2291
unsigned long int ipAddr;
2292
InkHashTableValue lookup;
2293
overviewRecord *peerRecord;
2294
char *returnName = NULL;
2296
ipAddr = inet_addr(peerIP);
2298
// Check to see if our address is malformed
2299
if ((long int) ipAddr == -1) {
2303
if (ink_hash_table_lookup(nodeRecords, (InkHashTableKey) ipAddr, &lookup)) {
2304
peerRecord = (overviewRecord *) lookup;
2305
returnName = xstrdup(peerRecord->hostname);
2313
// Handles the form submission for alarm resolution
2314
// uses the form arguments to call resolveAlarm.
2316
// Takes a hash-table returned by processFormSubmission
2318
// Note: resolving an alarm is asyncronous with the list of
2319
// alarms maintained in overviewRecords. That list
2320
// is only updates when checkAlarms is called
2323
resolveAlarm(InkHashTable * post_data_ht)
2326
InkHashTableIteratorState htis;
2327
InkHashTableEntry *hte;
2330
Tokenizer colonTok(":");
2334
for (hte = ink_hash_table_iterator_first(post_data_ht, &htis);
2335
hte != NULL; hte = ink_hash_table_iterator_next(post_data_ht, &htis)) {
2336
name = (char *) ink_hash_table_entry_key(post_data_ht, hte);
2337
value = (char *) ink_hash_table_entry_value(post_data_ht, hte);
2338
if (strncmp(name, "alarm:", 6) != 0)
2340
if (colonTok.Initialize(value) == 2) {
2341
alarmType = atoi(colonTok[0]);
2342
ipAddr = colonTok[1];
2343
Debug("dashboard", "Resolving alarm %d for %s\n", alarmType, ipAddr);
2344
if (strcmp("local", ipAddr) == 0)
2346
if (lmgmt->alarm_keeper->isCurrentAlarm(alarmType, (char *) ipAddr)) {
2347
Debug("dashboard", "\t Before resolution the alarm is current\n");
2349
Debug("dashboard", "\t Before resolution the alarm is NOT current\n");
2351
lmgmt->alarm_keeper->resolveAlarm(alarmType, (char *) ipAddr);
2352
if (lmgmt->alarm_keeper->isCurrentAlarm(alarmType, (char *) ipAddr)) {
2353
Debug("dashboard", "\t After resolution the alarm is current\n");
2355
Debug("dashboard", "\t After resolution the alarm is NOT current\n");
2359
overviewGenerator->checkForUpdates();
2363
resolveAlarmCLI(textBuffer * output, const char *request)
2365
NOWARN_UNUSED(output);
2366
Tokenizer colonTok(":");
2367
const char *ipAddr = NULL;
2370
// Get ipAddr of host to resolve alarm for
2371
// request is in form 'alarmType:ipAddr'
2372
if (request && colonTok.Initialize(request) == 2) {
2373
alarmType = atoi(colonTok[0]);
2374
ipAddr = colonTok[1];
2376
Debug("cli", "resolveAlarmCLI: Resolving alarm %d for %s\n", alarmType, ipAddr);
2378
if (strcmp("local", ipAddr) == 0)
2381
if (lmgmt->alarm_keeper->isCurrentAlarm(alarmType, (char *) ipAddr)) {
2382
Debug("cli", "\t Before resolution the alarm is current\n");
2384
Debug("cli", "\t Before resolution the alarm is NOT current\n");
2387
lmgmt->alarm_keeper->resolveAlarm(alarmType, (char *) ipAddr);
2389
if (lmgmt->alarm_keeper->isCurrentAlarm(alarmType, (char *) ipAddr)) {
2390
Debug("cli", "\t After resolution the alarm is current\n");
2392
Debug("cli", "\t After resolution the alarm is NOT current\n");
2396
overviewGenerator->checkForUpdates();
2397
} // end resolveAlarmCLI()
2399
// wrapper for the Alarm Callback
2401
overviewAlarmCallback(alarm_t newAlarm, char *ip, char *desc)
2403
overviewGenerator->addAlarm(newAlarm, ip, desc);
2406
AlarmListable::~AlarmListable()
2417
// int hostSortFunc(const void* arg1, const void* arg2)
2419
// A compare function that we can to qsort that sorts
2423
hostSortFunc(const void *arg1, const void *arg2)
2425
overviewRecord *rec1 = (overviewRecord *) * (void **) arg1;
2426
overviewRecord *rec2 = (overviewRecord *) * (void **) arg2;
2428
return strcmp(rec1->hostname, rec2->hostname);