00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00023 #include "equilibrium-data_main.h"
00024 #include "equilibrium-data_config.h"
00025 #include "equilibrium-data_monitor.h"
00026
00027
00028
00029
00030
00031
00032
00036 typedef struct eq_server_s {
00037 in_addr_t server_addr;
00038 TAILQ_ENTRY(eq_server_s) entries;
00039 } eq_server_t;
00040
00041
00045 typedef TAILQ_HEAD(server_list_s, eq_server_s) server_list_t;
00046
00047
00052 typedef struct eq_app_s {
00053 patnode node;
00054 char application_name[MAX_APP_NAME];
00055 in_addr_t application_addr;
00056 uint16_t application_port;
00057 uint16_t session_timeout;
00058 eq_smon_t * server_mon_params;
00059 server_list_t * servers;
00060 uint32_t session_count;
00061 } eq_app_t;
00062
00063
00068 typedef struct eq_serviceset_s {
00069 patnode node;
00070 uint16_t svc_set_id;
00071 patroot * applications;
00072 } eq_serviceset_t;
00073
00074 static patroot services_conf;
00075
00080 static atomic_uint_t current_time;
00081
00082
00083
00084
00085
00090 PATNODE_TO_STRUCT(service_entry, eq_serviceset_t, node)
00091
00092
00093
00097 PATNODE_TO_STRUCT(app_entry, eq_app_t, node)
00098
00099
00115 static void
00116 update_time(evContext ctx __unused,
00117 void * uap __unused,
00118 struct timespec due __unused,
00119 struct timespec inter __unused)
00120 {
00121 atomic_add_uint(1, ¤t_time);
00122 }
00123
00124
00125
00126
00127
00137 status_t
00138 init_config(evContext ctx)
00139 {
00140 patricia_root_init(&services_conf, FALSE, sizeof(uint16_t), 0);
00141
00142
00143 current_time = (atomic_uint_t)(time(NULL) - 1);
00144
00145
00146 if(evSetTimer(ctx, update_time, NULL,
00147 evNowTime(), evConsTime(1, 0), NULL)) {
00148
00149 LOG(LOG_EMERG, "%s: Failed to initialize an eventlib timer to generate "
00150 "the cached time", __func__);
00151 return EFAIL;
00152 }
00153
00154 return SUCCESS;
00155 }
00156
00160 void
00161 clear_config(void)
00162 {
00163 reset_configuration();
00164 }
00165
00166
00173 time_t
00174 get_current_time(void)
00175 {
00176 return (time_t)current_time;
00177 }
00178
00179
00183 void
00184 reset_configuration(void)
00185 {
00186 eq_serviceset_t * ss;
00187
00188 while((ss= service_entry(patricia_find_next(&services_conf, NULL)))!= NULL){
00189 delete_service_set(ss->svc_set_id);
00190 }
00191 }
00192
00193
00200 void
00201 delete_service_set(uint16_t svc_set_id)
00202 {
00203 eq_app_t * app;
00204 eq_serviceset_t * ss;
00205 eq_server_t * server;
00206
00207
00208 ss = service_entry(
00209 patricia_get(&services_conf, sizeof(svc_set_id), &svc_set_id));
00210
00211 if(ss == NULL) {
00212 LOG(LOG_WARNING, "%s: unknown service set", __func__);
00213 return;
00214 }
00215
00216
00217 if (!patricia_delete(&services_conf, &ss->node)) {
00218 LOG(LOG_ERR, "%s: Removing service set from the configuration",
00219 __func__);
00220 return;
00221 }
00222
00223 if(ss->applications == NULL) {
00224 free(ss);
00225 return;
00226 }
00227
00228 monitor_remove_all_servers_in_service_set(svc_set_id);
00229
00230 while((app= app_entry(patricia_find_next(ss->applications, NULL))) != NULL){
00231
00232 if(app->servers != NULL) {
00233 while((server = TAILQ_FIRST(app->servers)) != NULL) {
00234 TAILQ_REMOVE(app->servers, server, entries);
00235 free(server);
00236 }
00237 }
00238
00239 if(app->server_mon_params != NULL) {
00240 free(app->server_mon_params);
00241 }
00242
00243
00244 if (!patricia_delete(ss->applications, &app->node)) {
00245 LOG(LOG_ERR, "%s: Removing application from the service set failed",
00246 __func__);
00247 }
00248 free(app);
00249 }
00250
00251 patricia_root_delete(ss->applications);
00252 free(ss);
00253 }
00254
00255
00265 void
00266 delete_application(uint16_t svc_set_id,
00267 char * app_name)
00268 {
00269 eq_app_t * app;
00270 eq_serviceset_t * ss;
00271 eq_server_t * server;
00272
00273
00274 ss = service_entry(
00275 patricia_get(&services_conf, sizeof(svc_set_id), &svc_set_id));
00276
00277 if(ss == NULL) {
00278 LOG(LOG_WARNING, "%s: unknown service set", __func__);
00279 return;
00280 }
00281
00282 if(ss->applications == NULL) {
00283 return;
00284 }
00285
00286 app = app_entry(
00287 patricia_get(ss->applications, strlen(app_name) + 1, app_name));
00288
00289 if(app == NULL) {
00290 return;
00291 }
00292
00293 monitor_remove_all_servers_in_app(
00294 svc_set_id, app->application_addr, app->application_port);
00295
00296 while((server = TAILQ_FIRST(app->servers)) != NULL) {
00297 TAILQ_REMOVE(app->servers, server, entries);
00298 free(server);
00299 }
00300
00301 if(app->server_mon_params != NULL) {
00302 free(app->server_mon_params);
00303 }
00304
00305
00306 if (!patricia_delete(ss->applications, &app->node)) {
00307 LOG(LOG_ERR, "%s: Removing application from the service set failed",
00308 __func__);
00309 return;
00310 }
00311 free(app);
00312 }
00313
00314
00324 void
00325 delete_all_servers(uint16_t svc_set_id,
00326 char * app_name)
00327 {
00328 eq_app_t * app;
00329 eq_serviceset_t * ss;
00330 eq_server_t * server;
00331
00332
00333 ss = service_entry(
00334 patricia_get(&services_conf, sizeof(svc_set_id), &svc_set_id));
00335
00336 if(ss == NULL) {
00337 LOG(LOG_WARNING, "%s: unknown service set", __func__);
00338 return;
00339 }
00340
00341
00342 if(ss->applications == NULL) {
00343 LOG(LOG_WARNING, "%s: unknown application", __func__);
00344 return;
00345 }
00346
00347 app = app_entry(
00348 patricia_get(ss->applications, strlen(app_name) + 1, app_name));
00349
00350 if(app == NULL) {
00351 LOG(LOG_WARNING, "%s: unknown application", __func__);
00352 return;
00353 }
00354
00355 monitor_remove_all_servers_in_app(
00356 svc_set_id, app->application_addr, app->application_port);
00357
00358 while((server = TAILQ_FIRST(app->servers)) != NULL) {
00359 TAILQ_REMOVE(app->servers, server, entries);
00360 free(server);
00361 }
00362 }
00363
00364
00377 void
00378 delete_server(uint16_t svc_set_id,
00379 char * app_name,
00380 in_addr_t server_addr)
00381 {
00382 eq_app_t * app;
00383 eq_serviceset_t * ss;
00384 eq_server_t * server;
00385
00386
00387 ss = service_entry(
00388 patricia_get(&services_conf, sizeof(svc_set_id), &svc_set_id));
00389
00390 if(ss == NULL) {
00391 LOG(LOG_WARNING, "%s: server in unknown service set", __func__);
00392 return;
00393 }
00394
00395
00396 if(ss->applications == NULL) {
00397 LOG(LOG_WARNING, "%s: server in unknown application", __func__);
00398 return;
00399 }
00400
00401 app = app_entry(
00402 patricia_get(ss->applications, strlen(app_name) + 1, app_name));
00403
00404 if(app == NULL) {
00405 LOG(LOG_WARNING, "%s: server in unknown application", __func__);
00406 return;
00407 }
00408
00409 server = TAILQ_FIRST(app->servers);
00410 while(server != NULL) {
00411 if(server->server_addr == server_addr) {
00412 TAILQ_REMOVE(app->servers, server, entries);
00413
00414
00415 monitor_remove_server(svc_set_id, app->application_addr,
00416 app->application_port, server->server_addr);
00417
00418 free(server);
00419 return;
00420 }
00421 server = TAILQ_NEXT(server, entries);
00422 }
00423 LOG(LOG_WARNING, "%s: server is already not configured", __func__);
00424 }
00425
00426
00461 void
00462 update_application(uint16_t svc_set_id,
00463 char * app_name,
00464 in_addr_t app_addr,
00465 uint16_t app_port,
00466 uint16_t session_timeout,
00467 uint16_t connection_interval,
00468 uint16_t connection_timeout,
00469 uint8_t timeouts_allowed,
00470 uint16_t down_retry_interval)
00471 {
00472 eq_app_t * app;
00473 eq_serviceset_t * ss;
00474 eq_smon_t * smon = NULL;
00475 eq_server_t * server = NULL;
00476
00477
00478 ss = service_entry(
00479 patricia_get(&services_conf, sizeof(svc_set_id), &svc_set_id));
00480
00481 if(ss == NULL) {
00482 ss = calloc(1, sizeof(eq_serviceset_t));
00483 INSIST_ERR(ss != NULL);
00484 ss->svc_set_id = svc_set_id;
00485
00486
00487 if(!patricia_add(&services_conf, &ss->node)) {
00488 LOG(LOG_ERR, "%s: Failed to add service set %d to configuration",
00489 __func__, svc_set_id);
00490 return;
00491 }
00492 }
00493
00494
00495 if(ss->applications == NULL) {
00496
00497 ss->applications = patricia_root_init(NULL, FALSE, MAX_APP_NAME, 0);
00498 INSIST_ERR(ss->applications != NULL);
00499 }
00500
00501 app = app_entry(
00502 patricia_get(ss->applications, strlen(app_name) + 1, app_name));
00503
00504 if(connection_interval != 0) {
00505 smon = calloc(1, sizeof(eq_smon_t));
00506 INSIST_ERR(smon != NULL);
00507 smon->connection_interval = connection_interval;
00508 smon->connection_timeout = connection_timeout;
00509 smon->timeouts_allowed = timeouts_allowed;
00510 smon->down_retry_interval = down_retry_interval;
00511 }
00512
00513 if(app == NULL) {
00514 app = calloc(1, sizeof(eq_app_t));
00515 INSIST_ERR(app != NULL);
00516 strncpy(app->application_name, app_name, MAX_APP_NAME);
00517
00518
00519 patricia_node_init_length(&app->node, strlen(app_name) + 1);
00520
00521 if(!patricia_add(ss->applications, &app->node)) {
00522 LOG(LOG_ERR, "%s: Failed to add application %s to "
00523 "configuration", __func__, app_name);
00524 return;
00525 }
00526
00527 app->servers = malloc(sizeof(server_list_t));
00528 INSIST_ERR(app->servers != NULL);
00529 TAILQ_INIT(app->servers);
00530
00531 app->server_mon_params = smon;
00532 app->application_port = app_port;
00533 app->application_addr = app_addr;
00534 app->session_timeout = session_timeout;
00535
00536 LOG(LOG_INFO, "%s: Added new application <%d,%s> to configuration",
00537 __func__, svc_set_id, app_name);
00538
00539 return;
00540 }
00541
00542
00543
00544 app->session_timeout = session_timeout;
00545
00546 if(app->application_port != app_port || app->application_addr != app_addr) {
00547
00548
00549 monitor_remove_all_servers_in_app(
00550 svc_set_id, app->application_addr, app->application_port);
00551
00552 app->application_port = app_port;
00553 app->application_addr = app_addr;
00554
00555 server = TAILQ_FIRST(app->servers);
00556 while(server != NULL) {
00557
00558 monitor_add_server(svc_set_id, app->application_addr,
00559 app->application_port, server->server_addr,
00560 app->server_mon_params);
00561
00562 server = TAILQ_NEXT(server, entries);
00563 }
00564 }
00565
00566 if(app->server_mon_params == NULL) {
00567 if(smon != NULL) {
00568 change_monitoring_config(svc_set_id, app_addr, app_port, smon);
00569 app->server_mon_params = smon;
00570 }
00571 } else {
00572 if(smon == NULL) {
00573 change_monitoring_config(svc_set_id, app_addr, app_port, smon);
00574 free(app->server_mon_params);
00575 app->server_mon_params = NULL;
00576 } else {
00577 if(memcmp(smon, app->server_mon_params, sizeof(eq_smon_t)) != 0) {
00578 change_monitoring_config(svc_set_id, app_addr, app_port, smon);
00579 free(app->server_mon_params);
00580 app->server_mon_params = smon;
00581 } else {
00582 free(smon);
00583 }
00584 }
00585 }
00586 }
00587
00588
00601 void
00602 add_server(uint16_t svc_set_id,
00603 char * app_name,
00604 in_addr_t server_addr)
00605 {
00606 eq_app_t * app;
00607 eq_serviceset_t * ss;
00608 eq_server_t * server = NULL;
00609
00610
00611 ss = service_entry(
00612 patricia_get(&services_conf, sizeof(svc_set_id), &svc_set_id));
00613
00614 if(ss == NULL) {
00615 LOG(LOG_ERR, "%s: server in unknown service set %d", __func__,
00616 svc_set_id);
00617 return;
00618 }
00619
00620
00621 if(ss->applications == NULL) {
00622 LOG(LOG_ERR, "%s: server in unknown application", __func__);
00623 return;
00624 }
00625
00626 app = app_entry(
00627 patricia_get(ss->applications, strlen(app_name) + 1, app_name));
00628
00629 if(app == NULL) {
00630 LOG(LOG_ERR, "%s: server in unknown application", __func__);
00631 return;
00632 }
00633
00634 server = TAILQ_FIRST(app->servers);
00635 while(server != NULL) {
00636 if(server->server_addr == server_addr) {
00637 return;
00638 }
00639 server = TAILQ_NEXT(server, entries);
00640 }
00641
00642 server = malloc(sizeof(eq_server_t));
00643 INSIST_ERR(server != NULL);
00644 server->server_addr = server_addr;
00645 TAILQ_INSERT_TAIL(app->servers, server, entries);
00646
00647
00648 monitor_add_server(svc_set_id, app->application_addr, app->application_port,
00649 server_addr, app->server_mon_params);
00650 }
00651
00652
00669 char *
00670 get_app_name(uint16_t svc_set_id, in_addr_t addr, uint16_t port)
00671 {
00672 eq_app_t * app;
00673 eq_serviceset_t * ss;
00674
00675
00676 ss = service_entry(
00677 patricia_get(&services_conf, sizeof(svc_set_id), &svc_set_id));
00678
00679 if(ss == NULL || ss->applications == NULL) {
00680 return NULL;
00681 }
00682
00683
00684 app = app_entry(patricia_find_next(ss->applications, NULL));
00685
00686 while(app != NULL) {
00687
00688 if(app->application_addr == addr && app->application_port == port) {
00689 return app->application_name;
00690 }
00691
00692 app = app_entry(patricia_find_next(ss->applications, &app->node));
00693 }
00694
00695 return NULL;
00696 }
00697
00698
00716 uint16_t
00717 get_app_session_timeout(uint16_t svc_set_id, in_addr_t addr, uint16_t port)
00718 {
00719 eq_app_t * app;
00720 eq_serviceset_t * ss;
00721
00722
00723 ss = service_entry(
00724 patricia_get(&services_conf, sizeof(svc_set_id), &svc_set_id));
00725
00726 if(ss == NULL || ss->applications == NULL) {
00727 return 0;
00728 }
00729
00730
00731 app = app_entry(patricia_find_next(ss->applications, NULL));
00732
00733 while(app != NULL) {
00734
00735 if(app->application_addr == addr && app->application_port == port) {
00736 return app->session_timeout;
00737 }
00738
00739 app = app_entry(patricia_find_next(ss->applications, &app->node));
00740 }
00741
00742 return 0;
00743 }