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 }