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 "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 
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     
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     
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   
00069   r->registered = true;
00070   r->version = 0;
00071 
00072   return r;
00073 }
00074 
00075 
00076 
00077 
00078 
00079 static int
00080 link_int(const char * , RecDataT , 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 * , RecDataT , 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 * , RecDataT , 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 * , RecDataT , 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 * , RecDataT , 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 
00117 
00118 static int
00119 link_byte(const char * , RecDataT , 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 
00129 
00130 
00131 static int
00132 link_string_alloc(const char * , RecDataT , 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   
00142   RecString _temp2 = *((RecString *)cookie);
00143   *((RecString *)cookie) = _new_value;
00144   
00145   ats_free(_temp2);
00146 
00147   return REC_ERR_OKAY;
00148 }
00149 
00150 
00151 
00152 
00153 int
00154 RecCoreInit(RecModeT mode_type, Diags *_diags)
00155 {
00156   if (g_initialized) {
00157     return REC_ERR_OKAY;
00158   }
00159 
00160   
00161   RecSetDiags(_diags);
00162 
00163   
00164   RecConfigFileInit();
00165 
00166   g_records_tree = new RecTree(NULL);
00167   g_num_records = 0;
00168 
00169   
00170   g_records = (RecRecord *)ats_malloc(REC_MAX_RECORDS * sizeof(RecRecord));
00171 
00172   
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   
00179   if ((mode_type == RECM_SERVER) || (mode_type == RECM_STAND_ALONE)) {
00180     RecReadStatsFile();
00181   }
00182   
00183   if ((mode_type == RECM_SERVER) || (mode_type == RECM_STAND_ALONE)) {
00184     ink_mutex_init(&g_rec_config_lock, NULL);
00185     
00186     
00187     
00188     
00189     
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 
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 
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       
00295 
00296 
00297 
00298 
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 
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 
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 
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     
00737     
00738     
00739     
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 
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     
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 
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       
00803       
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 
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   
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 
00877 
00878 
00879 static void
00880 debug_record_callback(RecT , void * , 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 
00942 
00943 
00944 
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;  
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 }