00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 #include "P_Cache.h"
00025 
00026 #include "Show.h"
00027 #include "I_Tasks.h"
00028 
00029 struct ShowCacheInternal: public ShowCont
00030 {
00031   int vol_index;
00032   int seg_index;
00033   CacheKey show_cache_key;
00034   CacheVC *cache_vc;
00035 
00036 
00037   int showMain(int event, Event * e);
00038   int showEvacuations(int event, Event * e);
00039   int showVolEvacuations(int event, Event * e);
00040   int showVolumes(int event, Event * e);
00041   int showVolVolumes(int event, Event * e);
00042   int showSegments(int event, Event * e);
00043   int showSegSegment(int event, Event * e);
00044 #ifdef CACHE_STAT_PAGES
00045   int showConnections(int event, Event * e);
00046   int showVolConnections(int event, Event * e);
00047 #endif
00048 
00049   ShowCacheInternal(Continuation * c, HTTPHdr * h)
00050     : ShowCont(c, h), vol_index(0), seg_index(0)
00051   {
00052     SET_HANDLER(&ShowCacheInternal::showMain);
00053   }
00054 
00055   ~ShowCacheInternal() {
00056   }
00057 
00058 };
00059 extern ShowCacheInternal *theshowcacheInternal;
00060 Action *register_ShowCacheInternal(Continuation * c, HTTPHdr * h);
00061 
00062 
00063 
00064 
00065 extern Vol **gvol;
00066 extern volatile int gnvol;
00067 
00068 
00069 
00070 ShowCacheInternal *theshowcacheInternal = NULL;
00071 
00072 
00073 #define STREQ_PREFIX(_x,_s) (!strncasecmp(_x,_s,sizeof(_s)-1))
00074 #define STREQ_LEN_PREFIX(_x,_l,_s) (path_len < sizeof(_s) && !strncasecmp(_x,_s,sizeof(_s)-1))
00075 
00076 
00077 Action *
00078 register_ShowCacheInternal(Continuation * c, HTTPHdr * h)
00079 {
00080   theshowcacheInternal = new ShowCacheInternal(c, h);
00081   URL *u = h->url_get();
00082 
00083   int path_len;
00084   const char *path = u->path_get(&path_len);
00085 
00086   if (!path) {
00087   }
00088 #ifdef CACHE_STAT_PAGES
00089   else if (STREQ_LEN_PREFIX(path, path_len, "connections")) {
00090     SET_CONTINUATION_HANDLER(theshowcacheInternal, &ShowCacheInternal::showConnections);
00091   }
00092 #endif
00093   else if (STREQ_PREFIX(path, "evacuations")) {
00094     SET_CONTINUATION_HANDLER(theshowcacheInternal, &ShowCacheInternal::showEvacuations);
00095   } else if (STREQ_PREFIX(path, "volumes")) {
00096     SET_CONTINUATION_HANDLER(theshowcacheInternal, &ShowCacheInternal::showVolumes);
00097   }
00098 
00099   if (theshowcacheInternal->mutex->thread_holding)
00100     CONT_SCHED_LOCK_RETRY(theshowcacheInternal);
00101   else
00102     eventProcessor.schedule_imm(theshowcacheInternal, ET_TASK);
00103   return &theshowcacheInternal->action;
00104 }
00105 
00106 
00107 int
00108 ShowCacheInternal::showMain(int event, Event * e)
00109 {
00110   CHECK_SHOW(begin("Cache"));
00111 #ifdef CACHE_STAT_PAGES
00112   CHECK_SHOW(show("<H3>Show <A HREF=\"./connections\">Connections</A></H3>\n"
00113                   "<H3>Show <A HREF=\"./evacuations\">Evacuations</A></H3>\n"
00114                   "<H3>Show <A HREF=\"./volumes\">Volumes</A></H3>\n"));
00115 #else
00116   CHECK_SHOW(show("<H3>Show <A HREF=\"./evacuations\">Evacuations</A></H3>\n"
00117                   "<H3>Show <A HREF=\"./volumes\">Volumes</A></H3>\n"));
00118 #endif
00119   return complete(event, e);
00120 }
00121 
00122 #ifdef CACHE_STAT_PAGES
00123 int
00124 ShowCacheInternal::showConnections(int event, Event * e)
00125 {
00126   CHECK_SHOW(begin("Cache VConnections"));
00127   CHECK_SHOW(show("<H3>Cache Connections</H3>\n"
00128                   "<table border=1><tr>"
00129                   "<th>Operation</th>"
00130                   "<th>Volume</th>"
00131                   "<th>URL/Hash</th>" "<th>Bytes Done</th>" "<th>Total Bytes</th>" "<th>Bytes Todo</th>" "</tr>\n"));
00132 
00133   SET_HANDLER(&ShowCacheInternal::showVolConnections);
00134   CONT_SCHED_LOCK_RETRY_RET(this);
00135 }
00136 
00137 
00138 int
00139 ShowCacheInternal::showVolConnections(int event, Event * e)
00140 {
00141   CACHE_TRY_LOCK(lock, gvol[vol_index]->mutex, mutex->thread_holding);
00142   if (!lock) {
00143     CONT_SCHED_LOCK_RETRY_RET(this);
00144   }
00145   for (CacheVC * vc = (CacheVC *) gvol[vol_index]->stat_cache_vcs.head; vc; vc = vc->stat_link.next) {
00146 
00147     char nbytes[60], todo[60], url[81092];
00148     int ib = 0, xd = 0;
00149     URL uu;
00150 
00151     MUTEX_LOCK(lock2, vc->mutex, mutex->thread_holding);
00152     
00153     if (vc->closed == 1)
00154       continue;
00155     sprintf(nbytes, "%d", vc->vio.nbytes);
00156     sprintf(todo, "%d", vc->vio.ntodo());
00157 
00158     if (vc->f.frag_type == CACHE_FRAG_TYPE_HTTP && vc->request.valid()) {
00159       URL *u = vc->request.url_get(&uu);
00160       u->print(url, 8000, &ib, &xd);
00161       url[ib] = 0;
00162     } else if (vc->alternate.valid()) {
00163       URL *u = vc->alternate.request_url_get(&uu);
00164       u->print(url, 8000, &ib, &xd);
00165       url[ib] = 0;
00166     } else
00167       vc->key.string(url);
00168     CHECK_SHOW(show("<tr>" "<td>%s</td>"        
00169                     "<td>%s</td>"       
00170                     "<td>%s</td>"       
00171                     "<td>%d</td>"
00172                     "<td>%s</td>"
00173                     "<td>%s</td>"
00174                     "</tr>\n",
00175                     ((vc->vio.op == VIO::READ) ? "Read" : "Write"),
00176                     vc->vol->hash_id,
00177                     url,
00178                     vc->vio.ndone,
00179                     vc->vio.nbytes == INT64_MAX ? "all" : nbytes, vc->vio.nbytes == INT64_MAX ? "all" : todo));
00180   }
00181   vol_index++;
00182   if (vol_index < gnvol)
00183     CONT_SCHED_LOCK_RETRY(this);
00184   else {
00185     CHECK_SHOW(show("</table>\n"));
00186     return complete(event, e);
00187   }
00188   return EVENT_CONT;
00189 }
00190 
00191 #endif
00192 
00193 
00194 int
00195 ShowCacheInternal::showEvacuations(int event, Event * e)
00196 {
00197   CHECK_SHOW(begin("Cache Pending Evacuations"));
00198   CHECK_SHOW(show("<H3>Cache Evacuations</H3>\n"
00199                   "<table border=1><tr>"
00200                   "<th>Offset</th>" "<th>Estimated Size</th>" "<th>Reader Count</th>" "<th>Done</th>" "</tr>\n"));
00201 
00202   SET_HANDLER(&ShowCacheInternal::showVolEvacuations);
00203   CONT_SCHED_LOCK_RETRY_RET(this);
00204 }
00205 
00206 
00207 int
00208 ShowCacheInternal::showVolEvacuations(int event, Event * e)
00209 {
00210   Vol *p = gvol[vol_index];
00211   CACHE_TRY_LOCK(lock, p->mutex, mutex->thread_holding);
00212   if (!lock)
00213     CONT_SCHED_LOCK_RETRY_RET(this);
00214 
00215   EvacuationBlock *b;
00216   int last = (p->len - (p->start - p->skip)) / EVACUATION_BUCKET_SIZE;
00217   for (int i = 0; i < last; i++) {
00218     for (b = p->evacuate[i].head; b; b = b->link.next) {
00219       char offset[60];
00220       sprintf(offset, "%" PRIu64 "", (uint64_t) vol_offset(p, &b->dir));
00221       CHECK_SHOW(show("<tr>" "<td>%s</td>"      
00222                       "<td>%d</td>"     
00223                       "<td>%d</td>"     
00224                       "<td>%s</td>"     
00225                       "</tr>\n", offset, (int) dir_approx_size(&b->dir), b->readers, b->f.done ? "yes" : "no"));
00226     }
00227   }
00228   vol_index++;
00229   if (vol_index < gnvol)
00230     CONT_SCHED_LOCK_RETRY(this);
00231   else {
00232     CHECK_SHOW(show("</table>\n"));
00233     return complete(event, e);
00234   }
00235   return EVENT_CONT;
00236 }
00237 
00238 int
00239 ShowCacheInternal::showVolumes(int event, Event * e)
00240 {
00241   CHECK_SHOW(begin("Cache Volumes"));
00242   CHECK_SHOW(show("<H3>Cache Volumes</H3>\n"
00243                   "<table border=1><tr>"
00244                   "<th>ID</th>"
00245                   "<th>Blocks</th>"
00246                   "<th>Directory Entries</th>"
00247                   "<th>Write Position</th>"
00248                   "<th>Write Agg Todo</th>"
00249                   "<th>Write Agg Todo Size</th>"
00250                   "<th>Write Agg Done</th>"
00251                   "<th>Phase</th>" "<th>Create Time</th>" "<th>Sync Serial</th>" "<th>Write Serial</th>" "</tr>\n"));
00252 
00253   SET_HANDLER(&ShowCacheInternal::showVolVolumes);
00254   CONT_SCHED_LOCK_RETRY_RET(this);
00255 }
00256 
00257 
00258 int
00259 ShowCacheInternal::showVolVolumes(int event, Event * e)
00260 {
00261   Vol *p = gvol[vol_index];
00262   CACHE_TRY_LOCK(lock, p->mutex, mutex->thread_holding);
00263   if (!lock)
00264     CONT_SCHED_LOCK_RETRY_RET(this);
00265 
00266   char ctime[256];
00267   ink_ctime_r(&p->header->create_time, ctime);
00268   ctime[strlen(ctime) - 1] = 0;
00269   int agg_todo = 0;
00270   int agg_done = p->agg_buf_pos;
00271   CacheVC *c = 0;
00272   for (c = p->agg.head; c; c = (CacheVC *) c->link.next)
00273     agg_todo++;
00274   CHECK_SHOW(show("<tr>" "<td>%s</td>"  
00275                   "<td>%" PRId64 "</td>" 
00276                   "<td>%" PRId64 "</td>" 
00277                   "<td>%" PRId64 "</td>" 
00278                   "<td>%d</td>" 
00279                   "<td>%d</td>" 
00280                   "<td>%d</td>" 
00281                   "<td>%d</td>" 
00282                   "<td>%s</td>" 
00283                   "<td>%u</td>" 
00284                   "<td>%u</td>" 
00285                   "</tr>\n",
00286                   p->hash_text.get(),
00287                   (uint64_t)((p->len - (p->start - p->skip)) / CACHE_BLOCK_SIZE),
00288                   (uint64_t)(p->buckets * DIR_DEPTH * p->segments),
00289                   (uint64_t)((p->header->write_pos - p->start) / CACHE_BLOCK_SIZE),
00290                   agg_todo,
00291                   p->agg_todo_size,
00292                   agg_done, p->header->phase, ctime, p->header->sync_serial, p->header->write_serial));
00293   CHECK_SHOW(show("</table>\n"));
00294   SET_HANDLER(&ShowCacheInternal::showSegments);
00295   return showSegments(event, e);
00296 }
00297 
00298 int
00299 ShowCacheInternal::showSegments(int event, Event * e)
00300 {
00301   CHECK_SHOW(show("<H3>Cache Volume Segments</H3>\n"
00302                   "<table border=1><tr>"
00303                   "<th>Free</th>"
00304                   "<th>Used</th>"
00305                   "<th>Empty</th>" "<th>Valid</th>" "<th>Agg Valid</th>" "<th>Avg Size</th>" "</tr>\n"));
00306 
00307   SET_HANDLER(&ShowCacheInternal::showSegSegment);
00308   seg_index = 0;
00309   CONT_SCHED_LOCK_RETRY_RET(this);
00310 }
00311 
00312 int
00313 ShowCacheInternal::showSegSegment(int event, Event * e)
00314 {
00315   Vol *p = gvol[vol_index];
00316   CACHE_TRY_LOCK(lock, p->mutex, mutex->thread_holding);
00317   if (!lock)
00318     CONT_SCHED_LOCK_RETRY_RET(this);
00319   int free = 0, used = 0, empty = 0, valid = 0, agg_valid = 0, avg_size = 0;
00320   dir_segment_accounted(seg_index, p, 0, &free, &used, &empty, &valid, &agg_valid, &avg_size);
00321   CHECK_SHOW(show("<tr>"
00322                   "<td>%d</td>"
00323                   "<td>%d</td>"
00324                   "<td>%d</td>"
00325                   "<td>%d</td>" "<td>%d</td>" "<td>%d</td>" "</tr>\n", free, used, empty, valid, agg_valid, avg_size));
00326   seg_index++;
00327   if (seg_index < p->segments)
00328     CONT_SCHED_LOCK_RETRY(this);
00329   else {
00330     CHECK_SHOW(show("</table>\n"));
00331     seg_index = 0;
00332     vol_index++;
00333     if (vol_index < gnvol)
00334       CONT_SCHED_LOCK_RETRY(this);
00335     else
00336       return complete(event, e);
00337   }
00338   return EVENT_CONT;
00339 }
00340