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