equilibrium-data_config.c

Go to the documentation of this file.
00001 /*
00002  * $Id: equilibrium-data_config.c 346460 2009-11-14 05:06:47Z ssiano $
00003  *
00004  * This code is provided as is by Juniper Networks SDK Developer Support.
00005  * It is provided with no warranties or guarantees, and Juniper Networks
00006  * will not provide support or maintenance of this code in any fashion.
00007  * The code is provided only to help a developer better understand how
00008  * the SDK can be used.
00009  * 
00010  * Copyright (c) 2008, Juniper Networks, Inc.
00011  * All rights reserved.
00012  */
00013 
00023 #include "equilibrium-data_main.h"
00024 #include "equilibrium-data_config.h"
00025 #include "equilibrium-data_monitor.h"
00026 
00027 
00028 /*** Constants ***/
00029 
00030 
00031 /*** Data structures ***/
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 /*** STATIC/INTERNAL Functions ***/
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, &current_time);
00122 }
00123 
00124 
00125 /*** GLOBAL/EXTERNAL Functions ***/
00126 
00127 
00137 status_t
00138 init_config(evContext ctx)
00139 {
00140     patricia_root_init(&services_conf, FALSE, sizeof(uint16_t), 0);
00141                    // root, is key ptr, key size, key offset
00142 
00143     current_time = (atomic_uint_t)(time(NULL) - 1);
00144     
00145     // cached system time
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     // get this service-set
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     // Remove ss from patricia tree of the service sets
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         // Remove app from patricia tree of the service set
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     // get this service-set
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     // Remove app from patricia tree of the service set
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     // get this service-set
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     // check if any applications config exists
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     // get this service-set
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     // check if any applications config exists
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); // got it
00413             
00414             // tell the monitor about this server being removed
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     // check if we know about this service-set
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         // Add to patricia tree (without node length init) since it is fixed
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     // check if any applications config exists
00495     if(ss->applications == NULL) {
00496         // if not, init it
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         // Add to patricia tree
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     // it is now new, so we need to check for changes
00543     
00544     app->session_timeout = session_timeout;
00545     
00546     if(app->application_port != app_port || app->application_addr != app_addr) {
00547         
00548         // delete server and re-add them
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) { // added
00568             change_monitoring_config(svc_set_id, app_addr, app_port, smon);
00569             app->server_mon_params = smon;
00570         }
00571     } else { // existing monitor, look for a change
00572         if(smon == NULL) { // removed
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); // no change to existing monitor parameters
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     // get this service-set
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     // check if any applications config exists
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; // already know about this server
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     // tell the monitor about this new server
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     // get this service-set
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     // get first application
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     // get this service-set
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     // get first application
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 }

2007-2009 Juniper Networks, Inc. All rights reserved. The information contained herein is confidential information of Juniper Networks, Inc., and may not be used, disclosed, distributed, modified, or copied without the prior written consent of Juniper Networks, Inc. in an express license. This information is subject to change by Juniper Networks, Inc. Juniper Networks, the Juniper Networks logo, and JUNOS are registered trademarks of Juniper Networks, Inc. in the United States and other countries. All other trademarks, service marks, registered trademarks, or registered service marks are the property of their respective owners.
Generated on Sun May 30 20:26:56 2010 for SDK Your Net Corporation Equilibrium Load Balancer Example: equilibrium-data 1.0 by Doxygen 1.5.1