]> andersk Git - moira.git/blame - gdb/gdb_db.c
added copyright message
[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>
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
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
241int
242g_iadb(op, hcon, arg)
243OPERATION op;
244HALF_CONNECTION hcon;
245struct 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
282int
283g_tear_down (db_handle)
284DATABASE 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
328DATABASE
329g_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
350int
351access_db (db_ident, db_handle)
352char *db_ident;
353DATABASE *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
409int g_ipdb();
410
411struct 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
427int
428start_performing_db_operation (op, db_handle,request)
429OPERATION op;
430DATABASE db_handle;
431char *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
571int
572g_ipdb(op, hcon, arg)
573OPERATION op;
574HALF_CONNECTION hcon;
575struct 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
607perform_db_operation (db_handle,request)
608DATABASE db_handle;
609char *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
668int g_idbq();
669int g_cdbq();
670
671struct 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
707int
708start_db_query (op, db_handle,rel, query)
709OPERATION op;
710DATABASE db_handle;
711RELATION rel;
712char *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
891int
892g_idbq(op, hcon, arg)
893OPERATION op;
894HALF_CONNECTION hcon;
895struct 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
974int
975g_cdbq(op, hcon, arg)
976OPERATION op;
977HALF_CONNECTION hcon;
978struct 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
1063int
1064db_query(db_handle, rel, query)
1065DATABASE db_handle;
1066RELATION rel;
1067char *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 0.223095 seconds and 5 git commands to generate.