]> andersk Git - moira.git/blame - gdb/gdb_db.c
strings.h no longer exists on the sun, and string.h is POSIX anyway
[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
0a5ff702 17/* For copying and distribution information, please see
18/* the file <mit-copyright.h>.
5580185e 19/*
20/************************************************************************/
21
0a5ff702 22#include <mit-copyright.h>
5580185e 23#include <stdio.h>
f4c08abd 24#include <string.h>
5580185e 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
57DATABASE g_make_db();
58int g_iadb();
59
60struct adb_data {
61 DATABASE db;
62 OPERATION get_retcode;
63};
64
65int
66start_accessing_db (op, db_ident, db_handle)
67OPERATION op;
68char *db_ident;
69DATABASE *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
24582af9 241/*ARGSUSED*/
5580185e 242int
243g_iadb(op, hcon, arg)
244OPERATION op;
245HALF_CONNECTION hcon;
246struct 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
283int
284g_tear_down (db_handle)
285DATABASE 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
329DATABASE
330g_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
351int
352access_db (db_ident, db_handle)
353char *db_ident;
354DATABASE *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
410int g_ipdb();
411
412struct 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
428int
429start_performing_db_operation (op, db_handle,request)
430OPERATION op;
431DATABASE db_handle;
432char *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
24582af9 572/*ARGSUSED*/
5580185e 573int
574g_ipdb(op, hcon, arg)
575OPERATION op;
576HALF_CONNECTION hcon;
577struct 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
609perform_db_operation (db_handle,request)
610DATABASE db_handle;
611char *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
670int g_idbq();
671int g_cdbq();
672
673struct 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
709int
710start_db_query (op, db_handle,rel, query)
711OPERATION op;
712DATABASE db_handle;
713RELATION rel;
714char *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
24582af9 893/*ARGSUSED*/
5580185e 894int
895g_idbq(op, hcon, arg)
896OPERATION op;
897HALF_CONNECTION hcon;
898struct 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
24582af9 977/*ARGSUSED*/
5580185e 978int
979g_cdbq(op, hcon, arg)
980OPERATION op;
981HALF_CONNECTION hcon;
982struct 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
1067int
1068db_query(db_handle, rel, query)
1069DATABASE db_handle;
1070RELATION rel;
1071char *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 6.731344 seconds and 5 git commands to generate.