00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 #include "libts.h"
00031 
00032 #include "Error.h"
00033 #include "LogUtils.h"
00034 #include "LogField.h"
00035 #include "LogBuffer.h"
00036 #include "LogAccess.h"
00037 #include "Log.h"
00038 
00039 const char *container_names[] = {
00040   "not-a-container",
00041   "cqh",
00042   "psh",
00043   "pqh",
00044   "ssh",
00045   "cssh",
00046   "ecqh",
00047   "epsh",
00048   "epqh",
00049   "essh",
00050   "ecssh",
00051   "icfg",
00052   "scfg",
00053   "record",
00054   ""
00055 };
00056 
00057 const char *aggregate_names[] = {
00058   "not-an-agg-op",
00059   "COUNT",
00060   "SUM",
00061   "AVG",
00062   "FIRST",
00063   "LAST",
00064   ""
00065 };
00066 
00067 LogSlice::LogSlice(char *str)
00068 {
00069   char *a, *b, *c;
00070 
00071   m_enable = false;
00072   m_start = 0;
00073   m_end = INT_MAX;
00074 
00075   if ((a = strchr(str, '[')) == NULL)
00076     return;
00077 
00078   *a++ = '\0';
00079   if ((b = strchr(a, ':')) == NULL)
00080     return;
00081 
00082   *b++ = '\0';
00083   if ((c = strchr(b, ']')) == NULL)
00084     return;
00085 
00086   m_enable = true;
00087 
00088   
00089   while (a != b && *a == ' ') a++;
00090 
00091   if (a != b)
00092     m_start = atoi(a);
00093 
00094   
00095   while (b != c && *b == ' ') b++;
00096 
00097   if (b != c)
00098     m_end = atoi(b);
00099 }
00100 
00101 int
00102 LogSlice::toStrOffset(int strlen, int *offset)
00103 {
00104   int i, j, len;
00105 
00106   
00107   if (m_start >= 0)
00108     i = m_start;
00109   else
00110     i = m_start + strlen;
00111 
00112   if (i >= strlen)
00113     return 0;
00114 
00115   if (i < 0)
00116     i = 0;
00117 
00118   
00119   if (m_end >= 0)
00120     j = m_end;
00121   else
00122     j = m_end + strlen;
00123 
00124   if (j <= 0)
00125     return 0;
00126 
00127   if (j > strlen)
00128     j = strlen;
00129 
00130   
00131   len = j - i;
00132 
00133   if (len > 0)
00134     *offset = i;
00135 
00136   return len;
00137 }
00138 
00139 
00140 
00141 
00142 
00143 
00144 LogField::LogField(const char *name, const char *symbol, Type type, MarshalFunc marshal, UnmarshalFunc unmarshal, SetFunc _setfunc)
00145   : m_name(ats_strdup(name)), m_symbol(ats_strdup(symbol)), m_type(type), m_container(NO_CONTAINER), m_marshal_func(marshal),
00146     m_unmarshal_func(unmarshal), m_unmarshal_func_map(NULL), m_agg_op(NO_AGGREGATE), m_agg_cnt(0), m_agg_val(0),
00147     m_time_field(false), m_alias_map(0), m_set_func(_setfunc)
00148 {
00149   ink_assert(m_name != NULL);
00150   ink_assert(m_symbol != NULL);
00151   ink_assert(m_type >= 0 && m_type < N_TYPES);
00152   ink_assert(m_marshal_func != (MarshalFunc) NULL);
00153 
00154   m_time_field = (strcmp(m_symbol, "cqts") == 0
00155                   || strcmp(m_symbol, "cqth") == 0
00156                   || strcmp(m_symbol, "cqtq") == 0
00157                   || strcmp(m_symbol, "cqtn") == 0 || strcmp(m_symbol, "cqtd") == 0 || strcmp(m_symbol, "cqtt") == 0);
00158 }
00159 
00160 LogField::LogField(const char *name, const char *symbol, Type type,
00161                    MarshalFunc marshal, UnmarshalFuncWithMap unmarshal, Ptr<LogFieldAliasMap> map, SetFunc _setfunc)
00162   : m_name(ats_strdup(name)), m_symbol(ats_strdup(symbol)), m_type(type), m_container(NO_CONTAINER), m_marshal_func(marshal),
00163     m_unmarshal_func(NULL), m_unmarshal_func_map(unmarshal), m_agg_op(NO_AGGREGATE), m_agg_cnt(0), m_agg_val(0),
00164     m_time_field(false), m_alias_map(map), m_set_func(_setfunc)
00165 {
00166   ink_assert(m_name != NULL);
00167   ink_assert(m_symbol != NULL);
00168   ink_assert(m_type >= 0 && m_type < N_TYPES);
00169   ink_assert(m_marshal_func != (MarshalFunc) NULL);
00170   ink_assert(m_alias_map != NULL);
00171 
00172   m_time_field = (strcmp(m_symbol, "cqts") == 0
00173                   || strcmp(m_symbol, "cqth") == 0
00174                   || strcmp(m_symbol, "cqtq") == 0
00175                   || strcmp(m_symbol, "cqtn") == 0 || strcmp(m_symbol, "cqtd") == 0 || strcmp(m_symbol, "cqtt") == 0);
00176 }
00177 
00178 
00179 LogField::LogField(const char *field, Container container, SetFunc _setfunc)
00180   : m_name(ats_strdup(field)), m_symbol(ats_strdup(container_names[container])), m_type(LogField::STRING),
00181     m_container(container), m_marshal_func(NULL), m_unmarshal_func(NULL), m_unmarshal_func_map(NULL),
00182     m_agg_op(NO_AGGREGATE), m_agg_cnt(0), m_agg_val(0), m_time_field(false), m_alias_map(0), m_set_func(_setfunc)
00183 {
00184   ink_assert(m_name != NULL);
00185   ink_assert(m_symbol != NULL);
00186   ink_assert(m_type >= 0 && m_type < N_TYPES);
00187 
00188   m_time_field = (strcmp(m_symbol, "cqts") == 0
00189                   || strcmp(m_symbol, "cqth") == 0
00190                   || strcmp(m_symbol, "cqtq") == 0
00191                   || strcmp(m_symbol, "cqtn") == 0 || strcmp(m_symbol, "cqtd") == 0 || strcmp(m_symbol, "cqtt") == 0);
00192 
00193   switch (m_container) {
00194   case CQH:
00195   case PSH:
00196   case PQH:
00197   case SSH:
00198   case CSSH:
00199   case ECQH:
00200   case EPSH:
00201   case EPQH:
00202   case ESSH:
00203   case ECSSH:
00204   case SCFG:
00205     m_unmarshal_func = (UnmarshalFunc)&(LogAccess::unmarshal_str);
00206     break;
00207 
00208   case ICFG:
00209     m_unmarshal_func = &(LogAccess::unmarshal_int_to_str);
00210     break;
00211 
00212   case RECORD:
00213     m_unmarshal_func = &(LogAccess::unmarshal_record);
00214     break;
00215 
00216   default:
00217     Note("Invalid container type in LogField ctor: %d", container);
00218   }
00219 }
00220 
00221 
00222 LogField::LogField(const LogField &rhs)
00223   : m_name(ats_strdup(rhs.m_name)), m_symbol(ats_strdup(rhs.m_symbol)), m_type(rhs.m_type), m_container(rhs.m_container),
00224     m_marshal_func(rhs.m_marshal_func), m_unmarshal_func(rhs.m_unmarshal_func), m_unmarshal_func_map(rhs.m_unmarshal_func_map),
00225     m_agg_op(rhs.m_agg_op), m_agg_cnt(0), m_agg_val(0), m_time_field(rhs.m_time_field), m_alias_map(rhs.m_alias_map), m_set_func(rhs.m_set_func)
00226 {
00227   ink_assert(m_name != NULL);
00228   ink_assert(m_symbol != NULL);
00229   ink_assert(m_type >= 0 && m_type < N_TYPES);
00230 }
00231 
00232 
00233 
00234 
00235 LogField::~LogField()
00236 {
00237   ats_free(m_name);
00238   ats_free(m_symbol);
00239 }
00240 
00241 
00242 
00243 
00244 
00245 
00246 
00247 
00248 
00249 unsigned
00250 LogField::marshal_len(LogAccess *lad)
00251 {
00252   if (m_container == NO_CONTAINER)
00253     return (lad->*m_marshal_func) (NULL);
00254 
00255   switch (m_container) {
00256   case CQH:
00257   case PSH:
00258   case PQH:
00259   case SSH:
00260   case CSSH:
00261     return lad->marshal_http_header_field(m_container, m_name, NULL);
00262 
00263   case ECQH:
00264   case EPSH:
00265   case EPQH:
00266   case ESSH:
00267   case ECSSH:
00268     return lad->marshal_http_header_field_escapify(m_container, m_name, NULL);
00269 
00270   case ICFG:
00271     return lad->marshal_config_int_var(m_name, NULL);
00272 
00273   case SCFG:
00274     return lad->marshal_config_str_var(m_name, NULL);
00275 
00276   case RECORD:
00277     return lad->marshal_record(m_name, NULL);
00278 
00279   default:
00280     return 0;
00281   }
00282 }
00283 
00284 void
00285 LogField::updateField(LogAccess *lad, char *buf, int len)
00286 {
00287   if (m_container == NO_CONTAINER) {
00288     return (lad->*m_set_func) (buf, len);
00289   }
00290   
00291 }
00292 
00293 
00294 
00295 
00296 
00297 
00298 unsigned
00299 LogField::marshal(LogAccess *lad, char *buf)
00300 {
00301   if (m_container == NO_CONTAINER) {
00302     return (lad->*m_marshal_func) (buf);
00303   }
00304 
00305   switch (m_container) {
00306   case CQH:
00307   case PSH:
00308   case PQH:
00309   case SSH:
00310   case CSSH:
00311     return lad->marshal_http_header_field(m_container, m_name, buf);
00312 
00313   case ECQH:
00314   case EPSH:
00315   case EPQH:
00316   case ESSH:
00317   case ECSSH:
00318     return lad->marshal_http_header_field_escapify(m_container, m_name, buf);
00319 
00320   case ICFG:
00321     return lad->marshal_config_int_var(m_name, buf);
00322 
00323   case SCFG:
00324     return lad->marshal_config_str_var(m_name, buf);
00325 
00326   case RECORD:
00327     return lad->marshal_record(m_name, buf);
00328 
00329   default:
00330     return 0;
00331   }
00332 }
00333 
00334 
00335 
00336 
00337 unsigned
00338 LogField::marshal_agg(char *buf)
00339 {
00340   ink_assert(buf != NULL);
00341   int64_t avg = 0;
00342 
00343   switch (m_agg_op) {
00344 
00345   case eCOUNT:
00346     LogAccess::marshal_int(buf, m_agg_cnt);
00347     break;
00348 
00349   case eSUM:
00350   case eFIRST:
00351   case eLAST:
00352     LogAccess::marshal_int(buf, m_agg_val);
00353     break;
00354 
00355   case eAVG:
00356     if (m_agg_cnt) {
00357       avg = m_agg_val / m_agg_cnt;
00358     }
00359     LogAccess::marshal_int(buf, avg);
00360     break;
00361 
00362   default:
00363     Note("Cannot marshal aggregate field %s; " "invalid aggregate operator: %d", m_symbol, m_agg_op);
00364     return 0;
00365   }
00366 
00367   m_agg_val = 0;
00368   m_agg_cnt = 0;
00369 
00370   return INK_MIN_ALIGN;
00371 }
00372 
00373 
00374 
00375 
00376 
00377 
00378 
00379 unsigned
00380 LogField::unmarshal(char **buf, char *dest, int len)
00381 {
00382   if (m_alias_map == NULL) {
00383     if (m_unmarshal_func == (UnmarshalFunc)LogAccess::unmarshal_str
00384         || m_unmarshal_func == (UnmarshalFunc)LogAccess::unmarshal_http_text) {
00385       UnmarshalFuncWithSlice func = (UnmarshalFuncWithSlice)m_unmarshal_func;
00386       return (*func) (buf, dest, len, &m_slice);
00387     }
00388     return (*m_unmarshal_func) (buf, dest, len);
00389   } else {
00390     return (*m_unmarshal_func_map) (buf, dest, len, m_alias_map);
00391   }
00392 }
00393 
00394 
00395 
00396 
00397 void
00398 LogField::display(FILE *fd)
00399 {
00400   static const char *names[LogField::N_TYPES] = {
00401     "sINT",
00402     "dINT",
00403     "STR",
00404     "IP"
00405   };
00406 
00407   fprintf(fd, "    %30s %10s %5s\n", m_name, m_symbol, names[m_type]);
00408 }
00409 
00410 
00411 
00412 
00413 
00414 
00415 
00416 bool
00417 LogField::operator==(LogField & rhs) {
00418   if (strcmp(name(), rhs.name()) || strcmp(symbol(), rhs.symbol())) {
00419     return false;
00420   } else {
00421     return true;
00422   }
00423 }
00424 
00425 
00426 
00427 void
00428 LogField::set_aggregate_op(LogField::Aggregate agg_op)
00429 {
00430   if (agg_op > 0 && agg_op < LogField::N_AGGREGATES) {
00431     m_agg_op = agg_op;
00432   } else {
00433     Note("Invalid aggregate operator identifier: %d", agg_op);
00434     m_agg_op = NO_AGGREGATE;
00435   }
00436 }
00437 
00438 
00439 void
00440 LogField::update_aggregate(int64_t val)
00441 {
00442   switch (m_agg_op) {
00443 
00444   case eCOUNT:
00445   case eSUM:
00446   case eAVG:
00447     m_agg_val += val;
00448     m_agg_cnt++;
00449     break;
00450 
00451   case eFIRST:
00452     if (m_agg_cnt == 0) {
00453       m_agg_val = val;
00454       m_agg_cnt++;
00455     }
00456     break;
00457 
00458   case eLAST:
00459     m_agg_val = val;
00460     m_agg_cnt++;
00461     break;
00462 
00463   default:
00464     Note("Cannot update aggregate field; invalid operator %d", m_agg_op);
00465     return;
00466   }
00467 
00468   Debug("log-agg", "Aggregate field %s updated with val %" PRId64", "
00469         "new val = %" PRId64", cnt = %" PRId64"", m_symbol, val, m_agg_val, m_agg_cnt);
00470 }
00471 
00472 
00473 LogField::Container LogField::valid_container_name(char *name)
00474 {
00475   for (int i = 1; i < LogField::N_CONTAINERS; i++) {
00476     if (strcmp(name, container_names[i]) == 0) {
00477       return (LogField::Container) i;
00478     }
00479   }
00480   return LogField::NO_CONTAINER;
00481 }
00482 
00483 
00484 LogField::Aggregate LogField::valid_aggregate_name(char *name)
00485 {
00486   for (int i = 1; i < LogField::N_AGGREGATES; i++) {
00487     if (strcmp(name, aggregate_names[i]) == 0) {
00488       return (LogField::Aggregate) i;
00489     }
00490   }
00491   return LogField::NO_AGGREGATE;
00492 }
00493 
00494 
00495 bool LogField::fieldlist_contains_aggregates(char *fieldlist)
00496 {
00497   bool
00498     contains_aggregates = false;
00499   for (int i = 1; i < LogField::N_AGGREGATES; i++) {
00500     if (strstr(fieldlist, aggregate_names[i]) != NULL) {
00501       contains_aggregates = true;
00502     }
00503   }
00504   return contains_aggregates;
00505 }
00506 
00507 
00508 
00509 
00510 
00511 
00512 
00513 
00514 
00515 LogFieldList::LogFieldList()
00516   : m_marshal_len(0)
00517 { }
00518 
00519 LogFieldList::~LogFieldList()
00520 {
00521   clear();
00522 }
00523 
00524 void
00525 LogFieldList::clear()
00526 {
00527   LogField *f;
00528   while ((f = m_field_list.dequeue())) {
00529     delete f;                   
00530   }
00531   m_marshal_len = 0;
00532 }
00533 
00534 void
00535 LogFieldList::add(LogField *field, bool copy)
00536 {
00537   ink_assert(field != NULL);
00538 
00539   if (copy) {
00540     m_field_list.enqueue(new LogField(*field));
00541   } else {
00542     m_field_list.enqueue(field);
00543   }
00544 
00545   if (field->type() == LogField::sINT) {
00546     m_marshal_len += INK_MIN_ALIGN;
00547   }
00548 }
00549 
00550 LogField *
00551 LogFieldList::find_by_name(const char *name) const
00552 {
00553   for (LogField *f = first(); f; f = next(f)) {
00554     if (!strcmp(f->name(), name)) {
00555       return f;
00556     }
00557   }
00558   return NULL;
00559 }
00560 
00561 LogField *
00562 LogFieldList::find_by_symbol(const char *symbol) const
00563 {
00564   LogField *field = 0;
00565 
00566   if (Log::field_symbol_hash) {
00567     if (ink_hash_table_lookup(Log::field_symbol_hash, (char *) symbol, (InkHashTableValue *) & field) && field) {
00568       Debug("log-field-hash", "Field %s found", field->symbol());
00569       return field;
00570     }
00571   }
00572   
00573 
00574   for (field = first(); field; field = next(field)) {
00575     if (!strcmp(field->symbol(), symbol)) {
00576       return field;
00577     }
00578   }
00579 
00580   return NULL;
00581 }
00582 
00583 unsigned
00584 LogFieldList::marshal_len(LogAccess *lad)
00585 {
00586   int bytes = 0;
00587   for (LogField *f = first(); f; f = next(f)) {
00588     if (f->type() != LogField::sINT) {
00589       bytes += f->marshal_len(lad);
00590     }
00591   }
00592   return m_marshal_len + bytes;
00593 }
00594 
00595 unsigned
00596 LogFieldList::marshal(LogAccess *lad, char *buf)
00597 {
00598   char *ptr;
00599   int bytes = 0;
00600   for (LogField *f = first(); f; f = next(f)) {
00601     ptr = &buf[bytes];
00602     bytes += f->marshal(lad, ptr);
00603     ink_assert(bytes % INK_MIN_ALIGN == 0);
00604   }
00605   return bytes;
00606 }
00607 
00608 unsigned
00609 LogFieldList::marshal_agg(char *buf)
00610 {
00611   char *ptr;
00612   int bytes = 0;
00613   for (LogField *f = first(); f; f = next(f)) {
00614     ptr = &buf[bytes];
00615     bytes += f->marshal_agg(ptr);
00616   }
00617   return bytes;
00618 }
00619 
00620 unsigned
00621 LogFieldList::count()
00622 {
00623   unsigned cnt = 0;
00624   for (LogField *f = first(); f; f = next(f)) {
00625     cnt++;
00626   }
00627   return cnt;
00628 }
00629 
00630 void
00631 LogFieldList::display(FILE *fd)
00632 {
00633   for (LogField *f = first(); f; f = next(f)) {
00634     f->display(fd);
00635   }
00636 }