]> andersk Git - moira.git/blame - gdb/gdb_db.c
Be paranoid.
[moira.git] / gdb / gdb_db.c
CommitLineData
5580185e 1/*
2 * $Source$
3 * $Header$
4 */
5
6#ifndef lint
7static 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
54DATABASE g_make_db();
55int g_iadb();
56
57struct adb_data {
58 DATABASE db;
59 OPERATION get_retcode;
60};
61
62int
63start_accessing_db (op, db_ident, db_handle)
64OPERATION op;
65char *db_ident;
66DATABASE *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
238int
239g_iadb(op, hcon, arg)
240OPERATION op;
241HALF_CONNECTION hcon;
242struct 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
279int
280g_tear_down (db_handle)
281DATABASE 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
325DATABASE
326g_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
347int
348access_db (db_ident, db_handle)
349char *db_ident;
350DATABASE *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
406int g_ipdb();
407
408struct 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
424int
425start_performing_db_operation (op, db_handle,request)
426OPERATION op;
427DATABASE db_handle;
428char *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
568int
569g_ipdb(op, hcon, arg)
570OPERATION op;
571HALF_CONNECTION hcon;
572struct 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
604perform_db_operation (db_handle,request)
605DATABASE db_handle;
606char *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
665int g_idbq();
666int g_cdbq();
667
668struct 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
704int
705start_db_query (op, db_handle,rel, query)
706OPERATION op;
707DATABASE db_handle;
708RELATION rel;
709char *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
888int
889g_idbq(op, hcon, arg)
890OPERATION op;
891HALF_CONNECTION hcon;
892struct 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
971int
972g_cdbq(op, hcon, arg)
973OPERATION op;
974HALF_CONNECTION hcon;
975struct 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
1060int
1061db_query(db_handle, rel, query)
1062DATABASE db_handle;
1063RELATION rel;
1064char *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.245726 seconds and 5 git commands to generate.