a0719632260d5b2074d3d8edb9f080d6b20a3745
[Evergreen.git] / Open-ILS / src / c-apps / oils_dataloader.c
1 #include <opensrf/osrf_app_session.h>
2 #include <opensrf/osrf_system.h>
3 #include <opensrf/osrfConfig.h>
4 #include <opensrf/utils.h>
5 #include <opensrf/osrf_hash.h>
6
7 #include <stdio.h>
8
9 #include "openils/oils_idl.h"
10 #include "openils/oils_utils.h"
11
12 #define CSTORE "open-ils.cstore"
13 #define APPNAME "oils_dataloader"
14
15 #define E_SUCCESS 0
16 #define E_COMMITERROR -1
17 #define E_COMMANDERROR -2
18 #define E_ROLLBACKERROR -3
19
20 static int sendCommand ( const char* );
21 static int startTransaction ( );
22 static int commitTransaction ( );
23 static int rollbackTransaction ( );
24
25
26 static osrfHash* mnames = NULL;
27 static osrfAppSession* session = NULL;
28 static char* trans_id = NULL;
29
30 int main (int argc, char **argv) {
31         if( argc < 4 ) {
32                 fprintf( stderr, "Usage: %s <path_to_config_file> <config_context> <create|update|delete>\n", argv[0] );
33                 exit(0);
34         }
35
36         mnames = osrfNewHash();
37
38         char* config = strdup( argv[1] );
39         char* context = strdup( argv[2] );
40         char* method = strdup( argv[3] );
41
42         if (strcmp(method, "create") && strcmp(method, "update") && strcmp(method, "delete")) {
43                 osrfLogError(OSRF_LOG_MARK, "Bad method name!  Use create, update, or delete.");
44                 exit(1);
45         }
46
47         // connect to the network
48         osrfLogInfo(OSRF_LOG_MARK, "Launching data loader with config %s and config context %s", config, context );
49         if (!osrfSystemBootstrapClientResc( config, context, APPNAME )) {
50                 osrfLogError(OSRF_LOG_MARK, "Unable to bootstrap data loader!");
51                 exit(1);
52         }
53
54         // Load the IDL
55         osrfHash* idl;
56         char* idl_filename = osrfConfigGetValue(NULL, "/IDL");
57
58         if (!(idl = oilsIDLInit( idl_filename ))) {
59                 osrfLogError(OSRF_LOG_MARK, "Unable to load IDL!");
60                 exit(1);
61         }
62
63         // Generate "create" method name for each 
64         osrfStringArray* classes = osrfHashKeys(idl);
65         int c_index = 0;
66         char* classname;
67         char* st_tmp;
68
69         while ((classname = osrfStringArrayGetString(classes, c_index++))) {
70                 osrfHash* idlClass = oilsIDLFindPath("/%s", classname);
71
72                 char* _fm = strdup( (char*)osrfHashGet(idlClass, "fieldmapper") );
73                 char* part = strtok_r(_fm, ":", &st_tmp);
74
75                 growing_buffer* _method_name =  buffer_init(64);
76                 buffer_fadd(_method_name, "%s.direct.%s", CSTORE, part);
77
78                 while ((part = strtok_r(NULL, ":", &st_tmp))) {
79                         buffer_fadd(_method_name, ".%s", part);
80                 }
81                 buffer_fadd(_method_name, ".%s", method);
82
83                 char* m = buffer_release(_method_name);
84                 osrfHashSet( mnames, m, classname );
85
86                 osrfLogDebug(OSRF_LOG_MARK, "Constructed %s method named %s for %s", method, m, classname);
87
88                 free(_fm);
89         }
90
91         free(config);
92         free(context);
93         free(idl_filename);
94
95         // Connect to open-ils.cstore
96         session = osrfAppSessionClientInit(CSTORE);
97         osrfAppSessionConnect(session);
98
99         // Start a transaction
100         if (!startTransaction()) {
101                 osrfLogError(OSRF_LOG_MARK, "An error occured while attempting to start a transaction");
102         }
103
104         growing_buffer* json = buffer_init(128);
105         char* json_string;
106         int c;
107         int counter = 0;
108         while ((c = getchar())) {
109                 switch(c) {
110                         case '\n':
111                         case EOF:
112                                 // End of a line
113                                 json_string = buffer_data(json);
114                                 buffer_reset(json);
115
116                                 if (!sendCommand(json_string)) {
117                                         osrfLogError(
118                                                 OSRF_LOG_MARK,
119                                                 "An error occured while attempting to %s an object: [%s]",
120                                                 method,
121                                                 json_string
122                                         );
123
124                                         if (!rollbackTransaction()) {
125                                                 osrfAppSessionFree(session);
126                                                 osrfLogError(OSRF_LOG_MARK, "An error occured while attempting to complete a transaction");
127                                                 return E_ROLLBACKERROR;
128                                         }
129
130                                         osrfAppSessionFree(session);
131                                         return E_COMMANDERROR;
132                                 }
133
134                                 counter++;
135
136                                 buffer_reset(json);
137                                 free(json_string);
138                                 break;
139
140                         default:
141                                 buffer_add_char( json, c );
142                                 break;
143                 }
144         }
145
146         buffer_free(json);
147
148         // clean up, commit, go away
149         if (!commitTransaction()) {
150                 osrfLogError(OSRF_LOG_MARK, "An error occured while attempting to complete a transaction");
151                 osrfAppSessionFree(session);
152                 return E_COMMITERROR;
153         }
154
155         osrfAppSessionFree(session);
156         free(method);
157
158         return E_SUCCESS;
159 }
160
161 static int commitTransaction () {
162         int ret = 1;
163         const jsonObject* data;
164         int req_id = osrfAppSessionMakeRequest( session, NULL, "open-ils.cstore.transaction.commit", 1, NULL );
165         osrfMessage* res = osrfAppSessionRequestRecv( session, req_id, 5 );
166         if ( (data = osrfMessageGetResult(res)) ) {
167                 if(!(trans_id = jsonObjectGetString(data))) {
168                         ret = 0;
169                 }
170         } else {
171                 ret = 0;
172         }
173         osrfMessageFree(res);
174
175         return ret;
176 }
177
178 static int rollbackTransaction () {
179         int ret = 1;
180         const jsonObject* data;
181         int req_id = osrfAppSessionMakeRequest( session, NULL, "open-ils.cstore.transaction.rollback", 1, NULL );
182         osrfMessage* res = osrfAppSessionRequestRecv( session, req_id, 5 );
183         if ( (data = osrfMessageGetResult(res)) ) {
184                 if(!(trans_id = jsonObjectGetString(data))) {
185                         ret = 0;
186                 }
187         } else {
188                 ret = 0;
189         }
190         osrfMessageFree(res);
191
192         return ret;
193 }
194
195 static int startTransaction () {
196         int ret = 1;
197         jsonObject* data;
198         int req_id = osrfAppSessionMakeRequest( session, NULL, "open-ils.cstore.transaction.begin", 1, NULL );
199         osrfMessage* res = osrfAppSessionRequestRecv( session, req_id, 5 );
200         if ( (data = osrfMessageGetResult(res)) ) {
201                 if(!(trans_id = jsonObjectToSimpleString(data))) {
202                         ret = 0;
203                 }
204         } else {
205                 ret = 0;
206         }
207         osrfMessageFree(res);
208
209         return ret;
210 }
211
212 static int sendCommand ( const char* json ) {
213         int ret = 1;
214         jsonObject* item = jsonParseString(json);
215
216         if (!item->classname) {
217                 osrfLogError(OSRF_LOG_MARK, "Data loader cannot handle unclassed objects.  Skipping [%s]!", json);
218                 jsonObjectFree(item);
219                 return 0;
220         }
221
222         // Get the method name...
223         char* method_name = osrfHashGet( mnames, item->classname );
224         osrfLogDebug(OSRF_LOG_MARK, "Calling %s -> %s for %s", CSTORE, method_name, item->classname);
225
226         // make the param array
227         jsonObject* params = jsonParseString("[]");
228         jsonObjectSetIndex( params, 0, item );
229         jsonObjectSetIndex( params, 1, jsonParseString("{\"quiet\":\"true\"}") );
230
231         jsonObject* data;
232         int req_id = osrfAppSessionMakeRequest( session, params, method_name, 1, NULL );
233         jsonObjectFree(params);
234
235         osrfMessage* res = osrfAppSessionRequestRecv( session, req_id, 5 );
236
237         if (res) {
238                 if ( !(data = osrfMessageGetResult(res)) ) {
239                         ret = 0;
240                 }
241                 osrfMessageFree(res);
242         } else {
243                 ret = 0;
244         }
245
246         return ret;
247 }