Replace calls to osrfAppSessionMakeRequest() with
[OpenSRF.git] / src / libopensrf / osrf_settings.c
1 /**
2         @file osrf_settings.c
3         @brief Facility for retrieving server configuration settings.
4 */
5 #include <opensrf/osrf_settings.h> 
6
7 /**
8         @brief Stores a copy of server configuration settings as a jsonObject.
9
10         It also stores the host name of the settings server which supplied the configuration
11         settings.  In practice nothing uses the stored copy of the host name.
12 */
13 struct osrf_host_config_ {
14         /** @brief The host name of the settings server */
15         char* hostname;
16         /** @brief The configuration settings as a jsonObject */
17 jsonObject* config;
18 };
19
20 static osrf_host_config* osrf_settings_new_host_config(const char* hostname);
21
22 static osrf_host_config* config = NULL;
23
24 /**
25         @brief Fetch a specified string from an already-loaded configuration.
26         @param format A printf-style format string.  Subsequent parameters, if any, will be formatted
27                 and inserted into the format string.
28         @return If the value is found, a pointer to a newly-allocated string containing the value;
29                 otherwise NULL.
30
31         The format string, after expansion, defines a search path through a configuration previously
32         loaded and stored as a jsonObject.
33
34         The configuration must have been already been loaded via a call to osrf_settings_retrieve()
35         (probably via a call to osrfSystemBootstrap()).  Otherwise this function will call exit()
36         immediately.
37
38         The calling code is responsible for freeing the string.
39 */
40 char* osrf_settings_host_value(const char* format, ...) {
41         VA_LIST_TO_STRING(format);
42
43         if( ! config ) {
44                 const char * msg = "NULL config pointer; looking for config_context ";
45                 fprintf( stderr, "osrf_settings_host_value: %s\"%s\"\n",
46                         msg, VA_BUF );
47                 osrfLogError( OSRF_LOG_MARK, "%s\"%s\"", msg, VA_BUF );
48                 exit( 99 );
49         }
50
51         jsonObject* o = jsonObjectFindPath(config->config, VA_BUF);
52         char* val = jsonObjectToSimpleString(o);
53         jsonObjectFree(o);
54         return val;
55 }
56
57 /**
58         @brief Fetch a specified subset of an already-loaded configuration.
59         @param format A printf-style format string.  Subsequent parameters, if any, will be formatted
60                 and inserted into the format string.
61         @return If the value is found, a pointer to a newly created jsonObject containing the
62                 specified subset; otherwise NULL.
63
64         The format string, after expansion, defines a search path through a configuration previously
65         loaded and stored as a jsonObject.
66
67         The configuration must have been already been loaded via a call to osrf_settings_retrieve()
68         (probably via a call to osrfSystemBootstrap()).  Otherwise this function will call exit()
69         immediately.
70
71         The calling code is responsible for freeing the jsonObject.
72  */
73 jsonObject* osrf_settings_host_value_object(const char* format, ...) {
74         VA_LIST_TO_STRING(format);
75
76         if( ! config ) {
77                 const char * msg = "config pointer is NULL; looking for config context ";
78                 fprintf( stderr, "osrf_settings_host_value_object: %s\"%s\"\n",
79                         msg, VA_BUF );
80                 osrfLogError( OSRF_LOG_MARK, "%s\"%s\"", msg, VA_BUF );
81                 exit( 99 );
82         }
83
84         return jsonObjectFindPath(config->config, VA_BUF);
85 }
86
87
88 /**
89         @brief Look up the configuration settings and cache them for future reference.
90         @param hostname The host name for the settings server.
91         @return Zero if successful, or -1 if not.
92
93         The configuration settings come from a settings server.  This arrangement is intended for
94         use by servers, so that all server settings can be stored in a single location.  Typically
95         a client process (that is not also a server in its own right) will read its own
96         configuration file locally.
97
98         The settings are cached as a jsonObject for future lookups by the functions
99         osrf_settings_host_value() and osrf_settings_host_value_object().
100
101         The calling code is responsible for freeing the cached settings by calling
102         osrf_settings_free_host_config().
103  */
104 int osrf_settings_retrieve(const char* hostname) {
105
106         if(!config) {
107
108                 osrfAppSession* session = osrfAppSessionClientInit("opensrf.settings");
109                 jsonObject* params = jsonNewObject(NULL);
110                 jsonObjectPush(params, jsonNewObject(hostname));
111                 int req_id = osrfAppSessionSendRequest( 
112                         session, params, "opensrf.settings.host_config.get", 1 );
113                 osrfMessage* omsg = osrfAppSessionRequestRecv( session, req_id, 60 );
114                 jsonObjectFree(params);
115
116                 if(!omsg) {
117                         osrfLogError( OSRF_LOG_MARK, "No osrfMessage received from host %s (timeout?)", hostname);
118                 } else if(!omsg->_result_content) {
119                         osrfMessageFree(omsg);
120                         osrfLogError(
121                                 OSRF_LOG_MARK,
122                         "NULL or non-existent osrfMessage result content received from host %s, "
123                                 "broken message or no settings for host",
124                                 hostname
125                         );
126                 } else {
127                         config = osrf_settings_new_host_config(hostname);
128                         config->config = jsonObjectClone(omsg->_result_content);
129                         osrfMessageFree(omsg);
130                 }
131
132                 osrf_app_session_request_finish( session, req_id );
133                 osrfAppSessionFree( session );
134
135                 if(!config) {
136                         osrfLogError( OSRF_LOG_MARK, "Unable to load config for host %s", hostname);
137                         return -1;
138                 }
139         }
140
141         return 0;
142 }
143
144 /**
145         @brief Allocate and initialize an osrf_host_config for a given host name.
146         @param hostname Pointer to a host name.
147         @return Pointer to a newly created osrf_host_config.
148 */
149 static osrf_host_config* osrf_settings_new_host_config(const char* hostname) {
150         if(!hostname) return NULL;
151         osrf_host_config* c = safe_malloc(sizeof(osrf_host_config));
152         c->hostname = strdup(hostname);
153         c->config = NULL;
154         return c;
155 }
156
157 /**
158         @brief Deallocate an osrf_host_config and its contents.
159         @param c A pointer to the osrf_host_config to be deallocated.
160 */
161 void osrf_settings_free_host_config(osrf_host_config* c) {
162         if( !c ) {
163                 c = config;
164                 config = NULL;
165         }
166         if( c ) {
167                 free(c->hostname);
168                 jsonObjectFree(c->config);
169                 free(c);
170         }
171 }