0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 #include <stdlib.h>
0047 #include <stdio.h>
0048 #include <errno.h>
0049 #include <string.h>
0050 #include <ndrstandard.h>
0051 #include <atmi.h>
0052 #include <atmi_tls.h>
0053 #include <typed_buf.h>
0054 #include <edbutil.h>
0055
0056 #include "thlock.h"
0057 #include "userlog.h"
0058 #include "utlist.h"
0059 #include "exregex.h"
0060 #include <exparson.h>
0061 #include <atmi_cache.h>
0062 #include <Exfields.h>
0063
0064
0065
0066
0067
0068
0069 expublic ndrx_tpcache_phydb_t *ndrx_G_tpcache_phydb = NULL;
0070 expublic ndrx_tpcache_db_t *ndrx_G_tpcache_db = NULL;
0071 expublic ndrx_tpcache_svc_t *ndrx_G_tpcache_svc = NULL;
0072
0073
0074
0075 expublic ndrx_tpcache_typesupp_t ndrx_G_tpcache_types[] =
0076 {
0077
0078 {BUF_TYPE_UBF, ndrx_cache_rulcomp_ubf, ndrx_cache_ruleval_ubf, ndrx_cache_refeval_ubf,
0079 ndrx_cache_keyget_ubf, ndrx_cache_get_ubf, ndrx_cache_put_ubf,
0080 ndrx_cache_del_ubf, ndrx_cache_proc_flags_ubf, ndrx_cache_delete_ubf, ndrx_cache_maxreject_ubf},
0081
0082 {1, NULL, NULL, NULL,
0083 NULL, NULL, NULL,
0084 NULL, NULL, NULL, NULL},
0085
0086 {BUF_TYPE_INIT, NULL, NULL, NULL,
0087 NULL, NULL, NULL,
0088 NULL, NULL, NULL, NULL},
0089
0090 {BUF_TYPE_NULL, NULL, NULL, NULL,
0091 NULL, NULL, NULL,
0092 NULL, NULL, NULL, NULL},
0093
0094 {BUF_TYPE_STRING,NULL, NULL, NULL,
0095 NULL, NULL, NULL,
0096 NULL, NULL, NULL, NULL},
0097
0098 {BUF_TYPE_CARRAY, NULL, NULL, NULL,
0099 NULL, NULL, NULL,
0100 NULL, NULL, NULL, NULL},
0101
0102 {BUF_TYPE_JSON, NULL, NULL, NULL,
0103 NULL, NULL, NULL,
0104 NULL, NULL, NULL, NULL},
0105
0106 {BUF_TYPE_VIEW, NULL, NULL, NULL,
0107 NULL, NULL, NULL,
0108 NULL, NULL, NULL, NULL},
0109 {EXFAIL}
0110 };
0111
0112
0113
0114
0115
0116 expublic int ndrx_cache_used(void)
0117 {
0118 if (NULL!=ndrx_G_tpcache_db && NULL!=ndrx_G_tpcache_svc)
0119 {
0120 return EXTRUE;
0121 }
0122
0123 return EXFALSE;
0124 }
0125
0126
0127
0128
0129
0130
0131 expublic int ndrx_cache_maperr(int unixerr)
0132 {
0133 int ret = TPEOS;
0134
0135 switch (unixerr)
0136 {
0137 case EDB_NOTFOUND:
0138
0139 ret = TPENOENT;
0140
0141 break;
0142 }
0143
0144 return ret;
0145 }
0146
0147
0148
0149
0150
0151
0152
0153 expublic ndrx_tpcache_db_t* ndrx_cache_dbget(char *cachedb)
0154 {
0155 ndrx_tpcache_db_t *ret;
0156
0157 EXHASH_FIND_STR( ndrx_G_tpcache_db, cachedb, ret);
0158
0159 return ret;
0160 }
0161
0162
0163
0164
0165
0166
0167 expublic ndrx_tpcache_phydb_t* ndrx_cache_phydbget(char *cachedb)
0168 {
0169 ndrx_tpcache_phydb_t *ret;
0170
0171 EXHASH_FIND_STR( ndrx_G_tpcache_phydb, cachedb, ret);
0172
0173 return ret;
0174 }
0175
0176
0177
0178
0179
0180 exprivate void ndrx_cache_phydb_free(ndrx_tpcache_phydb_t *phydb)
0181 {
0182
0183 phydb->num_usages--;
0184
0185 if (phydb->num_usages<=0)
0186 {
0187 if (NULL!=phydb->env)
0188 {
0189 edb_env_close(phydb->env);
0190 }
0191 EXHASH_DEL(ndrx_G_tpcache_phydb, phydb);
0192 NDRX_FREE(phydb);
0193 }
0194 }
0195
0196
0197
0198
0199
0200
0201 exprivate void ndrx_cache_db_free(ndrx_tpcache_db_t *db)
0202 {
0203
0204 if (NULL!=db->phy)
0205 {
0206 edb_dbi_close(db->phy->env, db->dbi);
0207 ndrx_cache_phydb_free(db->phy);
0208
0209 }
0210
0211 NDRX_FREE(db);
0212 }
0213
0214
0215
0216
0217
0218
0219 expublic void ndrx_cache_tpcallcache_free(ndrx_tpcallcache_t *tpc)
0220 {
0221
0222 if (tpc->buf_type &&
0223 NULL!=ndrx_G_tpcache_types[tpc->buf_type->type_id].pf_cache_delete)
0224 {
0225 ndrx_G_tpcache_types[tpc->buf_type->type_id].pf_cache_delete(tpc);
0226 }
0227
0228 if (NULL!=tpc->rsprule_tree)
0229 {
0230 Btreefree(tpc->rsprule_tree);
0231 }
0232
0233 if (tpc->saveproj.regex_compiled)
0234 {
0235 ndrx_regfree(&tpc->saveproj.regex);
0236 }
0237
0238 if (tpc->delproj.regex_compiled)
0239 {
0240 ndrx_regfree(&tpc->delproj.regex);
0241 }
0242
0243 if (NULL!=tpc->keygroupmrej)
0244 {
0245 NDRX_FREE(tpc->keygroupmrej);
0246 }
0247
0248 if (NULL!=tpc->keygroupmrej_abuf)
0249 {
0250 tpfree(tpc->keygroupmrej_abuf);
0251 }
0252
0253 NDRX_FREE(tpc);
0254 }
0255
0256
0257
0258
0259
0260 expublic void ndrx_cache_svc_free(ndrx_tpcache_svc_t *svc)
0261 {
0262 ndrx_tpcallcache_t *elt, *el;
0263
0264
0265 DL_FOREACH_SAFE(svc->caches, el, elt)
0266 {
0267 DL_DELETE(svc->caches, el);
0268 ndrx_cache_tpcallcache_free(el);
0269 }
0270
0271 NDRX_FREE(svc);
0272 }
0273
0274
0275
0276
0277 expublic void ndrx_cache_svcs_free(void)
0278 {
0279 ndrx_tpcache_svc_t *el, *elt;
0280 EXHASH_ITER(hh, ndrx_G_tpcache_svc, el, elt)
0281 {
0282 EXHASH_DEL(ndrx_G_tpcache_svc, el);
0283 ndrx_cache_svc_free(el);
0284 }
0285 }
0286
0287
0288
0289
0290 expublic void ndrx_cache_dbs_free(void)
0291 {
0292 ndrx_tpcache_db_t *el, *elt;
0293 EXHASH_ITER(hh, ndrx_G_tpcache_db, el, elt)
0294 {
0295 EXHASH_DEL(ndrx_G_tpcache_db, el);
0296 ndrx_cache_db_free(el);
0297 }
0298 }
0299
0300
0301
0302
0303
0304 expublic ndrx_tpcache_db_t *ndrx_cache_dbgethash(void)
0305 {
0306 return ndrx_G_tpcache_db;
0307 }
0308
0309
0310
0311
0312
0313
0314
0315
0316 exprivate int sort_data_bydate(const EDB_val *a, const EDB_val *b)
0317 {
0318 ndrx_tpcache_data_t *ad = (ndrx_tpcache_data_t *)a->mv_data;
0319 ndrx_tpcache_data_t *bd = (ndrx_tpcache_data_t *)b->mv_data;
0320
0321 #ifdef EX_ALIGNMENT_FORCE
0322 long a_t;
0323 long a_tusec;
0324 long b_t;
0325 long b_tusec;
0326
0327 memcpy(&a_t, &ad->t, sizeof(a_t));
0328 memcpy(&a_tusec, &ad->tusec, sizeof(a_tusec));
0329
0330 memcpy(&b_t, &bd->t, sizeof(b_t));
0331 memcpy(&b_tusec, &bd->tusec, sizeof(b_tusec));
0332
0333
0334 return ndrx_utc_cmp(&b_t, &b_tusec, &a_t, &a_tusec);
0335
0336 #else
0337
0338 return ndrx_utc_cmp(&bd->t, &bd->tusec, &ad->t, &ad->tusec);
0339 #endif
0340
0341 }
0342
0343
0344
0345
0346
0347
0348 exprivate int ndrx_cache_phydb_getref(ndrx_tpcache_db_t *db)
0349 {
0350 int ret = EXSUCCEED;
0351 unsigned int dbflags=0;
0352 ndrx_tpcache_phydb_t *phy=NULL;
0353
0354 if (NULL!=(db->phy = ndrx_cache_phydbget(db->cachedbphy)))
0355 {
0356 db->phy->num_usages++;
0357
0358 NDRX_LOG(log_debug, "Cache db [%s] already loaded, new usage: %d",
0359 db->cachedbphy, db->phy->num_usages);
0360 goto out;
0361 }
0362
0363
0364 NDRX_CALLOC_OUT(phy, 1, sizeof(ndrx_tpcache_phydb_t), ndrx_tpcache_phydb_t);
0365
0366
0367
0368
0369 if (EXSUCCEED!=(ret=edb_env_create(&phy->env)))
0370 {
0371 NDRX_CACHE_TPERROR(ndrx_cache_maperr(ret),
0372 "CACHE: Failed to create env for [%s]: %s",
0373 db->cachedb, edb_strerror(errno));
0374 EXFAIL_OUT(ret);
0375 }
0376
0377 if (EXSUCCEED!=(ret=edb_env_set_maxreaders(phy->env, db->max_readers)))
0378 {
0379 NDRX_CACHE_TPERROR(ndrx_cache_maperr(ret),
0380 "CACHE: Failed to set max readers for [%s]: %s",
0381 db->cachedb, edb_strerror(ret));
0382
0383 EXFAIL_OUT(ret);
0384 }
0385
0386 if (EXSUCCEED!=(ret=edb_env_set_maxdbs(phy->env, db->max_dbs)))
0387 {
0388 NDRX_CACHE_TPERROR(ndrx_cache_maperr(ret),
0389 "Failed to set max dbs for [%s]: %s",
0390 db->cachedb, edb_strerror(ret));
0391
0392 EXFAIL_OUT(ret);
0393 }
0394
0395 if (EXSUCCEED!=(ret=edb_env_set_mapsize(phy->env, db->map_size)))
0396 {
0397 NDRX_CACHE_TPERROR(ndrx_cache_maperr(ret),
0398 "Failed to set map size for [%s]: %s",
0399 db->cachedb, edb_strerror(ret));
0400
0401 EXFAIL_OUT(ret);
0402 }
0403
0404 NDRX_STRCPY_SAFE(phy->resource, db->resource);
0405 NDRX_STRCPY_SAFE(phy->cachedb, db->cachedbphy);
0406
0407 if (db->flags & NDRX_TPCACHE_FLAGS_NOSYNC)
0408 {
0409 dbflags|=EDB_NOSYNC;
0410 }
0411
0412 if (db->flags & NDRX_TPCACHE_FLAGS_NOMETASYNC)
0413 {
0414 dbflags|=EDB_NOMETASYNC;
0415 }
0416
0417
0418
0419
0420
0421 if (EXSUCCEED!=(ret=edb_env_open(phy->env, db->resource, dbflags, db->perms)))
0422 {
0423 NDRX_CACHE_TPERROR(ndrx_cache_maperr(ret),
0424 "Failed to open env [%s] [%s]: %s",
0425 db->cachedb, db->resource, edb_strerror(ret));
0426
0427 EXFAIL_OUT(ret);
0428 }
0429
0430
0431 EXHASH_ADD_STR(ndrx_G_tpcache_phydb, cachedb, phy);
0432
0433
0434 phy->num_usages++;
0435 db->phy = phy;
0436
0437 out:
0438
0439 if (NULL!=phy && EXSUCCEED!=ret)
0440 {
0441 NDRX_FREE(phy);
0442 }
0443
0444 return ret;
0445 }
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456 expublic ndrx_tpcache_db_t* ndrx_cache_dbresolve(char *cachedb, int mode)
0457 {
0458 int ret = EXSUCCEED;
0459 ndrx_tpcache_db_t* db;
0460 ndrx_inicfg_section_keyval_t * csection = NULL, *val = NULL, *val_tmp = NULL;
0461
0462 char cachesection[sizeof(NDRX_CONF_SECTION_CACHEDB)+1+NDRX_CCTAG_MAX*2+1+1];
0463 char *p;
0464 char *saveptr1 = NULL;
0465 EDB_txn *txn = NULL;
0466 unsigned int dbi_flags;
0467 int any_config = EXFALSE;
0468 char dbnametmp[NDRX_CCTAG_MAX+1];
0469 int tran_started = EXFALSE;
0470
0471 if (NULL!=(db = ndrx_cache_dbget(cachedb)))
0472 {
0473 #ifdef NDRX_TPCACHE_DEBUG
0474 NDRX_LOG(log_debug, "Cache db [%s] already loaded", cachedb);
0475 #endif
0476 goto out;
0477 }
0478
0479 NDRX_CALLOC_OUT(db, 1, sizeof(ndrx_tpcache_db_t), ndrx_tpcache_db_t);
0480
0481
0482 NDRX_STRCPY_SAFE(dbnametmp, cachedb);
0483
0484 p=strchr(dbnametmp, NDRX_CACHE_NAMEDBSEP);
0485
0486 if (NULL!=p)
0487 {
0488 NDRX_STRCPY_SAFE(db->cachedb, dbnametmp);
0489
0490 *p=EXEOS;
0491 p++;
0492
0493 NDRX_STRCPY_SAFE(db->cachedbnam, dbnametmp);
0494
0495 NDRX_STRCPY_SAFE(db->cachedbphy, p);
0496 }
0497 else
0498 {
0499 NDRX_STRCPY_SAFE(db->cachedbnam, dbnametmp);
0500 NDRX_STRCPY_SAFE(db->cachedb, dbnametmp);
0501 NDRX_STRCPY_SAFE(db->cachedbphy, dbnametmp);
0502 }
0503
0504 NDRX_LOG(log_debug, "full name: [%s] logical name: [%s] physical name [%s]",
0505 db->cachedb, db->cachedbnam, db->cachedbphy);
0506
0507
0508
0509
0510
0511 if (0==strcmp(db->cachedb, db->cachedbnam))
0512 {
0513 snprintf(cachesection, sizeof(cachesection), "%s/%s",
0514 NDRX_CONF_SECTION_CACHEDB, cachedb);
0515 }
0516 else
0517 {
0518 snprintf(cachesection, sizeof(cachesection), "%s/%s/%s",
0519 NDRX_CONF_SECTION_CACHEDB, db->cachedbphy, db->cachedbnam);
0520 }
0521
0522 NDRX_LOG(log_debug, "cache db [%s] mode %d looking up: [%s]",
0523 cachedb, mode, cachesection);
0524
0525 if (EXSUCCEED!=ndrx_inicfg_get_subsect(ndrx_get_G_cconfig(),
0526 NULL,
0527 cachesection,
0528 &csection))
0529 {
0530 NDRX_CACHE_ERROR("%s: Failed to get section [%s]: %s",
0531 __func__, cachesection, Nstrerror(Nerror));
0532 EXFAIL_OUT(ret);
0533 }
0534
0535
0536
0537
0538
0539 db->max_readers = NDRX_CACHE_MAX_READERS_DFLT;
0540 db->map_size = NDRX_CACHE_MAP_SIZE_DFLT;
0541 db->perms = NDRX_CACHE_PERMS_DFLT;
0542 db->max_dbs = NDRX_CACHE_MAX_DBS_DFLT;
0543
0544 EXHASH_ITER(hh, csection, val, val_tmp)
0545 {
0546
0547 any_config = EXTRUE;
0548 #ifdef NDRX_TPCACHE_DEBUG
0549 NDRX_LOG(log_debug, "%s: config: key: [%s] value: [%s]",
0550 __func__, val->key, val->val);
0551 #endif
0552
0553 if (0==strcmp(val->key, NDRX_TPCACHE_KWD_CACHEDB))
0554 {
0555 if (0!=strcmp(val->val, db->cachedb))
0556 {
0557 NDRX_CACHE_ERROR("%s: Invalid cache name [%s] for section [%s] "
0558 "should be [%s]!",
0559 __func__, val->val, cachesection, db->cachedb);
0560 EXFAIL_OUT(ret);
0561 }
0562 }
0563 else if (0==strcmp(val->key, NDRX_TPCACHE_KWD_RESOURCE))
0564 {
0565 NDRX_STRCPY_SAFE(db->resource, val->val);
0566 }
0567 else if (0==strcmp(val->key, NDRX_TPCACHE_KWD_PERMS))
0568 {
0569 char *pend;
0570 db->perms = strtol(val->val, &pend, 0);
0571 }
0572
0573 else if (0==strcmp(val->key, NDRX_TPCACHE_KWD_LIMIT))
0574 {
0575 db->limit = (long)ndrx_num_dec_parsecfg(val->val);
0576 }
0577 else if (0==strcmp(val->key, NDRX_TPCACHE_KWD_EXPIRY))
0578 {
0579 db->expiry = (long)ndrx_num_time_parsecfg(val->val) / 1000L;
0580
0581
0582
0583 if (0>=db->expiry)
0584 {
0585 NDRX_CACHE_ERROR("Invalid expiry specified for db [%s], "
0586 "the minimums is 1 second ", cachedb);
0587 EXFAIL_OUT(ret);
0588 }
0589
0590 db->flags|=NDRX_TPCACHE_FLAGS_EXPIRY;
0591 }
0592 else if (0==strcmp(val->key, NDRX_TPCACHE_KWD_FLAGS))
0593 {
0594
0595 p = strtok_r (val->val, ",", &saveptr1);
0596 while (p != NULL)
0597 {
0598
0599 ndrx_str_strip(p, "\t ");
0600
0601
0602
0603 if (0==strcmp(p, NDRX_TPCACHE_KWD_BOOTRST))
0604 {
0605 db->flags|=NDRX_TPCACHE_FLAGS_BOOTRST;
0606 }
0607 else if (0==strcmp(p, NDRX_TPCACHE_KWD_LRU))
0608 {
0609 db->flags|=NDRX_TPCACHE_FLAGS_LRU;
0610 }
0611 else if (0==strcmp(p, NDRX_TPCACHE_KWD_HITS))
0612 {
0613 db->flags|=NDRX_TPCACHE_FLAGS_HITS;
0614 }
0615 else if (0==strcmp(p, NDRX_TPCACHE_KWD_FIFO))
0616 {
0617 db->flags|=NDRX_TPCACHE_FLAGS_FIFO;
0618 }
0619 else if (0==strcmp(p, NDRX_TPCACHE_KWD_BCASTPUT))
0620 {
0621 db->flags|=NDRX_TPCACHE_FLAGS_BCASTPUT;
0622 }
0623 else if (0==strcmp(p, NDRX_TPCACHE_KWD_BCASTDEL))
0624 {
0625 db->flags|=NDRX_TPCACHE_FLAGS_BCASTDEL;
0626 }
0627 else if (0==strcmp(p, NDRX_TPCACHE_KWD_TIMESYNC))
0628 {
0629 db->flags|=NDRX_TPCACHE_FLAGS_TIMESYNC;
0630 }
0631 else if (0==strcmp(p, NDRX_TPCACHE_KWD_SCANDUP))
0632 {
0633 db->flags|=NDRX_TPCACHE_FLAGS_SCANDUP;
0634 }
0635 else if (0==strcmp(p, NDRX_TPCACHE_KWD_CLRNOSVC))
0636 {
0637 db->flags|=NDRX_TPCACHE_FLAGS_CLRNOSVC;
0638 }
0639 else if (0==strcmp(p, NDRX_TPCACHE_KWD_KEYITEMS))
0640 {
0641 db->flags|=NDRX_TPCACHE_FLAGS_KEYITEMS;
0642 }
0643 else if (0==strcmp(p, NDRX_TPCACHE_KWD_KEYGRP))
0644 {
0645 db->flags|=NDRX_TPCACHE_FLAGS_KEYGRP;
0646 }
0647 else if (0==strcmp(p, NDRX_TPCACHE_KWD_NOSYNC))
0648 {
0649 db->flags|=NDRX_TPCACHE_FLAGS_NOSYNC;
0650 }
0651 else if (0==strcmp(p, NDRX_TPCACHE_KWD_NOMETASYNC))
0652 {
0653 db->flags|=NDRX_TPCACHE_FLAGS_NOMETASYNC;
0654 }
0655 else
0656 {
0657
0658 NDRX_CACHE_ERROR("Ignoring unknown cachedb [%s] flag: [%s]",
0659 cachedb, p);
0660 }
0661 p = strtok_r (NULL, ",", &saveptr1);
0662 }
0663
0664 }
0665 else if (0==strcmp(val->key, NDRX_TPCACHE_KWD_MAX_READERS))
0666 {
0667 db->max_readers = (long)ndrx_num_dec_parsecfg(val->val);
0668 }
0669 else if (0==strcmp(val->key, NDRX_TPCACHE_KWD_MAX_DBS))
0670 {
0671 db->max_dbs = (long)ndrx_num_dec_parsecfg(val->val);
0672 }
0673
0674 else if (0==strcmp(val->key, NDRX_TPCACHE_KWD_MAP_SIZE))
0675 {
0676 db->map_size = (long)ndrx_num_dec_parsecfg(val->val);
0677 }
0678 else if (0==strcmp(val->key, NDRX_TPCACHE_KWD_SUBSCR))
0679 {
0680 NDRX_STRCPY_SAFE(db->subscr, val->val);
0681 }
0682 else
0683 {
0684 NDRX_LOG(log_warn, "Ignoring unknown cache configuration param: [%s]",
0685 val->key);
0686 userlog("Ignoring unknown cache configuration param: [%s]",
0687 val->key);
0688 }
0689 }
0690
0691 if (!any_config)
0692 {
0693 NDRX_CACHE_ERROR("Cache db [%s] not found in configuration", cachedb);
0694 EXFAIL_OUT(ret);
0695 }
0696
0697
0698
0699 if (EXEOS==db->cachedb[0])
0700 {
0701 NDRX_CACHE_ERROR("Missing `%s' parameter for cache [%s]",
0702 NDRX_TPCACHE_KWD_CACHEDB, cachedb);
0703 EXFAIL_OUT(ret);
0704 }
0705
0706 if (EXEOS==db->resource[0])
0707 {
0708 NDRX_CACHE_ERROR("Missing `%s' parameter for cache [%s]",
0709 NDRX_TPCACHE_KWD_RESOURCE, cachedb);
0710 EXFAIL_OUT(ret);
0711 }
0712
0713
0714
0715 if (((db->flags & NDRX_TPCACHE_FLAGS_LRU) &&
0716 ((db->flags & NDRX_TPCACHE_FLAGS_HITS) ||
0717 (db->flags & NDRX_TPCACHE_FLAGS_FIFO)))
0718 ||
0719
0720 ((db->flags & NDRX_TPCACHE_FLAGS_HITS) &&
0721 ((db->flags & NDRX_TPCACHE_FLAGS_LRU) ||
0722 (db->flags & NDRX_TPCACHE_FLAGS_FIFO)))
0723 ||
0724 ((db->flags & NDRX_TPCACHE_FLAGS_FIFO) &&
0725 ((db->flags & NDRX_TPCACHE_FLAGS_LRU) ||
0726 (db->flags & NDRX_TPCACHE_FLAGS_HITS)))
0727
0728 )
0729 {
0730
0731 NDRX_LOG(log_error, "lru = %d", (db->flags & NDRX_TPCACHE_FLAGS_LRU));
0732 NDRX_LOG(log_error, "hits = %d", (db->flags & NDRX_TPCACHE_FLAGS_HITS));
0733 NDRX_LOG(log_error, "fifo = %d", (db->flags & NDRX_TPCACHE_FLAGS_FIFO));
0734
0735 NDRX_CACHE_ERROR("For cache db [%s] flags lru,hits and fifo cannot be mixed!",
0736 cachedb);
0737 EXFAIL_OUT(ret);
0738 }
0739
0740
0741
0742
0743 #ifdef NDRX_TPCACHE_DEBUG
0744 NDRX_TPCACHEDB_DUMPCFG(log_info, db);
0745 #endif
0746
0747 NDRX_LOG(log_debug, "cachedb: [%s] boot mode: %d flags: %ld reset: %d",
0748 db->cachedb, mode, db->flags, (int)(db->flags & NDRX_TPCACHE_FLAGS_BOOTRST));
0749
0750 if (NDRX_TPCACH_INIT_BOOT==mode &&
0751 db->flags & NDRX_TPCACHE_FLAGS_BOOTRST)
0752 {
0753 char errdet[PATH_MAX+1];
0754
0755 if (EXSUCCEED!=ndrx_mdb_unlink(db->resource, errdet, sizeof(errdet),
0756 LOG_FACILITY_NDRX))
0757 {
0758 NDRX_CACHE_TPERROR(TPESYSTEM, errdet);
0759 EXFAIL_OUT(ret);
0760 }
0761
0762 #if 0
0763 if (EXSUCCEED!=(ret=edb_drop(txn, db->dbi, 0)))
0764 {
0765 NDRX_CACHE_TPERROR(ndrx_cache_maperr(ret),
0766 "CACHE: Failed to clear db: [%s]: %s",
0767 db->cachedb, edb_strerror(ret));
0768
0769 EXFAIL_OUT(ret);
0770 }
0771 #endif
0772 }
0773
0774
0775 if (EXSUCCEED!=ndrx_cache_phydb_getref(db))
0776 {
0777 NDRX_CACHE_ERROR("Failed to load physical db for [%s]/[%s]",
0778 db->cachedbphy, db->cachedb);
0779 EXFAIL_OUT(ret);
0780 }
0781
0782
0783 if (EXSUCCEED!=(ret=edb_txn_begin(db->phy->env, NULL, 0, &txn)))
0784 {
0785 NDRX_CACHE_TPERROR(ndrx_cache_maperr(ret),
0786 "Failed to begin transaction for [%s]: %s",
0787 db->cachedb, edb_strerror(ret));
0788
0789 EXFAIL_OUT(ret);
0790 }
0791 tran_started = EXTRUE;
0792
0793
0794 if (db->flags & NDRX_TPCACHE_FLAGS_TIMESYNC)
0795 {
0796
0797
0798
0799 dbi_flags = EDB_DUPSORT;
0800 }
0801 else
0802 {
0803 dbi_flags = 0;
0804 }
0805
0806 if (EXSUCCEED!=(ret=edb_dbi_open(txn, db->cachedbnam, dbi_flags|EDB_CREATE, &db->dbi)))
0807 {
0808 NDRX_CACHE_TPERROR(ndrx_cache_maperr(ret),
0809 "Failed to open named db for [%s]: %s",
0810 db->cachedb, edb_strerror(ret));
0811
0812 EXFAIL_OUT(ret);
0813 }
0814
0815 if (db->flags & NDRX_TPCACHE_FLAGS_TIMESYNC)
0816 {
0817 if (EXSUCCEED!=(ret=edb_set_dupsort(txn, db->dbi, sort_data_bydate)))
0818 {
0819 NDRX_CACHE_TPERROR(ndrx_cache_maperr(ret),
0820 "Failed to begin transaction for [%s]: %s",
0821 db->cachedb, edb_strerror(ret));
0822
0823 goto out;
0824 }
0825 }
0826
0827 NDRX_LOG(log_debug, "boot mode: %d flags: %ld reset: %d",
0828 mode, db->flags, (int)(db->flags & NDRX_TPCACHE_FLAGS_BOOTRST));
0829
0830
0831 if (EXSUCCEED!=(ret=edb_txn_commit(txn)))
0832 {
0833 NDRX_CACHE_TPERROR(ndrx_cache_maperr(ret),
0834 "Failed to open named db for [%s]: %s",
0835 db->cachedb, edb_strerror(ret));
0836 EXFAIL_OUT(ret);
0837 }
0838 tran_started = EXFALSE;
0839
0840
0841
0842 EXHASH_ADD_STR(ndrx_G_tpcache_db, cachedb, db);
0843
0844 NDRX_LOG(log_debug, "Cache [%s] path: [%s] is open!",
0845 db->resource, db->cachedb);
0846 out:
0847
0848 if (NULL!=csection)
0849 {
0850 ndrx_keyval_hash_free(csection);
0851 }
0852
0853 if (tran_started)
0854 {
0855 edb_txn_abort(txn);
0856 }
0857
0858 if (EXSUCCEED!=ret)
0859 {
0860 if (NULL!=db)
0861 {
0862 ndrx_cache_db_free(db);
0863 }
0864
0865 return NULL;
0866 }
0867 else
0868 {
0869 return db;
0870 }
0871 }
0872
0873
0874
0875
0876
0877
0878
0879
0880
0881
0882
0883 expublic ndrx_tpcallcache_t* ndrx_cache_findtpcall_byidx(char *svcnm, int idx)
0884 {
0885 ndrx_tpcache_svc_t *svcc;
0886 ndrx_tpcallcache_t* el;
0887 int ret = EXSUCCEED;
0888 int i=0;
0889
0890 EXHASH_FIND_STR(ndrx_G_tpcache_svc, svcnm, svcc);
0891
0892 if (NULL==svcc)
0893 {
0894 NDRX_LOG(log_debug, "No cache defined for service [%s]", svcnm);
0895 return NULL;
0896 }
0897
0898 DL_FOREACH(svcc->caches, el)
0899 {
0900 if (i==idx)
0901 {
0902 return el;
0903 }
0904
0905 i++;
0906 }
0907
0908 out:
0909 return NULL;
0910 }
0911
0912
0913
0914
0915
0916
0917
0918
0919 expublic ndrx_tpcallcache_t* ndrx_cache_findtpcall(ndrx_tpcache_svc_t *svcc,
0920 typed_buffer_descr_t *buf_type, char *idata, long ilen, int idx)
0921 {
0922 ndrx_tpcallcache_t* el;
0923 int ret = EXSUCCEED;
0924 char errdet[MAX_TP_ERROR_LEN+1];
0925 int i = -1;
0926
0927 DL_FOREACH(svcc->caches, el)
0928 {
0929 i++;
0930 if (el->buf_type->type_id == buf_type->type_id)
0931 {
0932 if (i==idx)
0933 {
0934 return el;
0935 }
0936
0937 else if ( idx > EXFAIL)
0938 {
0939 continue;
0940 }
0941
0942 if (ndrx_G_tpcache_types[el->buf_type->type_id].pf_rule_eval)
0943 {
0944 ret = ndrx_G_tpcache_types[el->buf_type->type_id].pf_rule_eval(el,
0945 idata, ilen, errdet, sizeof(errdet));
0946 if (EXFAIL==ret)
0947 {
0948 NDRX_CACHE_ERROR("%s: Failed to evaluate buffer [%s]: %s",
0949 __func__, el->rule, errdet);
0950 return NULL;
0951 }
0952 else if (EXTRUE==ret)
0953 {
0954 #ifdef NDRX_TPCACHE_DEBUG
0955 NDRX_LOG(log_debug, "Buffer RULE TRUE [%s]", el->rule);
0956 #endif
0957 return el;
0958 }
0959 else
0960 {
0961 #ifdef NDRX_TPCACHE_DEBUG
0962 NDRX_LOG(log_debug, "Buffer RULE FALSE [%s]", el->rule);
0963 #endif
0964
0965 }
0966 }
0967 else
0968 {
0969
0970 NDRX_CACHE_ERROR("%s: Unsupported buffer type [%s] for cache",
0971 __func__, el->buf_type->type);
0972 return NULL;
0973 }
0974 }
0975 else if (i==idx)
0976 {
0977 NDRX_CACHE_ERROR("%s: Cache found at index [%d] but types "
0978 "does not match [%s] vs [%s]", __func__, el->buf_type->type,
0979 buf_type->type);
0980 return NULL;
0981 }
0982 }
0983
0984 return NULL;
0985 }
0986
0987
0988
0989
0990
0991 expublic void ndrx_cache_uninit(void)
0992 {
0993
0994 ndrx_cache_svcs_free();
0995 ndrx_cache_dbs_free();
0996
0997 }
0998
0999
1000
1001
1002
1003 expublic int ndrx_cache_init(int mode)
1004 {
1005 int ret = EXSUCCEED;
1006 char *svc;
1007 EXJSON_Value *root_value=NULL;
1008 EXJSON_Object *root_object, *array_object;
1009 EXJSON_Array *array;
1010 int type;
1011 int nrcaches;
1012 char *name;
1013 int cnt;
1014 const char *tmp;
1015 char flagstr[NDRX_CACHE_FLAGS_MAX+1];
1016 size_t i;
1017 ndrx_tpcallcache_t *cache = NULL;
1018 ndrx_tpcache_svc_t *cachesvc = NULL;
1019 char errdet[MAX_TP_ERROR_LEN+1];
1020 char *p_flags;
1021 ndrx_inicfg_section_keyval_t * csection = NULL, *val = NULL, *val_tmp = NULL;
1022 char *saveptr1 = NULL;
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032 if (NULL==ndrx_get_G_cconfig())
1033 {
1034
1035 #ifdef NDRX_TPCACHE_DEBUG
1036 NDRX_LOG(log_debug, "No CConfig - skip cache init");
1037 #endif
1038 goto out;
1039 }
1040
1041 if (EXSUCCEED!=ndrx_cconfig_get(NDRX_CONF_SECTION_CACHE, &csection))
1042 {
1043
1044 #ifdef NDRX_TPCACHE_DEBUG
1045 NDRX_LOG(log_debug, "[%s] section not found - no cache init",
1046 NDRX_CONF_SECTION_CACHE);
1047 #endif
1048 goto out;
1049 }
1050
1051 EXHASH_ITER(hh, csection, val, val_tmp)
1052 {
1053
1054 #ifdef NDRX_TPCACHE_DEBUG
1055 NDRX_LOG(log_info, "Found cache service: key: [%s] value: [%s]",
1056 val->key, val->val);
1057 #endif
1058
1059
1060 if (0!=strncmp(val->key, "svc ", 4) && 0!=strncmp(val->key, "svc\t", 4) )
1061 {
1062 continue;
1063 }
1064
1065
1066 svc = ndrx_str_lstrip_ptr(val->key+4, "\t ");
1067
1068 #ifdef NDRX_TPCACHE_DEBUG
1069 NDRX_LOG(log_info, "Got service: [%s] ... parsing json config", svc);
1070 #endif
1071
1072
1073 if (NULL!=root_value)
1074 {
1075 exjson_value_free(root_value);
1076 }
1077
1078 root_value = exjson_parse_string_with_comments(val->val);
1079
1080 NDRX_LOG(log_debug, "exjson_parse_string_with_comments %p", root_value);
1081
1082 type = exjson_value_get_type(root_value);
1083 NDRX_LOG(log_debug, "Type is %d", type);
1084
1085 if (exjson_value_get_type(root_value) != EXJSONObject)
1086 {
1087 NDRX_CACHE_ERROR("cache: invalid service [%s] cache: Failed "
1088 "to parse root element", svc);
1089 EXFAIL_OUT(ret);
1090 }
1091
1092 root_object = exjson_value_get_object(root_value);
1093
1094 nrcaches = exjson_object_get_count(root_object);
1095
1096 if (1!=nrcaches)
1097 {
1098 NDRX_CACHE_ERROR("CACHE: invalid service [%s] cache: "
1099 "Failed to parse root element", svc);
1100 EXFAIL_OUT(ret);
1101 }
1102
1103 name = (char *)exjson_object_get_name(root_object, 0);
1104
1105 if (0!=strcmp(NDRX_CACHES_BLOCK, name))
1106 {
1107 NDRX_CACHE_ERROR("CACHE: Expected [%s] got [%s]",
1108 NDRX_CACHES_BLOCK, name);
1109 EXFAIL_OUT(ret);
1110 }
1111
1112
1113 array = exjson_object_get_array(root_object, NDRX_CACHES_BLOCK);
1114 cnt = exjson_array_get_count(array);
1115
1116 #ifdef NDRX_TPCACHE_DEBUG
1117 NDRX_LOG(log_debug, "Got array values %d", cnt);
1118 #endif
1119
1120 NDRX_CALLOC_OUT(cachesvc, 1, sizeof(ndrx_tpcache_svc_t), ndrx_tpcache_svc_t);
1121
1122 NDRX_STRCPY_SAFE(cachesvc->svcnm, svc);
1123
1124 for (i = 0; i < cnt; i++)
1125 {
1126
1127 NDRX_CALLOC_OUT(cache, 1, sizeof(ndrx_tpcallcache_t), ndrx_tpcallcache_t);
1128 array_object = exjson_array_get_object(array, i);
1129
1130 cache->idx = i;
1131 NDRX_STRCPY_SAFE(cache->svcnm, cachesvc->svcnm);
1132
1133
1134
1135 if (NULL!=(tmp = exjson_object_get_string(array_object,
1136 NDRX_TPCACHE_KWC_FLAGS)))
1137 {
1138 NDRX_STRCPY_SAFE(flagstr, tmp);
1139
1140
1141 ndrx_str_strip(flagstr, " \t");
1142 NDRX_STRCPY_SAFE(cache->flagsstr, flagstr);
1143
1144 #ifdef NDRX_TPCACHE_DEBUG
1145 NDRX_LOG(log_debug, "Processing flags: [%s]", flagstr);
1146 #endif
1147
1148 p_flags = strtok_r (flagstr, ",", &saveptr1);
1149 while (p_flags != NULL)
1150 {
1151
1152
1153
1154
1155 if (0==strcmp(p_flags, NDRX_TPCACHE_KWC_DELREG))
1156 {
1157 cache->flags|=NDRX_TPCACHE_TPCF_DELREG;
1158 }
1159 else if (0==strcmp(p_flags, NDRX_TPCACHE_KWC_DELFULL))
1160 {
1161 cache->flags|=NDRX_TPCACHE_TPCF_DELFULL;
1162 }
1163 else if (0==strcmp(p_flags, NDRX_TPCACHE_KWC_SAVEREG))
1164 {
1165 cache->flags|=NDRX_TPCACHE_TPCF_SAVEREG;
1166 }
1167 else if (0==strcmp(p_flags, NDRX_TPCACHE_KWC_REPL))
1168 {
1169 cache->flags|=NDRX_TPCACHE_TPCF_REPL;
1170 }
1171 else if (0==strcmp(p_flags, NDRX_TPCACHE_KWC_MERGE))
1172 {
1173 cache->flags|=NDRX_TPCACHE_TPCF_MERGE;
1174 }
1175 else if (0==strcmp(p_flags, NDRX_TPCACHE_KWC_NOSVCOK))
1176 {
1177 cache->flags|=NDRX_TPCACHE_TPCF_NOSVCOK;
1178 }
1179 else if (0==strcmp(p_flags, NDRX_TPCACHE_KWC_SAVEFULL))
1180 {
1181 cache->flags|=NDRX_TPCACHE_TPCF_SAVEFULL;
1182 }
1183 else if (0==strcmp(p_flags, NDRX_TPCACHE_KWC_INVAL))
1184 {
1185 cache->flags|=NDRX_TPCACHE_TPCF_INVAL;
1186 }
1187 else if (0==strcmp(p_flags, NDRX_TPCACHE_KWC_NEXT))
1188 {
1189 cache->flags|=NDRX_TPCACHE_TPCF_NEXT;
1190 }
1191 else if (0==strcmp(p_flags, NDRX_TPCACHE_KWC_INVLKEYGRP))
1192 {
1193 cache->flags|=NDRX_TPCACHE_TPCF_INVLKEYGRP;
1194 }
1195 else
1196 {
1197 NDRX_LOG(log_warn, "For service [%s] buffer index %d, "
1198 "invalid flag: [%s] - ignore", svc, i, p_flags);
1199 userlog("For service [%s] buffer index %d, "
1200 "invalid flag: [%s] - ignore", svc, i, p_flags);
1201 }
1202
1203 p_flags = strtok_r (NULL, ",", &saveptr1);
1204 }
1205 }
1206
1207 if ((cache->flags & NDRX_TPCACHE_TPCF_REPL) &&
1208 (cache->flags & NDRX_TPCACHE_TPCF_MERGE)
1209 )
1210 {
1211 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: invalid config - conflicting "
1212 "flags `%s' and `%s' "
1213 "for service [%s], buffer index: %d",
1214 NDRX_TPCACHE_KWC_REPL, NDRX_TPCACHE_KWC_MERGE, svc, i);
1215 EXFAIL_OUT(ret);
1216 }
1217
1218
1219 if ( !(cache->flags & NDRX_TPCACHE_TPCF_REPL) &&
1220 !(cache->flags & NDRX_TPCACHE_TPCF_MERGE)
1221 )
1222 {
1223 cache->flags |= NDRX_TPCACHE_TPCF_REPL;
1224 }
1225
1226
1227 if ((cache->flags & NDRX_TPCACHE_TPCF_SAVEREG) &&
1228 (cache->flags & NDRX_TPCACHE_TPCF_SAVEFULL))
1229 {
1230 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: invalid config - conflicting "
1231 "flags `%s' and `%s' "
1232 "for service [%s], buffer index: %d",
1233 NDRX_TPCACHE_KWC_SAVEREG, NDRX_TPCACHE_KWC_SAVEFULL,
1234 svc, i);
1235 EXFAIL_OUT(ret);
1236 }
1237
1238 if ((cache->flags & NDRX_TPCACHE_TPCF_NEXT) &&
1239 !(cache->flags & NDRX_TPCACHE_TPCF_INVAL))
1240 {
1241 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: invalid config - conflicting "
1242 "flags `%s' can be used only with `%s' "
1243 "for service [%s], buffer index: %d",
1244 NDRX_TPCACHE_KWC_NEXT, NDRX_TPCACHE_KWC_INVAL, svc, i);
1245 EXFAIL_OUT(ret);
1246 }
1247
1248
1249 if (NULL==(tmp = exjson_object_get_string(array_object,
1250 NDRX_TPCACHE_KWC_TYPE)))
1251 {
1252 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: invalid config missing "
1253 "[type] for service [%s], buffer index: %d", svc, i);
1254 EXFAIL_OUT(ret);
1255 }
1256
1257 NDRX_STRCPY_SAFE(cache->str_buf_type, tmp);
1258
1259 if (NULL!=(tmp = exjson_object_get_string(array_object,
1260 NDRX_TPCACHE_KWC_SUBTYPE)))
1261 {
1262 NDRX_STRCPY_SAFE(cache->str_buf_subtype, tmp);
1263 }
1264
1265
1266 if (NULL==(cache->buf_type = ndrx_get_buffer_descr(cache->str_buf_type,
1267 cache->str_buf_subtype)))
1268 {
1269 NDRX_CACHE_TPERROR(TPEOTYPE, "CACHE: invalid buffer type "
1270 "for service [%s], buffer index: %d - Unknown type "
1271 "[%s]/subtype[%s]", svc, i, cache->str_buf_type,
1272 cache->str_buf_subtype);
1273 EXFAIL_OUT(ret);
1274 }
1275
1276
1277 if (NULL==(tmp = exjson_object_get_string(array_object,
1278 NDRX_TPCACHE_KWC_CACHEDB)))
1279 {
1280 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: invalid config missing "
1281 "[%s] for service [%s], buffer index: %d",
1282 NDRX_TPCACHE_KWC_CACHEDB, svc, i);
1283 EXFAIL_OUT(ret);
1284 }
1285
1286 NDRX_STRCPY_SAFE(cache->cachedbnm, tmp);
1287
1288
1289
1290
1291 if (NULL==(cache->cachedb=ndrx_cache_dbresolve(cache->cachedbnm, mode)))
1292 {
1293 NDRX_LOG(log_error, "%s failed", __func__);
1294 EXFAIL_OUT(ret);
1295 }
1296
1297 if (cache->flags & NDRX_TPCACHE_TPCF_INVAL)
1298 {
1299 ndrx_tpcache_svc_t *svcc;
1300
1301
1302
1303
1304
1305
1306
1307 if (NULL==(tmp = exjson_object_get_string(array_object,
1308 NDRX_TPCACHE_KWC_INVAL_SVC)))
1309 {
1310 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: invalid config missing "
1311 "[%s] for service [%s], buffer index: %d",
1312 NDRX_TPCACHE_KWC_INVAL_SVC, svc, i);
1313 EXFAIL_OUT(ret);
1314 }
1315
1316 NDRX_STRCPY_SAFE(cache->inval_svc, tmp);
1317
1318
1319 if (NULL==(tmp = exjson_object_get_string(array_object,
1320 NDRX_TPCACHE_KWC_INVAL_IDX)))
1321 {
1322 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: invalid config missing "
1323 "[%s] for service [%s], buffer index: %d",
1324 NDRX_TPCACHE_KWC_INVAL_IDX, svc, i);
1325 EXFAIL_OUT(ret);
1326 }
1327
1328 cache->inval_idx = atoi(tmp);
1329
1330 NDRX_LOG(log_debug, "Searching for %s: [%s]/%d",
1331 NDRX_TPCACHE_KWC_INVAL_SVC,
1332 cache->inval_svc, cache->inval_idx);
1333
1334
1335 EXHASH_FIND_STR(ndrx_G_tpcache_svc, cache->inval_svc, svcc);
1336
1337 if (NULL==svcc)
1338 {
1339 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: %s [%s] not found, "
1340 "or defined later (at this or another config file)",
1341 NDRX_TPCACHE_KWC_INVAL_SVC, cache->inval_svc);
1342 EXFAIL_OUT(ret);
1343 }
1344
1345 if (NULL==(cache->inval_cache = ndrx_cache_findtpcall(svcc,
1346 cache->buf_type, NULL, EXFAIL, cache->inval_idx)))
1347 {
1348 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: tpcall cache not found "
1349 "for service [%s], index=%d, type=[%s]",
1350 cache->inval_svc, cache->inval_idx,
1351 cache->buf_type->type);
1352 EXFAIL_OUT(ret);
1353 }
1354
1355 NDRX_LOG(log_debug, "Service found: %p", cache->inval_cache);
1356 }
1357
1358
1359
1360 if (NULL!=(tmp = exjson_object_get_string(array_object,
1361 NDRX_TPCACHE_KWC_KEYGRPDB)))
1362 {
1363
1364 if (NULL==(cache->keygrpdb=ndrx_cache_dbresolve((char *)tmp, mode)))
1365 {
1366 NDRX_LOG(log_error, "%s failed", __func__);
1367 EXFAIL_OUT(ret);
1368 }
1369 }
1370
1371
1372 if (NULL==ndrx_G_tpcache_types[cache->buf_type->type_id].pf_get_key)
1373 {
1374 NDRX_CACHE_TPERROR(TPEOTYPE, "CACHE: buffer type not supported "
1375 "for service [%s], buffer index: %d - Unknown type "
1376 "[%s]/subtype[%s]", svc, i, cache->str_buf_type,
1377 cache->str_buf_subtype);
1378 EXFAIL_OUT(ret);
1379 }
1380
1381
1382 if (NULL==(tmp = exjson_object_get_string(array_object,
1383 NDRX_TPCACHE_KWC_KEYFMT)))
1384 {
1385 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: invalid config missing "
1386 "[%s] for service [%s], buffer index: %d",
1387 NDRX_TPCACHE_KWC_KEYFMT, svc, i);
1388 EXFAIL_OUT(ret);
1389 }
1390
1391 NDRX_STRCPY_SAFE(cache->keyfmt, tmp);
1392
1393
1394 if (NULL!=(tmp = exjson_object_get_string(array_object,
1395 NDRX_TPCACHE_KWC_KEYGRPFMT)))
1396 {
1397 NDRX_STRCPY_SAFE(cache->keygrpfmt, tmp);
1398 }
1399
1400 if (NULL!=(tmp = exjson_object_get_string(array_object,
1401 NDRX_TPCACHE_KWC_KEYGRPMAXTPERRNO)))
1402 {
1403 cache->keygroupmtperrno = atoi(tmp);
1404
1405 if (cache->keygroupmtperrno<TPMINVAL ||
1406 cache->keygroupmtperrno > TPMAXVAL)
1407 {
1408 NDRX_LOG(log_error, "Invalid max keygroup reject tperrno code [%s] %d "
1409 "(min: %d, max: %d)", NDRX_TPCACHE_KWC_KEYGRPMAXTPERRNO,
1410 cache->keygroupmtperrno, TPMINVAL, TPMAXVAL);
1411 EXFAIL_OUT(ret);
1412 }
1413 }
1414
1415 if (NULL!=(tmp = exjson_object_get_string(array_object,
1416 NDRX_TPCACHE_KWC_KEYGRPMAXTPURCODE)))
1417 {
1418 cache->keygroupmtpurcode = atol(tmp);
1419 }
1420
1421
1422 if (NULL!=(tmp = exjson_object_get_string(array_object,
1423 NDRX_TPCACHE_KWC_RULE)))
1424 {
1425 NDRX_STRCPY_SAFE(cache->rule, tmp);
1426 }
1427 else
1428 {
1429 NDRX_LOG(log_info, "[%s] is missing - assume cache always",
1430 NDRX_TPCACHE_KWC_RULE);
1431 }
1432
1433 if (NULL!=(tmp = exjson_object_get_string(array_object,
1434 NDRX_TPCACHE_KWC_REFRESHRULE)))
1435 {
1436 NDRX_STRCPY_SAFE(cache->refreshrule, tmp);
1437 }
1438
1439
1440
1441 if (!(cache->flags & NDRX_TPCACHE_TPCF_SAVEFULL) &&
1442 !(cache->flags & NDRX_TPCACHE_TPCF_INVAL)
1443 )
1444 {
1445 if (NULL!=(tmp = exjson_object_get_string(array_object,
1446 NDRX_TPCACHE_KWC_SAVE)))
1447 {
1448
1449 NDRX_STRCPY_SAFE(cache->saveproj.expression, tmp);
1450
1451
1452 if (cache->flags & NDRX_TPCACHE_TPCF_SAVEREG)
1453 {
1454 if (EXSUCCEED!=ndrx_regcomp(&cache->saveproj.regex,
1455 cache->saveproj.expression))
1456 {
1457 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: failed to compile [%s] "
1458 "regex [%s] for svc [%s], "
1459 "buffer index: %d - see ndrx logs",
1460 NDRX_TPCACHE_KWC_SAVE,
1461 cache->saveproj.expression, svc, i);
1462 }
1463 cache->saveproj.regex_compiled=EXTRUE;
1464 }
1465 }
1466 else
1467 {
1468 NDRX_LOG(log_info, "No save strategy specified - default "
1469 "to full save");
1470 cache->flags |= NDRX_TPCACHE_TPCF_SAVEFULL;
1471 }
1472 }
1473
1474
1475
1476
1477
1478 if (!(cache->flags & NDRX_TPCACHE_TPCF_DELFULL))
1479 {
1480 if (NULL!=(tmp = exjson_object_get_string(array_object,
1481 NDRX_TPCACHE_KWC_DELETE)))
1482 {
1483 NDRX_STRCPY_SAFE(cache->delproj.expression, tmp);
1484
1485
1486 if (cache->flags & NDRX_TPCACHE_TPCF_DELREG)
1487 {
1488 if (EXSUCCEED!=ndrx_regcomp(&cache->delproj.regex,
1489 cache->delproj.expression))
1490 {
1491 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: failed to "
1492 "compile [%s] regex [%s] for svc [%s], "
1493 "buffer index: %d - see ndrx logs",
1494 NDRX_TPCACHE_KWC_DELETE,
1495 cache->delproj.expression, svc, i);
1496 }
1497 cache->delproj.regex_compiled=EXTRUE;
1498 }
1499 }
1500 }
1501
1502
1503 if (NULL!=(tmp = exjson_object_get_string(array_object,
1504 NDRX_TPCACHE_KWC_KEYGROUPMREJ)))
1505 {
1506 cache->keygroupmrej = NDRX_STRDUP(tmp);
1507
1508 if (NULL==cache->keygroupmrej)
1509 {
1510 int err = errno;
1511 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: failed to allocate [%s] buf"
1512 "for svc [%s] buffer index: %d",
1513 NDRX_TPCACHE_KWC_KEYGROUPMREJ,
1514 svc, i, strerror(err));
1515 EXFAIL_OUT(ret);
1516 }
1517 }
1518
1519
1520 if (NULL!=(tmp = exjson_object_get_string(array_object,
1521 NDRX_TPCACHE_KWC_KEYGROUPMAX)))
1522 {
1523 cache->keygroupmax = atol(tmp);
1524 }
1525
1526 if (NULL!=ndrx_G_tpcache_types[cache->buf_type->type_id].pf_process_flags)
1527 {
1528 if (EXSUCCEED!=ndrx_G_tpcache_types[cache->buf_type->type_id].pf_process_flags(cache,
1529 errdet, sizeof(errdet)))
1530
1531 {
1532 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: failed to check flags [%s] "
1533 "for service [%s], buffer index: %d: %s",
1534 cache->flagsstr, svc, i, errdet);
1535 EXFAIL_OUT(ret);
1536 }
1537 }
1538
1539
1540
1541 if (NULL!=ndrx_G_tpcache_types[cache->buf_type->type_id].pf_rule_compile)
1542 {
1543
1544 if (EXSUCCEED!=ndrx_G_tpcache_types[cache->buf_type->type_id].pf_rule_compile(
1545 cache, errdet, sizeof(errdet)))
1546 {
1547 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: failed to compile rule [%s] "
1548 "for service [%s], buffer index: %d: %s",
1549 cache->rule, svc, i, errdet);
1550 EXFAIL_OUT(ret);
1551 }
1552 }
1553
1554
1555 if (NULL!=(tmp = exjson_object_get_string(array_object,
1556 NDRX_TPCACHE_KWC_RSPRULE)))
1557 {
1558 NDRX_STRCPY_SAFE(cache->rsprule, tmp);
1559
1560
1561 if (NULL==(cache->rsprule_tree=Bboolco (cache->rsprule)))
1562 {
1563 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: failed to "
1564 "compile [%s] [%s] "
1565 "for service [%s], buffer index: %d: %s",
1566 NDRX_TPCACHE_KWC_RSPRULE,
1567 cache->rsprule, svc, i, Bstrerror(Berror));
1568 EXFAIL_OUT(ret);
1569 }
1570 }
1571
1572
1573
1574 if (EXEOS!=cache->keygrpfmt[0] &&
1575 !(cache->flags & NDRX_TPCACHE_TPCF_INVAL))
1576 {
1577
1578 cache->flags|=NDRX_TPCACHE_TPCF_KEYITEMS;
1579
1580
1581
1582 if (NULL==cache->keygrpdb)
1583 {
1584 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: [%s] must be "
1585 "defined if [%s] is used!",
1586 NDRX_TPCACHE_KWC_KEYGRPDB, NDRX_TPCACHE_KWC_KEYGRPFMT);
1587 EXFAIL_OUT(ret);
1588 }
1589
1590
1591
1592 if (!(cache->keygrpdb->flags & NDRX_TPCACHE_FLAGS_KEYGRP))
1593 {
1594 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: [%s] flag must be "
1595 "defined for [%s] database to use it for keyitems for"
1596 " service [%s] buffer index %d",
1597 NDRX_TPCACHE_KWC_KEYGRPDB,
1598 cache->keygrpdb->cachedb, svc, i);
1599 EXFAIL_OUT(ret);
1600 }
1601
1602
1603
1604 if (!(cache->cachedb->flags & NDRX_TPCACHE_FLAGS_KEYITEMS))
1605 {
1606 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: [%s] flag must be "
1607 "defined for [%s] database to use it for keyitems for",
1608 " service [%s] buffer index %d",
1609 NDRX_TPCACHE_KWD_KEYITEMS,
1610 cache->cachedb->cachedb, svc, i);
1611 EXFAIL_OUT(ret);
1612 }
1613
1614 if (NULL!=cache->keygroupmrej && cache->keygroupmax<=0)
1615 {
1616 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: [%s] defined, but "
1617 "[%s] is 0 - invalid config for"
1618 " service [%s] buffer index %d",
1619 NDRX_TPCACHE_KWC_KEYGROUPMREJ,
1620 NDRX_TPCACHE_KWC_KEYGROUPMAX, svc, i);
1621 EXFAIL_OUT(ret);
1622 }
1623
1624 if (NULL==cache->keygroupmrej && cache->keygroupmax>0)
1625 {
1626 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: [%s] defined, but "
1627 "[%s] not defined - invalid config for"
1628 " service [%s] buffer index %d",
1629 NDRX_TPCACHE_KWC_KEYGROUPMAX,
1630 NDRX_TPCACHE_KWC_KEYGROUPMREJ, svc, i);
1631 EXFAIL_OUT(ret);
1632 }
1633
1634
1635 if (0!=strcmp(cache->cachedb->cachedbphy, cache->keygrpdb->cachedbphy))
1636 {
1637 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: [%s] for when using keygroup, "
1638 "the [%s] and [%s] must come from same physical db name! "
1639 "(<name>@<physicalname>) ([%s] != [%s])",
1640 NDRX_TPCACHE_KWC_CACHEDB, NDRX_TPCACHE_KWC_KEYGRPDB,
1641 cache->cachedb->cachedbphy, cache->keygrpdb->cachedbphy);
1642 EXFAIL_OUT(ret);
1643 }
1644
1645 if (0!=strcmp(cache->cachedb->resource, cache->keygrpdb->resource))
1646 {
1647 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: [%s] for when using keygroup, "
1648 "the [%s] and [%s] must have from same physical db resource! "
1649 "(<name>@<physicalname>) ([%s] != [%s])",
1650 NDRX_TPCACHE_KWC_CACHEDB, NDRX_TPCACHE_KWC_KEYGRPDB,
1651 cache->cachedb->resource, cache->keygrpdb->resource);
1652 EXFAIL_OUT(ret);
1653 }
1654 }
1655 else
1656 {
1657 if (NULL!=cache->keygroupmrej)
1658 {
1659 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: [%s] not used as "
1660 "group format not defined - service [%s] buffer index %d",
1661 NDRX_TPCACHE_KWC_KEYGROUPMREJ, svc, i);
1662 EXFAIL_OUT(ret);
1663 }
1664
1665 if (cache->keygroupmax > 0)
1666 {
1667 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: [%s] defined, but "
1668 "group format not defined - service [%s] buffer index %d",
1669 NDRX_TPCACHE_KWC_KEYGROUPMAX, svc, i);
1670 EXFAIL_OUT(ret);
1671 }
1672 }
1673
1674
1675 if (cache->flags & NDRX_TPCACHE_TPCF_INVLKEYGRP &&
1676 !(cache->flags & NDRX_TPCACHE_TPCF_INVAL))
1677 {
1678 NDRX_CACHE_TPERROR(TPEINVAL, "CACHE: [%s] can be only used with "
1679 "[%s] for svc [%s] idx %d",
1680 NDRX_TPCACHE_KWC_INVLKEYGRP, NDRX_TPCACHE_KWC_INVAL,
1681 svc, i);
1682 EXFAIL_OUT(ret);
1683 }
1684
1685
1686 DL_APPEND(cachesvc->caches, cache);
1687
1688 #ifdef NDRX_TPCACHE_DEBUG
1689 NDRX_TPCACHETPCALL_DUMPCFG(log_debug, cache);
1690 #endif
1691
1692 cache = NULL;
1693 }
1694
1695 EXHASH_ADD_STR(ndrx_G_tpcache_svc, svcnm, cachesvc);
1696 cachesvc = NULL;
1697 }
1698
1699 out:
1700
1701
1702 if (NULL!=root_value)
1703 {
1704 exjson_value_free(root_value);
1705 }
1706
1707 if (NULL!=csection)
1708 {
1709 ndrx_keyval_hash_free(csection);
1710 }
1711
1712 if (EXSUCCEED!=ret)
1713 {
1714 if (NULL!=cache)
1715 {
1716 ndrx_cache_tpcallcache_free(cache);
1717 }
1718
1719 if (NULL!=cachesvc)
1720 {
1721 ndrx_cache_svc_free(cachesvc);
1722 }
1723
1724
1725 ndrx_cache_svcs_free();
1726
1727
1728 ndrx_cache_dbs_free();
1729 }
1730
1731 return ret;
1732 }
1733