* $Header$
*
* Copyright (C) 1987, 1988 by the Massachusetts Institute of Technology
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
*
*/
static char *rcsid_qrtn_qc = "$Header$";
#endif lint
+#include <mit-copyright.h>
#include "query.h"
#include "sms_server.h"
char *Argv[16];
-static int ingres_errno = 0;
+int ingres_errno = 0;
+int sms_errcode = 0;
+## int query_timeout = 30;
extern char *whoami;
extern FILE *journal;
#define INGRES_BAD_INT 4111
#define INGRES_BAD_DATE 4302
#define INGRES_DEADLOCK 4700
+#define INGRES_TIMEOUT 4702
/*
* ingerr: (supposedly) called when Ingres indicates an error.
static int ingerr(num)
int *num;
{
- char buf[256];
+ ingres_errno = *num;
switch (*num) {
case INGRES_BAD_INT:
- ingres_errno = SMS_INTEGER;
+ sms_errcode = SMS_INTEGER;
break;
case INGRES_BAD_DATE:
- ingres_errno = SMS_DATE;
+ sms_errcode = SMS_DATE;
break;
case INGRES_DEADLOCK:
- ingres_errno = SMS_DEADLOCK;
+ sms_errcode = SMS_DEADLOCK;
+ com_err(whoami, 0, "INGRES deadlock detected");
+ break;
+ case INGRES_TIMEOUT:
+ sms_errcode = SMS_BUSY;
+ com_err(whoami, 0, "timed out getting lock");
break;
default:
- ingres_errno = SMS_INGRES_ERR;
+ sms_errcode = SMS_INGRES_ERR;
com_err(whoami, SMS_INGRES_ERR, " code %d\n", *num);
critical_alert("SMS", "SMS server encountered INGRES ERROR %d", *num);
return (*num);
/* open the database */
## ingres sms
+## set lockmode session where level = table, timeout = query_timeout
+## set lockmode on capacls where readlock = shared
+## set lockmode on alias where readlock = shared
return ingres_errno;
}
struct query *q;
struct query *get_query_by_name();
+ ingres_errno = 0;
+
q = get_query_by_name(name, cl->args->sms_version_no);
if (q == (struct query *)0)
return(SMS_NO_HANDLE);
struct save_queue *sq_create();
char *build_sort();
+ ingres_errno = 0;
+
/* list queries command */
if (!strcmp(name, "_list_queries")) {
list_queries(cl->args->sms_version_no, action, actarg);
if (q == (struct query *)0) return(SMS_NO_HANDLE);
v = q->validate;
- if (q->type != RETRIEVE)
+ if (q->type != RETRIEVE) {
+## set lockmode session where readlock = exclusive
## begin transaction
+ }
/* setup argument vector, verify access and arguments */
if ((status = sms_verify_query(cl, q, argc, argv_ro)) != SMS_SUCCESS)
status = do_retrieve(q, pqual, psort, action, actarg);
}
if (status != SMS_SUCCESS) break;
- table = q->rtable;
-## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
-## where tblstats.#table = @table
} else {
status = (*v->post_rtn)(q, Argv, cl, action, actarg);
}
fflush(journal);
}
} else {
-## abort /* it never happened */
+ if (ingres_errno != INGRES_DEADLOCK) {
+## abort /* it never happened */
+ }
}
+## set lockmode session where readlock = system
+ }
+
+ if (status == SMS_SUCCESS && ingres_errno != 0) {
+ critical_alert("SMS", "Server didn't notice INGRES ERROR %d",
+ ingres_errno);
+ status = SMS_INTERNAL;
}
if (status != SMS_SUCCESS && log_flags & LOG_RES)
com_err(whoami, status, " (Query failed)");
+ /* until all the clients know about SMS_BUSY, convert this error
+ * to one they will recognize.
+ */
+ if (status == SMS_BUSY)
+ status = SMS_DEADLOCK;
return(status);
}
register struct validate *v = q->validate;
register int i;
register int privileged = 0;
+ int len;
/* copy the arguments into a local argv that we can modify */
+ if (argc >= QMAXARGS)
+ return(SMS_ARGS);
for (i = 0; i < argc; i++) {
- if (strlen(argv_ro[i]) < ARGLEN)
+ if ((len = strlen(argv_ro[i])) < ARGLEN)
strcpy(Argv[i], argv_ro[i]);
else
return(SMS_ARG_TOO_LONG);
+ if (Argv[i][len-1] == '\\')
+ return(SMS_BAD_CHAR);
}
/* check initial query access */
}
/* check for default access */
-## range of m is members
+## range of m is imembers
## repeat retrieve (exists = any(m.#member_id where m.list_id = @acl_id and
## m.member_type = "USER" and m.#member_id = def_uid))
if (exists) return(SMS_SUCCESS);
return(SMS_SUCCESS);
##}
-##find_member(list_type, list_id, member_type, member_id, sq)
+##find_member(list_type, list_id, member_type, member_id)
char *list_type;
## int list_id;
## char *member_type;
## int member_id;
- struct save_queue *sq;
##{
-## int exists;
-## int sublist;
- int child;
- struct save_queue *sq_create();
+## int exists, errorno;
+
+ if (!strcmp(strtrim(list_type), strtrim(member_type)) &&
+ list_id == member_id)
+ return(1);
/* see if client is a direct member of list */
+## range of m is imembers
## repeat retrieve (exists = any(m.#member_id where
## m.#list_id = @list_id and
## m.#member_type = @member_type and
## m.#member_id = @member_id))
- if (exists) return(1);
-
- /* are there any sub-lists? */
-## repeat retrieve (exists = any(m.#member_id where m.#list_id = @list_id and
-## m.#member_type = "LIST"))
- if (!exists) return(0);
-
- /* yes; now recurse through sublists */
-
- /* create a save queue */
- if (sq == (struct save_queue *)0) {
- sq = sq_create();
- child = 0;
- } else {
- child = 1;
- }
-
- /* save all sublist ids */
-## range of m is members
-## retrieve (sublist = m.#member_id)
-## where m.#list_id = list_id and m.#member_type = "LIST"
-## {
- sq_save_unique_data(sq, sublist);
-## }
-
- if (child) return(0);
-
- /* at top-level, check sub-lists for client (breadth-first search) */
- while (sq_get_data(sq, &sublist)) {
- exists = find_member(list_type, sublist, member_type, member_id, sq);
- if (exists) {
- sq_destroy(sq);
- return(1);
- }
- }
- sq_destroy(sq);
- return(0);
+## inquire_equel(errorno = "errorno")
+ if (errorno == 0)
+ return(exists);
+ else
+ return(0);
##}
{
register int i;
int maxv = 0, maxa = 0;
+#ifdef MULTIPROTOCOLS
extern int QueryCount1, QueryCount2;
extern struct query Queries1[], Queries2[];
+#else
+ extern int QueryCount2;
+ extern struct query Queries2[];
+#endif MULTIPROTOCOLS
+
#define MAX(x,y) ((x) > (y) ? (x) : (y))
+#ifdef MULTIPROTOCOLS
for (i = 0; i < QueryCount1; i++) {
maxv = MAX(maxv, Queries1[i].vcnt);
maxa = MAX(maxa, Queries1[i].argc);
}
+#endif MULTIPROTOCOLS
for (i = 0; i < QueryCount2; i++) {
maxv = MAX(maxv, Queries2[i].vcnt);
maxa = MAX(maxa, Queries2[i].argc);
exit(1);
}
}
-
-
-/*
- * Local Variables:
- * mode: c
- * c-indent-level: 4
- * c-continued-statement-offset: 4
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * End:
- */
-