• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

RecCore.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   Record core definitions
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 #include "libts.h"
00025 
00026 #include "P_RecFile.h"
00027 #include "P_RecCore.h"
00028 #include "P_RecUtils.h"
00029 #include "P_RecTree.h"
00030 #include "I_Layout.h"
00031 
00032 static bool g_initialized = false;
00033 
00034 RecRecord *g_records = NULL;
00035 InkHashTable *g_records_ht = NULL;
00036 ink_rwlock g_records_rwlock;
00037 int g_num_records = 0;
00038 
00039 RecTree *g_records_tree = NULL;
00040 
00041 //-------------------------------------------------------------------------
00042 // register_record
00043 //-------------------------------------------------------------------------
00044 static RecRecord *
00045 register_record(RecT rec_type, const char *name, RecDataT data_type, RecData data_default, RecPersistT persist_type)
00046 {
00047   RecRecord *r = NULL;
00048 
00049   if (ink_hash_table_lookup(g_records_ht, name, (void **) &r)) {
00050     ink_release_assert(r->rec_type == rec_type);
00051     ink_release_assert(r->data_type == data_type);
00052     // Note: do not set r->data as we want to keep the previous value
00053     RecDataSet(r->data_type, &(r->data_default), &(data_default));
00054   } else {
00055     if ((r = RecAlloc(rec_type, name, data_type)) == NULL) {
00056       return NULL;
00057     }
00058     // Set the r->data to its default value as this is a new record
00059     RecDataSet(r->data_type, &(r->data), &(data_default));
00060     RecDataSet(r->data_type, &(r->data_default), &(data_default));
00061     ink_hash_table_insert(g_records_ht, name, (void *) r);
00062 
00063     if (REC_TYPE_IS_STAT(r->rec_type)) {
00064       r->stat_meta.persist_type = persist_type;
00065     }
00066   }
00067 
00068   // we're now registered
00069   r->registered = true;
00070   r->version = 0;
00071 
00072   return r;
00073 }
00074 
00075 
00076 //-------------------------------------------------------------------------
00077 // link_XXX
00078 //-------------------------------------------------------------------------
00079 static int
00080 link_int(const char * /* name */, RecDataT /* data_type */, RecData data, void *cookie)
00081 {
00082   RecInt *rec_int = (RecInt *) cookie;
00083   ink_atomic_swap(rec_int, data.rec_int);
00084   return REC_ERR_OKAY;
00085 }
00086 
00087 static int
00088 link_int32(const char * /* name */, RecDataT /* data_type */, RecData data, void *cookie)
00089 {
00090   *((int32_t *) cookie) = (int32_t) data.rec_int;
00091   return REC_ERR_OKAY;
00092 }
00093 
00094 static int
00095 link_uint32(const char * /* name */, RecDataT /* data_type */, RecData data, void *cookie)
00096 {
00097   *((uint32_t *) cookie) = (uint32_t) data.rec_int;
00098   return REC_ERR_OKAY;
00099 }
00100 
00101 static int
00102 link_float(const char * /* name */, RecDataT /* data_type */, RecData data, void *cookie)
00103 {
00104   *((RecFloat *) cookie) = data.rec_float;
00105   return REC_ERR_OKAY;
00106 }
00107 
00108 static int
00109 link_counter(const char * /* name */, RecDataT /* data_type */, RecData data, void *cookie)
00110 {
00111   RecCounter *rec_counter = (RecCounter *) cookie;
00112   ink_atomic_swap(rec_counter, data.rec_counter);
00113   return REC_ERR_OKAY;
00114 }
00115 
00116 // This is a convenience wrapper, to allow us to treat the RecInt's as a
00117 // 1-byte entity internally.
00118 static int
00119 link_byte(const char * /* name */, RecDataT /* data_type */, RecData data, void *cookie)
00120 {
00121   RecByte *rec_byte = (RecByte *) cookie;
00122   RecByte byte = static_cast<RecByte>(data.rec_int);
00123 
00124   ink_atomic_swap(rec_byte, byte);
00125   return REC_ERR_OKAY;
00126 }
00127 
00128 // mimic Config.cc::config_string_alloc_cb
00129 // cookie e.g. is the DEFAULT_xxx_str value which this functiion keeps up to date with
00130 // the latest default applied during a config update from records.config
00131 static int
00132 link_string_alloc(const char * /* name */, RecDataT /* data_type */, RecData data, void *cookie)
00133 {
00134   RecString _ss = data.rec_string;
00135   RecString _new_value = NULL;
00136 
00137   if (_ss) {
00138     _new_value = ats_strdup(_ss);
00139   }
00140 
00141   // set new string for DEFAULT_xxx_str tp point to
00142   RecString _temp2 = *((RecString *)cookie);
00143   *((RecString *)cookie) = _new_value;
00144   // free previous string DEFAULT_xxx_str points to
00145   ats_free(_temp2);
00146 
00147   return REC_ERR_OKAY;
00148 }
00149 
00150 //-------------------------------------------------------------------------
00151 // RecCoreInit
00152 //-------------------------------------------------------------------------
00153 int
00154 RecCoreInit(RecModeT mode_type, Diags *_diags)
00155 {
00156   if (g_initialized) {
00157     return REC_ERR_OKAY;
00158   }
00159 
00160   // set our diags
00161   RecSetDiags(_diags);
00162 
00163   // Initialize config file parsing data structures.
00164   RecConfigFileInit();
00165 
00166   g_records_tree = new RecTree(NULL);
00167   g_num_records = 0;
00168 
00169   // initialize record array for our internal stats (this can be reallocated later)
00170   g_records = (RecRecord *)ats_malloc(REC_MAX_RECORDS * sizeof(RecRecord));
00171 
00172   // initialize record hash index
00173   g_records_ht = ink_hash_table_create(InkHashTableKeyType_String);
00174   ink_rwlock_init(&g_records_rwlock);
00175   if (!g_records_ht) {
00176     return REC_ERR_FAIL;
00177   }
00178   // read stats
00179   if ((mode_type == RECM_SERVER) || (mode_type == RECM_STAND_ALONE)) {
00180     RecReadStatsFile();
00181   }
00182   // read configs
00183   if ((mode_type == RECM_SERVER) || (mode_type == RECM_STAND_ALONE)) {
00184     ink_mutex_init(&g_rec_config_lock, NULL);
00185     // Import the file into memory; try the following in this order:
00186     // ./etc/trafficserver/records.config.shadow
00187     // ./records.config.shadow
00188     // ./etc/trafficserver/records.config
00189     // ./records.config
00190     bool file_exists = true;
00191     g_rec_config_fpath = Layout::relative_to(Layout::get()->sysconfdir, REC_CONFIG_FILE REC_SHADOW_EXT);
00192     if (RecFileExists(g_rec_config_fpath) == REC_ERR_FAIL) {
00193       ats_free((char *)g_rec_config_fpath);
00194       g_rec_config_fpath = Layout::relative_to(Layout::get()->sysconfdir, REC_CONFIG_FILE);
00195       if (RecFileExists(g_rec_config_fpath) == REC_ERR_FAIL) {
00196         RecLog(DL_Warning, "Could not find '%s', system will run with defaults\n", REC_CONFIG_FILE);
00197         file_exists = false;
00198       }
00199     }
00200     if (file_exists) {
00201       RecReadConfigFile(true);
00202     }
00203   }
00204 
00205   g_initialized = true;
00206 
00207   return REC_ERR_OKAY;
00208 }
00209 
00210 //-------------------------------------------------------------------------
00211 // RecLinkCnfigXXX
00212 //-------------------------------------------------------------------------
00213 int
00214 RecLinkConfigInt(const char *name, RecInt * rec_int)
00215 {
00216   if (RecGetRecordInt(name, rec_int) == REC_ERR_FAIL) {
00217     return REC_ERR_FAIL;
00218   }
00219   return RecRegisterConfigUpdateCb(name, link_int, (void *) rec_int);
00220 }
00221 
00222 int
00223 RecLinkConfigInt32(const char *name, int32_t * p_int32)
00224 {
00225   return RecRegisterConfigUpdateCb(name, link_int32, (void *) p_int32);
00226 }
00227 
00228 int
00229 RecLinkConfigUInt32(const char *name, uint32_t * p_uint32)
00230 {
00231   return RecRegisterConfigUpdateCb(name, link_uint32, (void *) p_uint32);
00232 }
00233 
00234 int
00235 RecLinkConfigFloat(const char *name, RecFloat * rec_float)
00236 {
00237   if (RecGetRecordFloat(name, rec_float) == REC_ERR_FAIL) {
00238     return REC_ERR_FAIL;
00239   }
00240   return RecRegisterConfigUpdateCb(name, link_float, (void *) rec_float);
00241 }
00242 
00243 int
00244 RecLinkConfigCounter(const char *name, RecCounter * rec_counter)
00245 {
00246   if (RecGetRecordCounter(name, rec_counter) == REC_ERR_FAIL) {
00247     return REC_ERR_FAIL;
00248   }
00249   return RecRegisterConfigUpdateCb(name, link_counter, (void *) rec_counter);
00250 }
00251 
00252 int
00253 RecLinkConfigString(const char *name, RecString * rec_string)
00254 {
00255   if (RecGetRecordString_Xmalloc(name, rec_string) == REC_ERR_FAIL) {
00256     return REC_ERR_FAIL;
00257   }
00258   return RecRegisterConfigUpdateCb(name, link_string_alloc, (void *) rec_string);
00259 }
00260 
00261 int
00262 RecLinkConfigByte(const char *name, RecByte * rec_byte)
00263 {
00264   if (RecGetRecordByte(name, rec_byte) == REC_ERR_FAIL) {
00265     return REC_ERR_FAIL;
00266   }
00267   return RecRegisterConfigUpdateCb(name, link_byte, (void *) rec_byte);
00268 }
00269 
00270 int
00271 RecLinkConfigBool(const char *name, RecBool * rec_bool)
00272 {
00273   if (RecGetRecordBool(name, rec_bool) == REC_ERR_FAIL) {
00274     return REC_ERR_FAIL;
00275   }
00276   return RecRegisterConfigUpdateCb(name, link_byte, (void *) rec_bool);
00277 }
00278 
00279 
00280 //-------------------------------------------------------------------------
00281 // RecRegisterConfigUpdateCb
00282 //-------------------------------------------------------------------------
00283 int
00284 RecRegisterConfigUpdateCb(const char *name, RecConfigUpdateCb update_cb, void *cookie)
00285 {
00286   int err = REC_ERR_FAIL;
00287   RecRecord *r;
00288 
00289   ink_rwlock_rdlock(&g_records_rwlock);
00290 
00291   if (ink_hash_table_lookup(g_records_ht, name, (void **) &r)) {
00292     rec_mutex_acquire(&(r->lock));
00293     if (REC_TYPE_IS_CONFIG(r->rec_type)) {
00294       /* -- upgrade to support a list of callback functions
00295          if (!(r->config_meta.update_cb)) {
00296          r->config_meta.update_cb = update_cb;
00297          r->config_meta.update_cookie = cookie;
00298          err = REC_ERR_OKAY;
00299          }
00300        */
00301 
00302       RecConfigUpdateCbList *new_callback = (RecConfigUpdateCbList *)ats_malloc(sizeof(RecConfigUpdateCbList));
00303       memset(new_callback, 0, sizeof(RecConfigUpdateCbList));
00304       new_callback->update_cb = update_cb;
00305       new_callback->update_cookie = cookie;
00306 
00307       new_callback->next = NULL;
00308 
00309       ink_assert(new_callback);
00310       if (!r->config_meta.update_cb_list) {
00311         r->config_meta.update_cb_list = new_callback;
00312       } else {
00313         RecConfigUpdateCbList *cur_callback = NULL;
00314         RecConfigUpdateCbList *prev_callback = NULL;
00315         for (cur_callback = r->config_meta.update_cb_list; cur_callback; cur_callback = cur_callback->next) {
00316           prev_callback = cur_callback;
00317         }
00318         ink_assert(prev_callback);
00319         ink_assert(!prev_callback->next);
00320         prev_callback->next = new_callback;
00321       }
00322       err = REC_ERR_OKAY;
00323     }
00324 
00325     rec_mutex_release(&(r->lock));
00326   }
00327 
00328   ink_rwlock_unlock(&g_records_rwlock);
00329 
00330   return err;
00331 }
00332 
00333 
00334 //-------------------------------------------------------------------------
00335 // RecGetRecordXXX
00336 //-------------------------------------------------------------------------
00337 int
00338 RecGetRecordInt(const char *name, RecInt *rec_int, bool lock)
00339 {
00340   int err;
00341   RecData data;
00342   if ((err = RecGetRecord_Xmalloc(name, RECD_INT, &data, lock)) == REC_ERR_OKAY)
00343     *rec_int = data.rec_int;
00344   return err;
00345 }
00346 
00347 int
00348 RecGetRecordFloat(const char *name, RecFloat * rec_float, bool lock)
00349 {
00350   int err;
00351   RecData data;
00352   if ((err = RecGetRecord_Xmalloc(name, RECD_FLOAT, &data, lock)) == REC_ERR_OKAY)
00353     *rec_float = data.rec_float;
00354   return err;
00355 }
00356 
00357 int
00358 RecGetRecordString(const char *name, char *buf, int buf_len, bool lock)
00359 {
00360   int err = REC_ERR_OKAY;
00361   RecRecord *r;
00362   if (lock) {
00363     ink_rwlock_rdlock(&g_records_rwlock);
00364   }
00365   if (ink_hash_table_lookup(g_records_ht, name, (void **) &r)) {
00366     rec_mutex_acquire(&(r->lock));
00367     if (!r->registered || (r->data_type != RECD_STRING)) {
00368       err = REC_ERR_FAIL;
00369     } else {
00370       if (r->data.rec_string == NULL) {
00371         buf[0] = '\0';
00372       } else {
00373         ink_strlcpy(buf, r->data.rec_string, buf_len);
00374       }
00375     }
00376     rec_mutex_release(&(r->lock));
00377   } else {
00378     err = REC_ERR_FAIL;
00379   }
00380   if (lock) {
00381     ink_rwlock_unlock(&g_records_rwlock);
00382   }
00383   return err;
00384 }
00385 
00386 int
00387 RecGetRecordString_Xmalloc(const char *name, RecString * rec_string, bool lock)
00388 {
00389   int err;
00390   RecData data;
00391   if ((err = RecGetRecord_Xmalloc(name, RECD_STRING, &data, lock)) == REC_ERR_OKAY)
00392     *rec_string = data.rec_string;
00393   return err;
00394 }
00395 
00396 int
00397 RecGetRecordCounter(const char *name, RecCounter * rec_counter, bool lock)
00398 {
00399   int err;
00400   RecData data;
00401   if ((err = RecGetRecord_Xmalloc(name, RECD_COUNTER, &data, lock)) == REC_ERR_OKAY)
00402     *rec_counter = data.rec_counter;
00403   return err;
00404 }
00405 
00406 int
00407 RecGetRecordByte(const char *name, RecByte *rec_byte, bool lock)
00408 {
00409   int err;
00410   RecData data;
00411   if ((err = RecGetRecord_Xmalloc(name, RECD_INT, &data, lock)) == REC_ERR_OKAY)
00412     *rec_byte = data.rec_int;
00413   return err;
00414 }
00415 
00416 int
00417 RecGetRecordBool(const char *name, RecBool *rec_bool, bool lock)
00418 {
00419   int err;
00420   RecData data;
00421   if ((err = RecGetRecord_Xmalloc(name, RECD_INT, &data, lock)) == REC_ERR_OKAY)
00422     *rec_bool = 0 != data.rec_int;
00423   return err;
00424 }
00425 
00426 //-------------------------------------------------------------------------
00427 // RecGetRec Attributes
00428 //-------------------------------------------------------------------------
00429 int
00430 RecGetRecordType(const char *name, RecT * rec_type, bool lock)
00431 {
00432   int err = REC_ERR_FAIL;
00433   RecRecord *r;
00434 
00435   if (lock) {
00436     ink_rwlock_rdlock(&g_records_rwlock);
00437   }
00438 
00439   if (ink_hash_table_lookup(g_records_ht, name, (void **) &r)) {
00440     rec_mutex_acquire(&(r->lock));
00441     *rec_type = r->rec_type;
00442     err = REC_ERR_OKAY;
00443     rec_mutex_release(&(r->lock));
00444   }
00445 
00446   if (lock) {
00447     ink_rwlock_unlock(&g_records_rwlock);
00448   }
00449 
00450   return err;
00451 }
00452 
00453 
00454 int
00455 RecGetRecordDataType(const char *name, RecDataT * data_type, bool lock)
00456 {
00457   int err = REC_ERR_FAIL;
00458   RecRecord *r = NULL;
00459 
00460   if (lock) {
00461     ink_rwlock_rdlock(&g_records_rwlock);
00462   }
00463 
00464   if (ink_hash_table_lookup(g_records_ht, name, (void **) &r)) {
00465     rec_mutex_acquire(&(r->lock));
00466     if (!r->registered) {
00467       err = REC_ERR_FAIL;
00468     } else {
00469       *data_type = r->data_type;
00470       err = REC_ERR_OKAY;
00471     }
00472     rec_mutex_release(&(r->lock));
00473   }
00474 
00475   if (lock) {
00476     ink_rwlock_unlock(&g_records_rwlock);
00477   }
00478 
00479   return err;
00480 }
00481 
00482 int
00483 RecGetRecordPersistenceType(const char *name, RecPersistT * persist_type, bool lock)
00484 {
00485   int err = REC_ERR_FAIL;
00486   RecRecord *r = NULL;
00487 
00488   if (lock) {
00489     ink_rwlock_rdlock(&g_records_rwlock);
00490   }
00491 
00492   *persist_type = RECP_NULL;
00493 
00494   if (ink_hash_table_lookup(g_records_ht, name, (void **) &r)) {
00495     rec_mutex_acquire(&(r->lock));
00496     if (REC_TYPE_IS_STAT(r->rec_type)) {
00497       *persist_type = r->stat_meta.persist_type;
00498       err = REC_ERR_OKAY;
00499     }
00500     rec_mutex_release(&(r->lock));
00501   }
00502 
00503   if (lock) {
00504     ink_rwlock_unlock(&g_records_rwlock);
00505   }
00506 
00507   return err;
00508 }
00509 
00510 int
00511 RecGetRecordOrderAndId(const char *name, int* order, int* id, bool lock)
00512 {
00513   int err = REC_ERR_FAIL;
00514   RecRecord *r = NULL;
00515 
00516   if (lock) {
00517     ink_rwlock_rdlock(&g_records_rwlock);
00518   }
00519 
00520   if (ink_hash_table_lookup(g_records_ht, name, (void **) &r)) {
00521     if (r->registered) {
00522       rec_mutex_acquire(&(r->lock));
00523       if (order)
00524         *order = r->order;
00525       if (id)
00526         *id = r->rsb_id;
00527       err = REC_ERR_OKAY;
00528       rec_mutex_release(&(r->lock));
00529     }
00530   }
00531 
00532   if (lock) {
00533     ink_rwlock_unlock(&g_records_rwlock);
00534   }
00535 
00536   return err;
00537 }
00538 
00539 int
00540 RecGetRecordUpdateType(const char *name, RecUpdateT *update_type, bool lock)
00541 {
00542   int err = REC_ERR_FAIL;
00543   RecRecord *r = NULL;
00544 
00545   if (lock) {
00546     ink_rwlock_rdlock(&g_records_rwlock);
00547   }
00548 
00549   if (ink_hash_table_lookup(g_records_ht, name, (void **) &r)) {
00550     rec_mutex_acquire(&(r->lock));
00551     if (REC_TYPE_IS_CONFIG(r->rec_type)) {
00552       *update_type = r->config_meta.update_type;
00553       err = REC_ERR_OKAY;
00554     } else {
00555       ink_assert(!"rec_type is not CONFIG");
00556     }
00557     rec_mutex_release(&(r->lock));
00558   }
00559 
00560   if (lock) {
00561     ink_rwlock_unlock(&g_records_rwlock);
00562   }
00563 
00564   return err;
00565 }
00566 
00567 
00568 int
00569 RecGetRecordCheckType(const char *name, RecCheckT *check_type, bool lock)
00570 {
00571   int err = REC_ERR_FAIL;
00572   RecRecord *r = NULL;
00573 
00574   if (lock) {
00575     ink_rwlock_rdlock(&g_records_rwlock);
00576   }
00577 
00578   if (ink_hash_table_lookup(g_records_ht, name, (void **) &r)) {
00579     rec_mutex_acquire(&(r->lock));
00580     if (REC_TYPE_IS_CONFIG(r->rec_type)) {
00581       *check_type = r->config_meta.check_type;
00582       err = REC_ERR_OKAY;
00583     } else {
00584       ink_assert(!"rec_type is not CONFIG");
00585     }
00586     rec_mutex_release(&(r->lock));
00587   }
00588 
00589   if (lock) {
00590     ink_rwlock_unlock(&g_records_rwlock);
00591   }
00592 
00593   return err;
00594 }
00595 
00596 
00597 int
00598 RecGetRecordCheckExpr(const char *name, char **check_expr, bool lock)
00599 {
00600   int err = REC_ERR_FAIL;
00601   RecRecord *r = NULL;
00602 
00603   if (lock) {
00604     ink_rwlock_rdlock(&g_records_rwlock);
00605   }
00606 
00607   if (ink_hash_table_lookup(g_records_ht, name, (void **) &r)) {
00608     rec_mutex_acquire(&(r->lock));
00609     if (REC_TYPE_IS_CONFIG(r->rec_type)) {
00610       *check_expr = r->config_meta.check_expr;
00611       err = REC_ERR_OKAY;
00612     } else {
00613       ink_assert(!"rec_type is not CONFIG");
00614     }
00615     rec_mutex_release(&(r->lock));
00616   }
00617 
00618   if (lock) {
00619     ink_rwlock_unlock(&g_records_rwlock);
00620   }
00621 
00622   return err;
00623 }
00624 
00625 int
00626 RecGetRecordDefaultDataString_Xmalloc(char *name, char **buf, bool lock)
00627 {
00628   int err;
00629   RecRecord *r = NULL;
00630 
00631   if (lock) {
00632     ink_rwlock_rdlock(&g_records_rwlock);
00633   }
00634 
00635   if (ink_hash_table_lookup(g_records_ht, name, (void **) &r)) {
00636     *buf = (char *)ats_malloc(sizeof(char) * 1024);
00637     memset(*buf, 0, 1024);
00638     err = REC_ERR_OKAY;
00639 
00640     switch (r->data_type) {
00641     case RECD_INT:
00642       snprintf(*buf, 1023, "%" PRId64 "", r->data_default.rec_int);
00643       break;
00644     case RECD_FLOAT:
00645       snprintf(*buf, 1023, "%f", r->data_default.rec_float);
00646       break;
00647     case RECD_STRING:
00648       if (r->data_default.rec_string) {
00649         ink_strlcpy(*buf, r->data_default.rec_string, 1024);
00650       } else {
00651         ats_free(*buf);
00652         *buf = NULL;
00653       }
00654       break;
00655     case RECD_COUNTER:
00656       snprintf(*buf, 1023, "%" PRId64 "", r->data_default.rec_counter);
00657       break;
00658     default:
00659       ink_assert(!"Unexpected RecD type");
00660       ats_free(*buf);
00661       *buf = NULL;
00662       break;
00663     }
00664   } else {
00665     err = REC_ERR_FAIL;
00666   }
00667 
00668   if (lock) {
00669     ink_rwlock_unlock(&g_records_rwlock);
00670   }
00671 
00672   return err;
00673 }
00674 
00675 
00676 int
00677 RecGetRecordAccessType(const char *name, RecAccessT *access, bool lock)
00678 {
00679   int err = REC_ERR_FAIL;
00680   RecRecord *r = NULL;
00681 
00682   if (lock) {
00683     ink_rwlock_rdlock(&g_records_rwlock);
00684   }
00685 
00686   if (ink_hash_table_lookup(g_records_ht, name, (void **) &r)) {
00687     rec_mutex_acquire(&(r->lock));
00688     *access = r->config_meta.access_type;
00689     err = REC_ERR_OKAY;
00690     rec_mutex_release(&(r->lock));
00691   }
00692 
00693   if (lock) {
00694     ink_rwlock_unlock(&g_records_rwlock);
00695   }
00696 
00697   return err;
00698 }
00699 
00700 
00701 int
00702 RecSetRecordAccessType(const char *name, RecAccessT access, bool lock)
00703 {
00704   int err = REC_ERR_FAIL;
00705   RecRecord *r = NULL;
00706 
00707   if (lock) {
00708     ink_rwlock_rdlock(&g_records_rwlock);
00709   }
00710 
00711   if (ink_hash_table_lookup(g_records_ht, name, (void **) &r)) {
00712     rec_mutex_acquire(&(r->lock));
00713     r->config_meta.access_type = access;
00714     err = REC_ERR_OKAY;
00715     rec_mutex_release(&(r->lock));
00716   }
00717 
00718   if (lock) {
00719     ink_rwlock_unlock(&g_records_rwlock);
00720   }
00721 
00722   return err;
00723 }
00724 
00725 
00726 //-------------------------------------------------------------------------
00727 // RecRegisterStat
00728 //-------------------------------------------------------------------------
00729 RecRecord *
00730 RecRegisterStat(RecT rec_type, const char *name, RecDataT data_type, RecData data_default, RecPersistT persist_type)
00731 {
00732   RecRecord *r = NULL;
00733 
00734   ink_rwlock_wrlock(&g_records_rwlock);
00735   if ((r = register_record(rec_type, name, data_type, data_default, persist_type)) != NULL) {
00736     // If the persistence type we found in the records hash is not the same as the persistence
00737     // type we are registering, then that means that it changed between the previous software
00738     // version and the current version. If the metric changed to non-persistent, reset to the
00739     // new default value.
00740     if ((r->stat_meta.persist_type == RECP_NULL ||r->stat_meta.persist_type == RECP_PERSISTENT) &&
00741         persist_type == RECP_NON_PERSISTENT) {
00742       RecDebug(DL_Debug, "resetting default value for formerly persisted stat '%s'", r->name);
00743       RecDataSet(r->data_type, &(r->data), &(data_default));
00744     }
00745 
00746     r->stat_meta.persist_type = persist_type;
00747   } else {
00748     ink_assert(!"Can't register record!");
00749     RecDebug(DL_Warning, "failed to register '%s' record", name);
00750   }
00751   ink_rwlock_unlock(&g_records_rwlock);
00752 
00753   return r;
00754 }
00755 
00756 
00757 //-------------------------------------------------------------------------
00758 // RecRegisterConfig
00759 //-------------------------------------------------------------------------
00760 RecRecord *
00761 RecRegisterConfig(RecT rec_type, const char *name, RecDataT data_type,
00762                   RecData data_default, RecUpdateT update_type,
00763                   RecCheckT check_type, const char *check_expr, RecAccessT access_type)
00764 {
00765   RecRecord *r;
00766   ink_rwlock_wrlock(&g_records_rwlock);
00767   if ((r = register_record(rec_type, name, data_type, data_default, RECP_NULL)) != NULL) {
00768     // Note: do not modify 'record->config_meta.update_required'
00769     r->config_meta.update_type = update_type;
00770     r->config_meta.check_type = check_type;
00771     if (r->config_meta.check_expr) {
00772       ats_free(r->config_meta.check_expr);
00773     }
00774     r->config_meta.check_expr = ats_strdup(check_expr);
00775     r->config_meta.update_cb_list = NULL;
00776     r->config_meta.access_type = access_type;
00777   }
00778   ink_rwlock_unlock(&g_records_rwlock);
00779 
00780   return r;
00781 }
00782 
00783 
00784 //-------------------------------------------------------------------------
00785 // RecGetRecord_Xmalloc
00786 //-------------------------------------------------------------------------
00787 int
00788 RecGetRecord_Xmalloc(const char *name, RecDataT data_type, RecData *data, bool lock)
00789 {
00790   int err = REC_ERR_OKAY;
00791   RecRecord *r;
00792 
00793   if (lock) {
00794     ink_rwlock_rdlock(&g_records_rwlock);
00795   }
00796 
00797   if (ink_hash_table_lookup(g_records_ht, name, (void **) &r)) {
00798     rec_mutex_acquire(&(r->lock));
00799     if (!r->registered || (r->data_type != data_type)) {
00800       err = REC_ERR_FAIL;
00801     } else {
00802       // Clear the caller's record just in case it has trash in it.
00803       // Passing trashy records to RecDataSet will cause confusion.
00804       memset(data, 0, sizeof(RecData));
00805       RecDataSet(data_type, data, &(r->data));
00806     }
00807     rec_mutex_release(&(r->lock));
00808   } else {
00809     err = REC_ERR_FAIL;
00810   }
00811 
00812   if (lock) {
00813     ink_rwlock_unlock(&g_records_rwlock);
00814   }
00815 
00816   return err;
00817 }
00818 
00819 
00820 //-------------------------------------------------------------------------
00821 // RecForceInsert
00822 //-------------------------------------------------------------------------
00823 RecRecord *
00824 RecForceInsert(RecRecord * record)
00825 {
00826   RecRecord *r = NULL;
00827   bool r_is_a_new_record;
00828 
00829   ink_rwlock_wrlock(&g_records_rwlock);
00830 
00831   if (ink_hash_table_lookup(g_records_ht, record->name, (void **) &r)) {
00832     r_is_a_new_record = false;
00833     rec_mutex_acquire(&(r->lock));
00834     r->rec_type = record->rec_type;
00835     r->data_type = record->data_type;
00836   } else {
00837     r_is_a_new_record = true;
00838     if ((r = RecAlloc(record->rec_type, record->name, record->data_type)) == NULL) {
00839       ink_rwlock_unlock(&g_records_rwlock);
00840       return NULL;
00841     }
00842   }
00843 
00844   // set the record value
00845   RecDataSet(r->data_type, &(r->data), &(record->data));
00846   RecDataSet(r->data_type, &(r->data_default), &(record->data_default));
00847 
00848   r->registered = record->registered;
00849   r->rsb_id = record->rsb_id;
00850 
00851   if (REC_TYPE_IS_STAT(r->rec_type)) {
00852     r->stat_meta.persist_type = record->stat_meta.persist_type;
00853     r->stat_meta.data_raw = record->stat_meta.data_raw;
00854   } else if (REC_TYPE_IS_CONFIG(r->rec_type)) {
00855     r->config_meta.update_required = record->config_meta.update_required;
00856     r->config_meta.update_type = record->config_meta.update_type;
00857     r->config_meta.check_type = record->config_meta.check_type;
00858     ats_free(r->config_meta.check_expr);
00859     r->config_meta.check_expr = ats_strdup(record->config_meta.check_expr);
00860     r->config_meta.access_type = record->config_meta.access_type;
00861   }
00862 
00863   if (r_is_a_new_record) {
00864     ink_hash_table_insert(g_records_ht, r->name, (void *) r);
00865   } else {
00866     rec_mutex_release(&(r->lock));
00867   }
00868 
00869   ink_rwlock_unlock(&g_records_rwlock);
00870 
00871   return r;
00872 }
00873 
00874 
00875 //-------------------------------------------------------------------------
00876 // RecDumpRecordsHt
00877 //-------------------------------------------------------------------------
00878 
00879 static void
00880 debug_record_callback(RecT /* rec_type */, void * /* edata */, int registered, const char *name, int data_type, RecData *datum)
00881 {
00882   switch(data_type) {
00883   case RECD_INT:
00884     RecDebug(DL_Note, "  ([%d] '%s', '%" PRId64 "')", registered, name, datum->rec_int);
00885     break;
00886   case RECD_FLOAT:
00887     RecDebug(DL_Note, "  ([%d] '%s', '%f')", registered, name, datum->rec_float);
00888     break;
00889   case RECD_STRING:
00890     RecDebug(DL_Note, "  ([%d] '%s', '%s')",
00891              registered, name, datum->rec_string ? datum->rec_string : "NULL");
00892     break;
00893   case RECD_COUNTER:
00894     RecDebug(DL_Note, "  ([%d] '%s', '%" PRId64 "')", registered, name, datum->rec_counter);
00895     break;
00896   default:
00897     RecDebug(DL_Note, "  ([%d] '%s', <? ? ?>)", registered, name);
00898     break;
00899   }
00900 }
00901 void
00902 RecDumpRecords(RecT rec_type, RecDumpEntryCb callback, void *edata)
00903 {
00904   int i, num_records;
00905 
00906   num_records = g_num_records;
00907   for (i = 0; i < num_records; i++) {
00908     RecRecord *r = &(g_records[i]);
00909     if ((rec_type == RECT_NULL) || (rec_type & r->rec_type)) {
00910       rec_mutex_acquire(&(r->lock));
00911       callback(rec_type, edata, r->registered, r->name, r->data_type, &r->data);
00912       rec_mutex_release(&(r->lock));
00913     }
00914   }
00915 }
00916 
00917 void
00918 RecDumpRecordsHt(RecT rec_type) {
00919   RecDebug(DL_Note, "Dumping Records:");
00920   RecDumpRecords(rec_type, debug_record_callback, NULL);
00921 }
00922 
00923 void
00924 RecGetRecordTree(char *subtree)
00925 {
00926   RecTree *tree = g_records_tree;
00927   if (subtree) {
00928     tree = tree->rec_tree_get(subtree);
00929   }
00930   tree->print();
00931 }
00932 
00933 void
00934 RecGetRecordList(char *var, char ***buffer, int *count)
00935 {
00936   g_records_tree->rec_tree_get_list(&(*var), &(*buffer), &(*count));
00937 }
00938 
00939 
00940 //-------------------------------------------------------------------------
00941 // RecGetRecordPrefix_Xmalloc
00942 //
00943 //     mimics/replaces proxy/StatSystem.cc::stat_callback().
00944 //     returns the number of variables name match the prefix.
00945 //-------------------------------------------------------------------------
00946 int
00947 RecGetRecordPrefix_Xmalloc(char *prefix, char **buf, int *buf_len)
00948 {
00949   int num_records = g_num_records;
00950   int result_size = num_records * 256;  /* estimate buffer size */
00951   int num_matched = 0;
00952   char *result = NULL;
00953 
00954   result = (char *)ats_malloc(result_size * sizeof(char));
00955   memset(result, 0, result_size * sizeof(char));
00956 
00957   int i;
00958   int total_bytes_written = 0;
00959   int error = 0;
00960   for (i = 0; !error && i < num_records; i++) {
00961     int bytes_written = 0;
00962     int bytes_avail = result_size - total_bytes_written;
00963     RecRecord *r = &(g_records[i]);
00964     if (strncmp(prefix, r->name, strlen(prefix)) == 0) {
00965       rec_mutex_acquire(&(r->lock));
00966       switch (r->data_type) {
00967       case RECD_INT:
00968         num_matched++;
00969         bytes_written = snprintf(result + total_bytes_written, bytes_avail, "%s=%" PRId64 "\r\n", r->name, r->data.rec_int);
00970         break;
00971       case RECD_FLOAT:
00972         num_matched++;
00973         bytes_written = snprintf(result + total_bytes_written, bytes_avail, "%s=%f\r\n", r->name, r->data.rec_float);
00974         break;
00975       case RECD_STRING:
00976         num_matched++;
00977         bytes_written = snprintf(result + total_bytes_written, bytes_avail, "%s=%s\r\n", r->name, r->data.rec_string ? r->data.rec_string : "NULL");
00978         break;
00979       case RECD_COUNTER:
00980         num_matched++;
00981         bytes_written = snprintf(result + total_bytes_written, bytes_avail, "%s=%" PRId64 "\r\n", r->name, r->data.rec_int);
00982         break;
00983       default:
00984         break;
00985       }
00986 
00987       if(bytes_written <= 0 || bytes_written > bytes_avail) {
00988         error = 1;
00989       } else
00990         total_bytes_written += bytes_written;
00991 
00992       rec_mutex_release(&(r->lock));
00993     }
00994   }
00995 
00996   if(error || total_bytes_written == result_size) {
00997     RecLog(DL_Error, "Stat system was unable to fully generate stat list, size exceeded limit of %d", result_size);
00998   }
00999 
01000   *buf = result;
01001   *buf_len = strlen(result);
01002 
01003   return num_matched;
01004 }
01005 
01006 
01007 //-------------------------------------------------------------------------
01008 // Backwards compatibility ... TODO: Should eliminate these
01009 //-------------------------------------------------------------------------
01010 RecInt
01011 REC_ConfigReadInteger(const char *name)
01012 {
01013   RecInt t = 0;
01014   RecGetRecordInt(name, &t);
01015   return t;
01016 }
01017 
01018 char *
01019 REC_ConfigReadString(const char *name)
01020 {
01021   char *t = 0;
01022   RecGetRecordString_Xmalloc(name, (RecString *) & t);
01023   return t;
01024 }
01025 
01026 RecFloat
01027 REC_ConfigReadFloat(const char *name)
01028 {
01029   RecFloat t = 0;
01030   RecGetRecordFloat(name, (RecFloat *) & t);
01031   return t;
01032 }
01033 
01034 RecCounter
01035 REC_ConfigReadCounter(const char *name)
01036 {
01037   RecCounter t = 0;
01038   RecGetRecordCounter(name, (RecCounter *) & t);
01039   return t;
01040 }
01041 
01042 
01043 //-------------------------------------------------------------------------
01044 // Backwards compatibility. TODO: Should remove these.
01045 //-------------------------------------------------------------------------
01046 RecInt
01047 REC_readInteger(const char *name, bool * found, bool lock)
01048 {
01049   ink_assert(name);
01050   RecInt _tmp = 0;
01051   bool _found;
01052   _found = (RecGetRecordInt(name, &_tmp, lock) == REC_ERR_OKAY);
01053   if (found)
01054     *found = _found;
01055   return _tmp;
01056 }
01057 
01058 RecFloat
01059 REC_readFloat(char *name, bool * found, bool lock)
01060 {
01061   ink_assert(name);
01062   RecFloat _tmp = 0.0;
01063   bool _found;
01064   _found = (RecGetRecordFloat(name, &_tmp, lock) == REC_ERR_OKAY);
01065   if (found)
01066     *found = _found;
01067   return _tmp;
01068 }
01069 
01070 RecCounter
01071 REC_readCounter(char *name, bool * found, bool lock)
01072 {
01073   ink_assert(name);
01074   RecCounter _tmp = 0;
01075   bool _found;
01076   _found = (RecGetRecordCounter(name, &_tmp, lock) == REC_ERR_OKAY);
01077   if (found)
01078     *found = _found;
01079   return _tmp;
01080 }
01081 
01082 RecString
01083 REC_readString(const char *name, bool * found, bool lock)
01084 {
01085   ink_assert(name);
01086   RecString _tmp = NULL;
01087   bool _found;
01088   _found = (RecGetRecordString_Xmalloc(name, &_tmp, lock) == REC_ERR_OKAY);
01089   if (found)
01090     *found = _found;
01091   return _tmp;
01092 }
01093 
01094 //-------------------------------------------------------------------------
01095 // RecConfigReadRuntimeDir
01096 //-------------------------------------------------------------------------
01097 char *
01098 RecConfigReadRuntimeDir()
01099 {
01100   char buf[PATH_NAME_MAX + 1];
01101 
01102   buf[0] = '\0';
01103   RecGetRecordString("proxy.config.local_state_dir", buf, PATH_NAME_MAX);
01104   if (strlen(buf) > 0) {
01105     return Layout::get()->relative(buf);
01106   } else {
01107     return ats_strdup(Layout::get()->runtimedir);
01108   }
01109 }
01110 
01111 //-------------------------------------------------------------------------
01112 // RecConfigReadLogDir
01113 //-------------------------------------------------------------------------
01114 char *
01115 RecConfigReadLogDir()
01116 {
01117   char buf[PATH_NAME_MAX + 1];
01118 
01119   buf[0] = '\0';
01120   RecGetRecordString("proxy.config.log.logfile_dir", buf, PATH_NAME_MAX);
01121   if (strlen(buf) > 0) {
01122     return Layout::get()->relative(buf);
01123   } else {
01124     return ats_strdup(Layout::get()->logdir);
01125   }
01126 }
01127 
01128 //-------------------------------------------------------------------------
01129 // RecConfigReadBinDir
01130 //-------------------------------------------------------------------------
01131 char *
01132 RecConfigReadBinDir()
01133 {
01134   char buf[PATH_NAME_MAX + 1];
01135 
01136   buf[0] = '\0';
01137   RecGetRecordString("proxy.config.bin_path", buf, PATH_NAME_MAX);
01138   if (strlen(buf) > 0) {
01139     return Layout::get()->relative(buf);
01140   } else {
01141     return ats_strdup(Layout::get()->bindir);
01142   }
01143 }
01144 
01145 //-------------------------------------------------------------------------
01146 // RecConfigReadSnapshotDir.
01147 //-------------------------------------------------------------------------
01148 char *
01149 RecConfigReadSnapshotDir()
01150 {
01151   char buf[PATH_NAME_MAX + 1];
01152 
01153   buf[0] = '\0';
01154   RecGetRecordString("proxy.config.snapshot_dir", buf, PATH_NAME_MAX);
01155   if (strlen(buf) > 0) {
01156     return Layout::get()->relative_to(Layout::get()->sysconfdir, buf);
01157   } else {
01158     return Layout::get()->relative_to(Layout::get()->sysconfdir, "snapshots");
01159   }
01160 }
01161 
01162 //-------------------------------------------------------------------------
01163 // RecConfigReadConfigPath
01164 //-------------------------------------------------------------------------
01165 char *
01166 RecConfigReadConfigPath(const char * file_variable, const char * default_value)
01167 {
01168   char buf[PATH_NAME_MAX + 1];
01169 
01170   buf[0] = '\0';
01171   RecGetRecordString(file_variable, buf, PATH_NAME_MAX);
01172   if (strlen(buf) > 0) {
01173     return Layout::get()->relative_to(Layout::get()->sysconfdir, buf);
01174   }
01175 
01176   if (default_value) {
01177     return Layout::get()->relative_to(Layout::get()->sysconfdir, default_value);
01178   }
01179 
01180   return NULL;
01181 }
01182 
01183 //-------------------------------------------------------------------------
01184 // RecConfigReadPrefixPath
01185 //-------------------------------------------------------------------------
01186 char *
01187 RecConfigReadPrefixPath(const char * file_variable, const char * default_value)
01188 {
01189   char buf[PATH_NAME_MAX + 1];
01190 
01191   buf[0] = '\0';
01192   RecGetRecordString(file_variable, buf, PATH_NAME_MAX);
01193   if (strlen(buf) > 0) {
01194     return Layout::get()->relative_to(Layout::get()->prefix, buf);
01195   }
01196 
01197   if (default_value) {
01198     return Layout::get()->relative_to(Layout::get()->prefix, default_value);
01199   }
01200 
01201   return NULL;
01202 }
01203 
01204 //-------------------------------------------------------------------------
01205 // RecConfigReadPersistentStatsPath
01206 //-------------------------------------------------------------------------
01207 char *
01208 RecConfigReadPersistentStatsPath()
01209 {
01210   ats_scoped_str rundir(RecConfigReadRuntimeDir());
01211   return Layout::relative_to(rundir, REC_RAW_STATS_FILE);
01212 }
01213 
01214 void
01215 RecSignalWarning(int sig, const char * fmt, ...)
01216 {
01217   char msg[1024];
01218   va_list args;
01219 
01220   va_start(args, fmt);
01221   WarningV(fmt, args);
01222   va_end(args);
01223 
01224   va_start(args, fmt);
01225   vsnprintf(msg, sizeof(msg), fmt, args);
01226   RecSignalManager(sig, msg);
01227   va_end(args);
01228 }

Generated by  doxygen 1.7.1