]> andersk Git - moira.git/blob - gdb/gdb_db.c
5d8727eecb9feb3803433ae49d05010ff72235e3
[moira.git] / gdb / gdb_db.c
1 /*
2  *      $Source$
3  *      $Header$
4  */
5
6 #ifndef lint
7 static char *rcsid_gdb_db_c = "$Header$";
8 #endif  lint
9
10 /************************************************************************/
11 /*      
12 /*                              gdb_db.c
13 /*      
14 /*      Authors: Susan Ryan and Noah Mendelsohn
15 /*      
16 /*      Copyright: 1986 MIT Project Athena
17 /*      
18 /************************************************************************/
19
20 #include <stdio.h>
21 #include <strings.h>
22 #include "gdb.h"
23
24
25
26 \f/************************************************************************/
27 /*      
28 /*                              start_accessing_db (start_accessing_db)
29 /*      
30 /*      1) Creates a new db structure to describe the database.
31 /*      
32 /*      2) Parses the supplied db_ident into a server and a db name
33 /*      
34 /*      3) Opens a connection to the server, sending the name of the 
35 /*         database as an argument
36 /*      
37 /*      4) Asynchronously receives a return code from the server
38 /*         to indicate whether the database could be accessed
39 /*      
40 /*      5) If successful, the handle on the new structure is placed into
41 /*         the variable supplied by the caller.  Otherwise, the structure
42 /*         is de_allocated and failure status is returned to the caller.
43 /*      
44 /*      Note: this code was adapted from an earlier synchronous 
45 /*            implementation and there may yet be some loose ends.
46 /*      
47 /************************************************************************/
48
49 #define MIN_NAME_LEN 1   /*completely arbitrary */
50 #define FAILURE NULL /*until we decide what it should really be */
51                      /*note if fails returns NULL for the db_handle value*/
52                      /*as per above     */
53
54 DATABASE g_make_db();
55 int g_iadb();
56
57 struct adb_data {
58         DATABASE db;
59         OPERATION get_retcode;
60 };
61
62 int
63 start_accessing_db (op, db_ident, db_handle)
64 OPERATION op;
65 char *db_ident;
66 DATABASE *db_handle;               
67 {
68         /*----------------------------------------------------------*/
69         /*      
70         /*                      Declarations
71         /*      
72         /*----------------------------------------------------------*/
73
74         register DATABASE db;                   /* the newly created */
75                                                 /* structure */
76         register struct adb_data *arg;          /* holds our state */
77                                                 /* during async operation*/
78         char *ident, *server, *temp_server;     /* loop variables for */
79                                                 /* parsing*/
80         char *db_name, *temp_name;
81         int count;                              /* counts chars during parse */
82
83         CONNECTION connexn;                     /* the connection to the */
84                                                 /* database server*/
85
86         /*----------------------------------------------------------*/
87         /*      
88         /*                  Execution begins here
89         /*      
90         /*      Make sure parameters are correct, then allocate a
91         /*      structure.
92         /*      
93         /*----------------------------------------------------------*/
94
95         GDB_INIT_CHECK
96
97         db_name = NULL;
98         temp_name = NULL;
99         ident = NULL ;
100         server = NULL;
101
102         GDB_CHECK_OP(op, "start_accessing_db")
103
104         if ((db_ident == NULL)|| (strlen(db_ident)<MIN_NAME_LEN)) {
105                 fprintf (gdb_log,"access_db: correct syntax is db_name@server \n");
106                 *db_handle = NULL;
107                 return (OP_CANCELLED);
108         }
109
110         db = g_make_db();
111         *db_handle = db;
112
113         /*----------------------------------------------------------*/
114         /*      
115         /*      Loop to count lengths of server and database names
116         /*      Allocate space for each and copy them both
117         /*      
118         /*----------------------------------------------------------*/
119
120         count = 1;
121         ident = db_ident;
122         while (*ident++ != '@') {
123                 count++;
124         }
125
126         db_name = db_alloc (count);             /* space for db_name */
127                                                 /* note: this is cleaned */
128                                                 /* up by the tear down rtn*/
129
130         count = 1;
131         while (*ident++ != '\0') 
132                 count++;
133
134         count += strlen(GDB_DB_SERVICE)+1;      /* leave room for :service */
135         server = db_alloc (count);              /* space for host:service */
136                                                 /* note: this is cleaned */
137                                                 /* up by the tear down rtn*/
138
139        /*
140         * copy head of db_ident string from db_name@server to db_name
141         */
142         temp_name = db_name;
143         while (*db_ident != '@') {
144                 *temp_name = *db_ident;
145                 temp_name++;
146                 db_ident++;
147         }
148         *temp_name = '\0';
149
150         db->name = db_name;                              
151
152        /*
153         * Set up server host name
154         */
155         temp_server = server;   
156         db_ident++;                             /* skip the '@' */
157         while (*db_ident!= '\0') {
158                 *temp_server = *db_ident;
159                 temp_server++;
160                 db_ident++;     
161         }
162
163        /*
164         * Append :service id to the server host name
165         */
166         *temp_server++ = ':';
167         *temp_server = '\0';
168         (void) strcat(server, GDB_DB_SERVICE);
169
170         db->server = server;
171
172
173         /*----------------------------------------------------------*/
174         /*      
175         /*      Create a connection to the server.
176         /*      
177         /*----------------------------------------------------------*/
178
179         connexn = start_server_connection (server, db_name);
180
181         if (connexn==NULL || connection_status(connexn) != CON_UP) {
182              connection_perror(connexn, "Error starting server connection");
183              fprintf (gdb_log, "gdb:access_db: couldn't connect to server %s \n", server);
184              g_tear_down(*db_handle);
185              OP_STATUS(op) = OP_CANCELLED;
186              return (OP_CANCELLED);
187         }
188
189         db->connection = connexn;
190
191        /*
192         * Start asynchronously receiving the return code from the 
193         * data base server.  May take awhile, since ingres is so
194         * slow to start up.
195         */
196
197         arg = (struct adb_data *)db_alloc(sizeof(struct adb_data));
198         arg->get_retcode = create_operation();
199         arg->db = db;
200
201         start_receiving_object (arg->get_retcode, connexn, 
202                                 (char *)&(OP_RESULT(op)), INTEGER_T);   
203        /*
204         * Error handling
205         */
206         if (OP_STATUS(arg->get_retcode) == OP_CANCELLED) {
207             g_tear_down (*db_handle);
208             OP_STATUS(op) = OP_CANCELLED;
209             delete_operation(arg->get_retcode);
210             db_free((char *)arg, sizeof(struct adb_data));
211             return OP_CANCELLED;
212         }
213
214        /*
215         * We've successfully queued the receive of the return code.
216         * That's about all we have to do if things go well, but if the
217         * operation fails later, we have to be there to clean up.  To
218         * get control back, we queue ourselves as a second operation
219         * so we can see how the first did, and so we can free up arg.
220         */
221         initialize_operation(op, g_iadb, (char *)arg, (int (*)())NULL); 
222         (void) queue_operation(connexn, CON_INPUT, op);
223
224         return OP_RUNNING;              
225 }
226
227         /*----------------------------------------------------------*/
228         /*      
229         /*                      g_iadb
230         /*      
231         /*      Init routine for getting return code on accessing a
232         /*      database.  If all went well, (or even if it didn't), then
233         /*      we are done.  All we have to do is clean up the stuff we've
234         /*      allocated.
235         /*      
236         /*----------------------------------------------------------*/
237
238 int
239 g_iadb(op, hcon, arg)
240 OPERATION op;
241 HALF_CONNECTION hcon;
242 struct adb_data *arg;
243 {
244         int rc;
245
246        /*
247         * Figure out how the receipt went
248         */
249         rc = OP_STATUS(arg->get_retcode);
250
251        /*
252         * Release all transient data structures.
253         */
254         if (rc != OP_COMPLETE || op->result != DB_OPEN)
255                 g_tear_down(arg->db);
256         else
257                 DB_STATUS(arg->db) = DB_OPEN;
258           
259         delete_operation(arg->get_retcode);
260         db_free((char *)arg, sizeof(struct adb_data));
261         
262         return rc;
263 }
264 \f
265 /************************************************************************/
266 /*      
267 /*                      g_tear_down
268 /*      
269 /*      this is called by access_db and perf_db_op when a fatal error 
270 /*      is reached. It is an attempt to intelligently handle the error,
271 /*      and tear down connections and data structures if necessary.
272 /*      
273 /*      The current version simply tears down everything, perhaps later
274 /*      versions should make provision for closing the db as necessary,
275 /*      and/or other less drastic ways to handle the errors.
276 /*       
277 /************************************************************************/
278
279 int
280 g_tear_down (db_handle)
281 DATABASE db_handle;
282 {
283         register DATABASE db = db_handle; 
284
285         /*----------------------------------------------------------*/
286         /*      
287         /*      If the db is opened, and the connexn is severed, 
288         /*      some error handling, closing of the db should be done 
289         /*      at the server.
290         /*      
291         /*      Also, at the server, perhaps a return code to indicate
292         /*      that user tried to open non-existant db???
293         /*      
294         /*----------------------------------------------------------*/
295           
296
297         if (db==NULL)
298                 return;
299
300
301         (void) sever_connection (db->connection);
302
303        /*
304         * Free up the separately allocated strings to which the
305         * database descriptor points
306         */
307         gdb_fstring(db->server);
308         gdb_fstring(db->name);
309
310        /*
311         * Free the descriptor itself
312         */
313         db_free ((char *)db,sizeof(struct db_struct));
314         return;
315 }
316 \f
317 /************************************************************************/
318 /*      
319 /*                        g_make_db
320 /*      
321 /*      Allocate and initialize a database descriptor structure.
322 /*      
323 /************************************************************************/
324
325 DATABASE
326 g_make_db()
327 {
328         register DATABASE db;
329
330         db = (DATABASE)db_alloc (sizeof(struct db_struct));
331         db->id = GDB_DB_ID;
332         db->connection = NULL;
333         db->name = NULL;
334         db->server = NULL;
335         DB_STATUS(db) = DB_CLOSED;
336         
337         return db;
338 }
339 \f/************************************************************************/
340 /*      
341 /*                              access_db (access_db)
342 /*      
343 /*      Does a start_accessing_db and waits for it to complete.
344 /*      
345 /************************************************************************/
346
347 int
348 access_db (db_ident, db_handle)
349 char *db_ident;
350 DATABASE *db_handle;               
351 {
352         register OPERATION op;
353         register int status;
354         register int result;
355
356         GDB_INIT_CHECK
357
358        /*
359         * Create an operation and use it to asynchronously access
360         * the database
361         */
362         op = create_operation();
363         (void) start_accessing_db(op, db_ident, db_handle);
364
365        /*
366         * Wait for it to complete, note whether the operation completed
367         * at all, and if so, whether it returned a successful result
368         * in accessing the database.  Then reclaim the space used for
369         * the operation.
370         */
371         (void) complete_operation(op);
372         status = OP_STATUS(op);
373         result = OP_RESULT(op);
374
375         delete_operation(op);
376
377        /*
378         * Tell the caller either that we were interrupted, or pass
379         * on the actual result of accessing the database.  If it
380         * failed, then tear everything down after all.
381         */
382         if (status==OP_COMPLETE)
383                 return result;
384         else
385                 return status;
386 }
387 \f/************************************************************************/
388 /*      
389 /*                start_performing_db_operation (start_performing_db_operation)
390 /*      
391 /*      Asynchronously performs  any operation except for a query
392 /*      on the remote database.
393 /*      
394 /*      The operation is encoded as a GDB string and sent to the server.
395 /*      
396 /*      An integer return code is received back and returned to the caller.
397 /*      
398 /*      Note that this operation executes on both the outbound and inbound
399 /*      half connections.  Since there is no explicit sync between the two
400 /*      directions, operations like this pipeline freely from requestor
401 /*      to server, but there is no way to cancel this operation once it
402 /*      has started without severing the accompanying connection.
403 /*      
404 /************************************************************************/
405
406 int g_ipdb();
407
408 struct pdb_data {
409         DATABASE db;                            /* the database we're */
410                                                 /* working on */
411         OPERATION send_request;                 /* used to send the string */
412                                                 /* containing the db oper. */
413                                                 /* to be performed */
414         OPERATION get_retcode;                  /* used to get back the */
415                                                 /* response to our request */
416         STRING s;                               /* the operation string */
417                                                 /* itself.  This is sent. */
418 };
419
420 #define MIN_REQUEST_LEN 1 /*completely arbitrary */
421 #undef FAILURE
422 #define FAILURE -1
423
424 int
425 start_performing_db_operation (op, db_handle,request)
426 OPERATION op;
427 DATABASE db_handle; 
428 char *request;
429 {
430         /*----------------------------------------------------------*/
431         /*      
432         /*                      Declarations
433         /*      
434         /*----------------------------------------------------------*/
435
436         register struct pdb_data *arg;          /* holds our state */
437                                                 /* during async operation*/
438         register DATABASE db = db_handle;       /* fast working copy */
439
440         /*----------------------------------------------------------*/
441         /*      
442         /*                  Execution begins here
443         /*      
444         /*      Make sure parameters are correct, then allocate a
445         /*      structure.
446         /*      
447         /*----------------------------------------------------------*/
448
449         GDB_CHECK_OP(op, "start_performing_db_operation ")
450         if (db==NULL) {
451                 fprintf (gdb_log, "gdb: start_performing_db_operation: supplied database is NULL\n");
452                 OP_STATUS(op) = OP_CANCELLED;
453                 return OP_CANCELLED;
454         }
455
456         GDB_CHECK_DB(db, "start_performing_db_operation")
457
458         if (DB_STATUS(db) != DB_OPEN) {
459                 fprintf (gdb_log, "gdb: start_performing_db_operation: request to closed database ");
460                 OP_STATUS(op) = OP_CANCELLED;
461                 return OP_CANCELLED;
462         }
463
464         if (db->connection == NULL) {
465                 fprintf (gdb_log,
466                          "gdb: start_performing_db_operation: connection severed, request cancelled\n");
467                 OP_STATUS(op) = OP_CANCELLED;
468                 return OP_CANCELLED;
469         }
470
471         if (connection_status(db->connection) != CON_UP ) {
472                 fprintf (gdb_log, "gdb: start_performing_db_operation: problems maintaining connection ");
473                 connection_perror(db->connection, "Reason for connection failure");
474                 fprintf (gdb_log, "request cancelled \n");
475                 OP_STATUS(op) = OP_CANCELLED;
476                 return OP_CANCELLED;
477         }
478
479         if ((request == NULL) || (strlen (request)<MIN_REQUEST_LEN)) { 
480                 fprintf (gdb_log, "gdb: start_performing_db_operation: request either missing or too short\n");
481                 OP_STATUS(op) = OP_CANCELLED;
482                 return OP_CANCELLED;
483                   /*should we disallow empty requests? */
484         }
485
486
487         /*----------------------------------------------------------*/
488         /*      
489         /*      Asynchronously send the request to the server
490         /*      
491         /*----------------------------------------------------------*/
492
493        /*
494         * Allocate a structure to hold our state while we're gone
495         * waiting for this to complete.
496         */
497
498         arg = (struct pdb_data *)db_alloc(sizeof(struct pdb_data));
499         arg->db = db;
500         arg->send_request = create_operation();
501
502        /*
503         * Send the request string to the server
504         */
505         STRING_DATA(arg->s) = request;
506         MAX_STRING_SIZE(arg->s) = strlen (request) +1;
507         start_sending_object (arg->send_request, db->connection, 
508                                 (char *)&(arg->s), STRING_T);   
509         if (OP_STATUS(arg->send_request) == OP_CANCELLED) {
510             OP_STATUS(op) = OP_CANCELLED;
511             delete_operation(arg->send_request);
512             db_free((char *)arg, sizeof(struct pdb_data));
513             return OP_CANCELLED;
514         }
515
516         /*----------------------------------------------------------*/
517         /*      
518         /*      Asynchronously receive the return code (note, we
519         /*      really don't know whether the request has even been
520         /*      sent yet...doesn't really matter.)
521         /*      
522         /*----------------------------------------------------------*/
523
524         arg->get_retcode = create_operation();
525        /*
526         *  This must come here as it sets op_result 
527         */
528         initialize_operation(op, g_ipdb, (char *)arg, (int (*)())NULL);
529
530         start_receiving_object (arg->get_retcode, db->connection, 
531                                 (char *)&(OP_RESULT(op)), INTEGER_T);   
532         if (OP_STATUS(arg->get_retcode) == OP_CANCELLED) {
533             OP_STATUS(op) = OP_CANCELLED;
534             (void) cancel_operation(arg->send_request);/* this could be a bug, */
535                                                 /* because we introduce */
536                                                 /* indeterminism into */
537                                                 /* the reply stream, probably */
538                                                 /* should shutdown the whole */
539                                                 /* db here */
540             delete_operation(arg->send_request);
541             delete_operation(arg->get_retcode);
542             db_free((char *)arg, sizeof(struct adb_data));
543             return OP_CANCELLED;
544         }
545
546        /*
547         * We've successfully queued the receive of the return code.
548         * That's about all we have to do if things go well, but if the
549         * operation fails later, we have to be there to clean up.  To
550         * get control back, we queue ourselves as a second operation
551         * so we can see how the first did, and so we can free up arg.
552         */
553         (void) queue_operation(db->connection, CON_INPUT, op);
554         return OP_RUNNING;
555 }
556
557         /*----------------------------------------------------------*/
558         /*      
559         /*                      g_ipdb
560         /*      
561         /*      Init routine for getting return code on performin a db
562         /*      operation.  If all went well, (or even if it didn't),
563         /*      then we are done.  All we have to do is clean up the
564         /*      stuff we've allocated.
565         /*      
566         /*----------------------------------------------------------*/
567
568 int
569 g_ipdb(op, hcon, arg)
570 OPERATION op;
571 HALF_CONNECTION hcon;
572 struct pdb_data *arg;
573 {
574         int rc1, rc2;
575
576        /*
577         * Figure out how the receipt went
578         */
579         rc1 = OP_STATUS(arg->send_request);
580         rc2 = OP_STATUS(arg->get_retcode);
581
582        /*
583         * Release all transient data structures.
584         */
585         if (rc1 != OP_COMPLETE || rc2 != OP_COMPLETE)
586                 g_tear_down(arg->db);
587           
588         delete_operation(arg->send_request);
589         delete_operation(arg->get_retcode);
590         db_free((char *)arg, sizeof(struct pdb_data));
591         
592         return rc2;
593 }
594 \f
595 /************************************************************************/
596 /*      
597 /*                      perform_db_operation (perform_db_operation)
598 /*      
599 /*      Do a database operation synchronously.  This just calls
600 /*      the async routine and waits for it to complete.
601 /*      
602 /************************************************************************/
603
604 perform_db_operation (db_handle,request)
605 DATABASE db_handle; 
606 char *request;
607 {
608         register OPERATION op;
609         register int status;
610         register int result;
611
612        /*
613         * Create an operation and use it to asynchronously perform
614         * the operation
615         */
616         op = create_operation();
617         (void) start_performing_db_operation(op, db_handle, request);
618
619        /* 
620         * Wait for it to complete, note whether the operation
621         * completed at all, and if so, whether it returned a
622         * successful result.  Then reclaim the space used for the
623         * operation.
624         */
625         (void) complete_operation(op);
626         status = OP_STATUS(op);
627         result = OP_RESULT(op);
628
629         delete_operation(op);
630
631        /*
632         * Tell the caller either that we were interrupted, or pass
633         * on the actual result of accessing the database.  If it
634         * failed, then tear everything down after all.
635         */
636         if (status==OP_COMPLETE)
637                 return result;
638         else
639                 return status;
640 }
641 \f/************************************************************************/
642 /*      
643 /*                start_db_query (start_db_query)
644 /*      
645 /*      Asynchronously performs a database query on the remote
646 /*      database.
647 /*      
648 /*      The operation is encoded as a GDB string and sent to the server.
649 /*      
650 /*      An integer return code is received back and returned to the caller.
651 /*      
652 /*      If the return code indicates success, then we go into a loop
653 /*      receiving the retrieved data.  Each returned tuple is preceeded by
654 /*      a so-called yes/no flag, which indicates whether tuple data is really
655 /*      to follow.  Last tuple is followed by a NO flag.
656 /*      
657 /*      Note that this operation executes on both the outbound and inbound
658 /*      half connections.  Since there is no explicit sync between the two
659 /*      directions, operations like this pipeline freely from requestor
660 /*      to server, but there is no way to cancel this operation once it
661 /*      has started without severing the accompanying connection.
662 /*      
663 /************************************************************************/
664
665 int g_idbq();
666 int g_cdbq();
667
668 struct dbq_data {
669        /*
670         * Following may be used throughout processing
671         */
672         DATABASE db;                            /* the database we're */
673                                                 /* working on */
674         RELATION rel;
675         TUPLE_DESCRIPTOR tpd;
676        /*
677         * used primarily in first phase for sending query and getting
678         * return code
679         */
680         OPERATION send_query;                   /* used to send the string */
681                                                 /* containing the query */
682                                                 /* to be performed */
683         OPERATION send_descriptor;              /* used to send the tuple */
684                                                 /* descriptor to the server */
685         OPERATION get_retcode;                  /* used to get back the */
686                                                 /* response to our request */
687         STRING s;                               /* the operation string */
688                                                 /* itself.  This is sent. */
689        /*
690         * Following are used during later phase to receive the tuples 
691         */
692         int state;                              /* are we expecting a yes/no */
693                                                 /* or a tuple next? */
694 #define YESNO 1
695 #define TUPDATA 2
696         int yesno;                              /* an indicator of whether */
697                                                 /* another tuple is to follow*/
698 #define YES 1
699         OPERATION receive_yesno_or_data;
700         TUPLE tup;                              /* a place to put */
701                                                 /* the next tuple */
702 };
703
704 int
705 start_db_query (op, db_handle,rel, query)
706 OPERATION op;
707 DATABASE db_handle; 
708 RELATION rel;
709 char *query;
710 {
711         /*----------------------------------------------------------*/
712         /*      
713         /*                      Declarations
714         /*      
715         /*----------------------------------------------------------*/
716
717         register struct dbq_data *arg;          /* holds our state */
718                                                 /* during async operation*/
719         register DATABASE db = db_handle;       /* fast working copy */
720
721         /*----------------------------------------------------------*/
722         /*      
723         /*                  Execution begins here
724         /*      
725         /*      Make sure parameters are correct, then allocate a
726         /*      structure.
727         /*      
728         /*----------------------------------------------------------*/
729
730         GDB_CHECK_OP(op, "start_db_query ")
731
732         if (rel ==NULL) {
733                 fprintf (gdb_log, "gdb: query_db: input rel is null \n");
734                 OP_STATUS(op) = OP_CANCELLED;
735                 return OP_CANCELLED;
736         }
737
738         if (db==NULL) {
739                 fprintf (gdb_log, "gdb: start_db_query: supplied database is NULL\n");
740                 OP_STATUS(op) = OP_CANCELLED;
741                 return OP_CANCELLED;
742         }
743
744         GDB_CHECK_DB(db, "start_db_query")
745
746         if (DB_STATUS(db) != DB_OPEN) {
747                 fprintf (gdb_log, "gdb: start_db_query: request to closed database ");
748                 OP_STATUS(op) = OP_CANCELLED;
749                 return OP_CANCELLED;
750         }
751
752         if (db->connection == NULL) {
753                 fprintf (gdb_log,"gdb: start_db_query: connection severed, request cancelled\n");
754                 OP_STATUS(op) = OP_CANCELLED;
755                 return OP_CANCELLED;
756         }
757
758         if (connection_status(db->connection) != CON_UP ) {
759                 fprintf (gdb_log,"gdb: start_db_query: problems maintaining connection ");
760                 connection_perror(db->connection, "Reason for connection failure");
761                 fprintf (gdb_log,"request cancelled \n");
762                 OP_STATUS(op) = OP_CANCELLED;
763                 return OP_CANCELLED;
764         }
765
766         if (query == NULL || *query == '\0') { 
767                 fprintf (gdb_log, "gdb: start_db_query: request string is null\n");
768                 OP_STATUS(op) = OP_CANCELLED;
769                 return OP_CANCELLED;
770         }
771
772
773         /*----------------------------------------------------------*/
774         /*      
775         /*      Asynchronously send the query to the server
776         /*      
777         /*----------------------------------------------------------*/
778
779        /*
780         * Allocate a structure to hold our state while we're gone
781         * waiting for this to complete.
782         */
783
784         arg = (struct dbq_data *)db_alloc(sizeof(struct dbq_data));
785         arg->db = db;
786         arg->rel = rel;
787         arg->send_query = create_operation();
788
789        /*
790         * Send the query string to the server
791         */
792         (void) string_alloc(&(arg->s), strlen(query)+11);
793         (void) strcpy(STRING_DATA(arg->s), "retrieve ");
794         (void) strcat(STRING_DATA(arg->s), query);
795         MAX_STRING_SIZE(arg->s) = strlen (query) +11;
796         start_sending_object (arg->send_query, db->connection, 
797                                 (char *)&(arg->s), STRING_T);   
798         if (OP_STATUS(arg->send_query) == OP_CANCELLED) {
799             OP_STATUS(op) = OP_CANCELLED;
800             delete_operation(arg->send_query);
801             string_free(&(arg->s));
802             db_free((char *)arg, sizeof(struct dbq_data));
803             return OP_CANCELLED;
804         }
805
806        /*
807         * Send the tuple descriptor to the server
808         */
809
810         arg->send_descriptor = create_operation();
811         arg->tpd = DESCRIPTOR_FROM_RELATION(arg->rel);
812
813         start_sending_object (arg->send_descriptor, db->connection, 
814                                 (char *)&(arg->tpd), TUPLE_DESCRIPTOR_T);
815         if (OP_STATUS(arg->send_descriptor) == OP_CANCELLED) {
816             OP_STATUS(op) = OP_CANCELLED;
817             (void) cancel_operation(arg->send_query);/* this could be a bug, */
818                                                 /* because we introduce */
819                                                 /* indeterminism into */
820                                                 /* the reply stream, probably */
821                                                 /* should shutdown the whole */
822                                                 /* db here */
823             delete_operation(arg->send_query);
824             delete_operation(arg->send_descriptor);
825             string_free(&(arg->s));
826             db_free((char *)arg, sizeof(struct dbq_data));
827             return OP_CANCELLED;
828         }
829
830         /*----------------------------------------------------------*/
831         /*      
832         /*      Asynchronously receive the return code (note, we
833         /*      really don't know whether the query/and the descriptor
834         /*      have even been sent yet...doesn't really matter.)
835         /*      
836         /*----------------------------------------------------------*/
837
838         arg->get_retcode = create_operation();
839         start_receiving_object (arg->get_retcode, db->connection, 
840                                 (char *)&(OP_RESULT(op)), INTEGER_T);   
841         if (OP_STATUS(arg->get_retcode) == OP_CANCELLED) {
842             OP_STATUS(op) = OP_CANCELLED;
843             (void) cancel_operation(arg->send_query);/* this could be a bug, */
844                                                 /* because we introduce */
845                                                 /* indeterminism into */
846                                                 /* the reply stream, probably */
847                                                 /* should shutdown the whole */
848                                                 /* db here */
849             (void) cancel_operation(arg->send_descriptor);
850             string_free(&(arg->s));
851             delete_operation(arg->send_query);
852             delete_operation(arg->send_descriptor);
853             delete_operation(arg->get_retcode);
854             db_free((char *)arg, sizeof(struct adb_data));
855             return OP_CANCELLED;
856         }
857
858        /*
859         * We've successfully queued the receive of the return code.
860         * That's about all we have to do if things go well, but if the
861         * operation fails later, we have to be there to clean up.  To
862         * get control back, we queue ourselves as a second operation
863         * so we can see how the first did, and so we can free up arg.
864         */
865         initialize_operation(op, g_idbq, (char *)arg, (int (*)())NULL);
866         (void) queue_operation(db->connection, CON_INPUT, op);
867
868         return OP_RUNNING;
869 }
870
871         /*----------------------------------------------------------*/
872         /*      
873         /*                      g_idbq
874         /*      
875         /*      Init routine for getting return code on performing a
876         /*      bd query.  If there was an error, then we are done except for
877         /*      cleaning up all the dynamic memory we allocated.
878         /*      If the return code was 0,then we must asynchronously
879         /*      do the following iteratively until a no is received:
880         /*      
881         /*        while (async_receive(yes/no) == yes) {
882         /*             async receive new tuple
883         /*             add it to the relation 
884         /*        } 
885         /*      
886         /*----------------------------------------------------------*/
887
888 int
889 g_idbq(op, hcon, arg)
890 OPERATION op;
891 HALF_CONNECTION hcon;
892 struct dbq_data *arg;
893 {
894         int rc1, rc2, rc3;
895
896         /*----------------------------------------------------------*/
897         /*      
898         /*      See how the three asynchronous operations went,and
899         /*      clean up after them.
900         /*      
901         /*----------------------------------------------------------*/
902
903        /*
904         * Figure out how the receipt went
905         */
906         rc1 = OP_STATUS(arg->send_query);
907         rc2 = OP_STATUS(arg->send_descriptor);
908         rc3 = OP_STATUS(arg->get_retcode);
909
910        /*
911         * Release all transient data structures which were used in the
912         * preliminary operations.
913         */
914         delete_operation(arg->send_query);
915         delete_operation(arg->get_retcode);
916         string_free(&(arg->s));
917        /*
918         * If we've failed for any reason, then mark ourselves complete and
919         * return.
920         */
921         if (rc1 != OP_COMPLETE || rc2 != OP_COMPLETE|| rc3 != OP_COMPLETE
922             || OP_RESULT(op) != OP_SUCCESS) {
923                     OP_STATUS(op) = rc3;        /* we must have done */
924                                                 /* about as well as */
925                                                 /* the last one */
926                 
927                     db_free((char *)arg, sizeof(struct dbq_data));
928                     return rc3;                 /* tell the dispatcher */
929                                                 /* that we're either */
930                                                 /* cancelled or complete */
931         }
932           
933         /*----------------------------------------------------------*/
934         /*      
935         /*      We've successfully received a return code of 0 from
936         /*      Ingres, which means we are now going to begin the
937         /*      yes/no loop.
938         /*      
939         /*----------------------------------------------------------*/
940
941         op->fcn.cont = g_cdbq;                  /* after the preempting */
942                                                 /* receive completes, the */
943                                                 /* dispatcher will call */
944                                                 /* this routine. */
945         arg->state = YESNO;                     /* tell continuation routine */
946                                                 /* that we're receiving */
947                                                 /* a yes/no */
948         arg->tup = NULL;                        /* so we won't try to clean */
949                                                 /* it up */
950         arg->receive_yesno_or_data = create_operation();
951         
952         preempt_and_start_receiving_object(arg->receive_yesno_or_data,
953                                            op,
954                                            (char *)&(arg->yesno),
955                                            INTEGER_T);
956         return OP_PREEMPTED;    
957 }
958
959         /*----------------------------------------------------------*/
960         /*      
961         /*                      g_cdbq
962         /*      
963         /*      Continuation routine for receiving results of a query.
964         /*      Tbis is called repeatedly each time either a yes/no or
965         /*      a new tuple is received.  It repeatedly preempts itself
966         /*      to receive the next yes/no or tuple until a 'no'
967         /*      is finally received.
968         /*      
969         /*----------------------------------------------------------*/
970
971 int
972 g_cdbq(op, hcon, arg)
973 OPERATION op;
974 HALF_CONNECTION hcon;
975 struct dbq_data *arg;
976 {
977         /*----------------------------------------------------------*/
978         /*      
979         /*      See whether the preempting operation completed
980         /*      successfully.  If not, we just clean up and cancel
981         /*      
982         /*----------------------------------------------------------*/
983
984         if (OP_STATUS(arg->receive_yesno_or_data) != OP_COMPLETE) {
985                 delete_operation(arg->receive_yesno_or_data);
986                 if (arg->tup != NULL)
987                         delete_tuple(arg->tup);
988                 db_free((char *)arg, sizeof(struct dbq_data));
989                 OP_STATUS(op) = OP_CANCELLED;
990                 return OP_CANCELLED;
991         }
992
993         /*----------------------------------------------------------*/
994         /*      
995         /*      Whatever it was, we received it cleanly.  If it 
996         /*      was tuple data, then accept it and prepare to receive
997         /*      a yesno.  If it was a yes, then prepare to receive
998         /*      the tuple data.  If it was a NO, then we're all done.
999         /*      
1000         /*      Note that g_cdbg will be recalled by the dispatcher
1001         /*      after the preempting routines have completed.
1002         /*      
1003         /*----------------------------------------------------------*/
1004
1005        /*
1006         * New TUPLE DATA
1007         */
1008
1009         if (arg->state == TUPDATA) {
1010                 ADD_TUPLE_TO_RELATION(arg->rel, arg->tup);
1011                 arg->tup = NULL;                /* so we won't try to */
1012                                                 /* delete it in case of error*/
1013                 reset_operation(arg->receive_yesno_or_data);
1014                 arg->state = YESNO;
1015                 preempt_and_start_receiving_object(arg->receive_yesno_or_data,
1016                                                    op,
1017                                                    (char *)&(arg->yesno),
1018                                                    INTEGER_T);
1019                 return OP_PREEMPTED;    
1020         }
1021
1022        /*
1023         * We just received a yes or no. If it's a YES, prepare to
1024         * receive some more tuple data.
1025         */
1026         if (arg->yesno == YES)  {
1027                 arg->tup = create_tuple(arg->tpd);
1028                 reset_operation(arg->receive_yesno_or_data);
1029                 arg->state = TUPDATA;
1030                 preempt_and_start_receiving_object(arg->receive_yesno_or_data,
1031                                                    op,
1032                                                    (char *)arg->tup,
1033                                                    TUPLE_DATA_T);
1034                 return OP_PREEMPTED;    
1035         }
1036        /*
1037         * We just received a NO.  Looks like we're all done cleanly.
1038         */
1039         delete_operation(arg->receive_yesno_or_data);
1040         if (arg->tup != NULL)
1041                 delete_tuple(arg->tup);
1042         db_free((char *)arg, sizeof(struct dbq_data));
1043         OP_STATUS(op) = OP_COMPLETE;
1044         return OP_COMPLETE;
1045         
1046 }
1047 \f
1048 /************************************************************************/
1049 /*      
1050 /*                              db_query (db_query)
1051 /*      
1052 /*      Perform a relational query on the specified database.
1053 /*      
1054 /*      This just calls the asynchronous form of doing a query and
1055 /*      waits for it to complete.
1056 /*      
1057 /*      
1058 /************************************************************************/
1059
1060 int
1061 db_query(db_handle, rel, query)
1062 DATABASE db_handle; 
1063 RELATION rel;
1064 char *query;
1065 {
1066         register OPERATION op;
1067         register int status;
1068         register int result;
1069
1070        /*
1071         * Create an operation and use it to asynchronously perform
1072         * the operation
1073         */
1074         op = create_operation();
1075         (void) start_db_query(op, db_handle, rel, query);
1076
1077        /* 
1078         * Wait for it to complete, note whether the operation
1079         * completed at all, and if so, whether it returned a
1080         * successful result.  Then reclaim the space used for the
1081         * operation.
1082         */
1083         (void) complete_operation(op);
1084         status = OP_STATUS(op);
1085         result = OP_RESULT(op);
1086
1087         delete_operation(op);
1088
1089        /*
1090         * Tell the caller either that we were interrupted, or pass
1091         * on the actual result of accessing the database.  If it
1092         * failed, then tear everything down after all.
1093         */
1094         if (status==OP_COMPLETE)
1095                 return result;
1096         else
1097                 return status;
1098 }
This page took 0.11818 seconds and 3 git commands to generate.