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