NCBI C++ ToolKit
timeout.c
Go to the documentation of this file.

Go to the SVN repository for this file.

Go to the SVN repository for this file.

Go to the SVN repository for this file.

Go to the SVN repository for this file.

1 /*
2  * Purpose: Test handling of timeouts with an error handler
3  * Functions: dberrhandle, dbsetlogintime, dbsettime, dbsetopt, dbclropt, dbisopt
4  * \todo We test returning INT_CANCEL for a login timeout. We don't test it for a query_timeout.
5  */
6 
7 #include "common.h"
8 #include <time.h>
9 
10 #include <common/test_assert.h>
11 
12 static int ntimeouts = 0, ncancels = 0;
13 static const int max_timeouts = 2, timeout_seconds = 2;
14 static time_t start_time;
15 
16 static int timeout_err_handler(DBPROCESS * dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr);
17 static int chkintr(DBPROCESS * dbproc);
18 static int hndlintr(DBPROCESS * dbproc);
19 
20 #if !defined(SYBETIME)
21 #define SYBETIME SQLETIME
22 #define INT_TIMEOUT INT_CANCEL
23 dbsetinterrupt(DBPROCESS *dbproc, void* hand, void* p) {}
24 #endif
25 
26 static int
27 timeout_err_handler(DBPROCESS * dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
28 {
29  /*
30  * For server messages, cancel the query and rely on the
31  * message handler to spew the appropriate error messages out.
32  */
33  if (dberr == SYBESMSG)
34  return INT_CANCEL;
35 
36  if (dberr == SYBETIME) {
37  fprintf(stderr, "%d timeouts received in %ld seconds, ", ++ntimeouts, (long int) (time(NULL) - start_time));
38  if (ntimeouts > max_timeouts) {
39  if (++ncancels > 1) {
40  fprintf(stderr, "could not timeout cleanly, breaking connection\n");
41  ncancels = 0;
42  return INT_CANCEL;
43  }
44  fprintf(stderr, "lost patience, cancelling (allowing 10 seconds)\n");
45  if (dbsettime(10) == FAIL)
46  fprintf(stderr, "... but dbsettime() failed in error handler\n");
47  return INT_TIMEOUT;
48  }
49  fprintf(stderr, "continuing to wait\n");
50  return INT_CONTINUE;
51  }
52 
53  ntimeouts = 0; /* reset */
54 
55  fprintf(stderr,
56  "DB-LIBRARY error (severity %d, dberr %d, oserr %d, dberrstr %s, oserrstr %s):\n",
57  severity, dberr, oserr, dberrstr ? dberrstr : "(null)", oserrstr ? oserrstr : "(null)");
58  fflush(stderr);
59 
60  /*
61  * If the dbprocess is dead or the dbproc is a NULL pointer and
62  * we are not in the middle of logging in, then we need to exit.
63  * We can't do anything from here on out anyway.
64  * It's OK to end up here in response to a dbconvert() that
65  * resulted in overflow, so don't exit in that case.
66  */
67  if ((dbproc == NULL) || DBDEAD(dbproc)) {
68  if (dberr != SYBECOFL) {
69  fprintf(stderr, "error: dbproc (%p) is %s, goodbye\n",
70  dbproc, dbproc? (DBDEAD(dbproc)? "DEAD" : "OK") : "NULL");
71  exit(255);
72  }
73  }
74 
75  return INT_CANCEL;
76 }
77 
78 static int
80 {
81  printf("in chkintr, %ld seconds elapsed\n", (long int) (time(NULL) - start_time));
82  return FALSE;
83 }
84 
85 static int
87 {
88  printf("in hndlintr, %ld seconds elapsed\n", (long int) (time(NULL) - start_time));
89  return INT_CONTINUE;
90 }
91 
92 static int failed = 0;
93 
94 static void
95 test(int per_process)
96 {
97  LOGINREC *login;
99  int i, r;
100  RETCODE erc, row_code;
101  int num_resultset = 0;
102  char teststr[1024];
103  char timeout[32];
104 
105  sprintf(timeout, "%d", timeout_seconds);
106 
107  ntimeouts = 0;
108  ncancels = 0;
109 
110  /*
111  * Connect to server
112  */
115 
116  printf("About to logon\n");
117 
118  login = dblogin();
121  DBSETLAPP(login, "#timeout");
122 
123  printf("About to open %s.%s\n", SERVER, DATABASE);
124 
125  /*
126  * One way to test the login timeout is to connect to a discard server (grep discard /etc/services).
127  * It's normally supported by inetd.
128  */
129  printf ("using %d 1-second login timeouts\n", max_timeouts);
130  dbsetlogintime(1);
131 
132  start_time = time(NULL); /* keep track of when we started for reporting purposes */
133 
134  if (NULL == (dbproc = dbopen(login, SERVER))){
135  fprintf(stderr, "Failed: dbopen\n");
136  exit(1);
137  }
138 
139  printf ("connected.\n");
140 
141  if (strlen(DATABASE))
143 
145 
146  /* Set a very long global timeout. */
147  if (per_process)
148  dbsettime(5 * 60);
149 
150  /* Verify no query timeout is set for this DBPROCESS */
151  if (dbisopt(dbproc, DBSETTIME, 0)) {
152  printf("unexpected return code from dbisopt() before calling dbsetopt(..., DBSETTIME, ...)\n");
153  exit(1);
154  }
155 
156  if (FAIL == dbsetopt(dbproc, DBSETTIME, timeout, 0)) {
157  fprintf(stderr, "Failed: dbsetopt(..., DBSETTIME, \"%d\")\n", timeout_seconds);
158  exit(1);
159  }
160 
161  /* Verify a query timeout is actually set for this DBPROCESS now */
162  if (!dbisopt(dbproc, DBSETTIME, 0)) {
163  printf("unexpected return code from dbisopt() after calling dbsetopt(..., DBSETTIME, ...)\n");
164  exit(1);
165  }
166 
167  if (FAIL == dbclropt(dbproc, DBSETTIME, 0)) {
168  fprintf(stderr, "Failed: dbclropt(..., DBSETTIME, ...)\n");
169  exit(1);
170  }
171 
172  /* Verify no query timeout remains set for this DBPROCESS */
173  if (dbisopt(dbproc, DBSETTIME, 0)) {
174  printf("unexpected return code from dbisopt() after calling dbclropt(..., DBSETTIME, ...)\n");
175  exit(1);
176  }
177 
178  printf ("using %d %d-second query timeouts\n", max_timeouts, timeout_seconds);
179  if (per_process) {
180  if (FAIL == dbsetopt(dbproc, DBSETTIME, timeout, 0)) {
181  fprintf(stderr, "Failed: dbsetopt(..., DBSETTIME, \"%d\")\n", timeout_seconds);
182  exit(1);
183  }
184 
185  /* Verify setting the global timeout won't override the per-process timeout value */
186  dbsettime(35);
187  } else {
188  if (FAIL == dbsettime(timeout_seconds)) {
189  fprintf(stderr, "Failed: dbsettime\n");
190  exit(1);
191  }
192  }
193 
194  /* send something that will take awhile to execute */
195  printf ("issuing a query that will take 30 seconds\n");
196 
197  if (FAIL == sql_cmd(dbproc)) {
198  fprintf(stderr, "Failed: dbcmd\n");
199  exit(1);
200  }
201 
202  start_time = time(NULL); /* keep track of when we started for reporting purposes */
203  ntimeouts = 0;
206 
207  if (FAIL == dbsqlsend(dbproc)) {
208  fprintf(stderr, "Failed: dbsend\n");
209  exit(1);
210  }
211 
212  /* wait for it to execute */
213  printf("executing dbsqlok\n");
214  erc = dbsqlok(dbproc);
215  if (erc != FAIL) {
216  fprintf(stderr, "dbsqlok should fail for timeout\n");
217  exit(1);
218  }
219 
220  /* retrieve outputs per usual */
221  r = 0;
222  for (i=0; (erc = dbresults(dbproc)) != NO_MORE_RESULTS; i++) {
223  int nrows, ncols;
224  switch (erc) {
225  case SUCCEED:
226  if (DBROWS(dbproc) == FAIL){
227  r++;
228  continue;
229  }
231  printf("dbrows() returned SUCCEED, processing rows\n");
232 
233  ncols = dbnumcols(dbproc);
234  ++num_resultset;
235  printf("bound 1 of %d columns ('%s') in result %d.\n", ncols, dbcolname(dbproc, 1), ++r);
236  dbbind(dbproc, 1, STRINGBIND, 0, (BYTE *) teststr);
237 
238  printf("\t%s\n\t-----------\n", dbcolname(dbproc, 1));
239  while ((row_code = dbnextrow(dbproc)) != NO_MORE_ROWS) {
240  if (row_code == REG_ROW) {
241  printf("\t%s\n", teststr);
242  } else {
243  /* not supporting computed rows in this unit test */
244  failed = 1;
245  fprintf(stderr, "Failed. Expected a row\n");
246  exit(1);
247  }
248  }
249  nrows = (int) dbcount(dbproc);
250  printf("row count %d\n", nrows);
251  if (nrows < 0){
252  failed++;
253  printf("error: dbrows() returned SUCCEED, but dbcount() returned -1\n");
254  }
255 
256  if (FAIL == dbclropt(dbproc, DBSETTIME, 0)) {
257  failed++;
258  printf("error: dbclropt(dbproc, DBSETTIME, ...) failed\n");
259  }
260  break;
261  case FAIL:
262  printf("dbresults returned FAIL\n");
263  exit(1);
264  default:
265  printf("unexpected return code %d from dbresults\n", erc);
266  exit(1);
267  }
268  if (i > 1) {
269  failed++;
270  break;
271  }
272  } /* while dbresults */
273 }
274 
275 int
276 main(int argc, char **argv)
277 {
279 
280  read_login_info(argc, argv);
281 
282  fprintf(stdout, "Starting %s\n", argv[0]);
283 
284  dbinit();
285 
286  test(0);
287  test(1);
288 
289  dbexit();
290 
291  printf("%s %s\n", __FILE__, (failed ? "failed!" : "OK"));
292  return failed ? 1 : 0;
293 }
char PASSWORD[512]
Definition: common.c:31
char DATABASE[512]
Definition: common.c:32
CS_RETCODE read_login_info(void)
Definition: common.c:71
char SERVER[512]
Definition: common.c:30
static TDSLOGIN * login
Definition: dataread.c:31
RETCODE sql_cmd(DBPROCESS *dbproc)
Definition: common.c:280
int syb_msg_handler(DBPROCESS *dbproc, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname, char *procname, int line)
Definition: common.c:334
void set_malloc_options(void)
Definition: common.c:47
static char teststr[1024]
Definition: t0006.c:10
dbsetinterrupt(DBPROCESS *dbproc, void *hand, void *p)
Definition: timeout.c:23
int main(int argc, char **argv)
Definition: timeout.c:276
#define INT_TIMEOUT
Definition: timeout.c:22
static const int timeout_seconds
Definition: timeout.c:13
static int hndlintr(DBPROCESS *dbproc)
Definition: timeout.c:86
#define SYBETIME
Definition: timeout.c:21
static int ntimeouts
Definition: timeout.c:12
static int timeout_err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
Definition: timeout.c:27
static int ncancels
Definition: timeout.c:12
static int chkintr(DBPROCESS *dbproc)
Definition: timeout.c:79
static const int max_timeouts
Definition: timeout.c:13
static void test(int per_process)
Definition: timeout.c:95
static time_t start_time
Definition: timeout.c:14
static int failed
Definition: timeout.c:92
STATUS dbnextrow(DBPROCESS *dbproc)
Definition: dblib.c:2076
#define USER
Definition: fastme_common.h:43
#define NULL
Definition: ncbistd.hpp:225
#define DBSETLPWD(x, y)
Set the password in the login packet.
Definition: sybdb.h:1259
#define DBSETLAPP(x, y)
Set the (client) application name in the login packet.
Definition: sybdb.h:1266
#define DBSETLUSER(x, y)
Set the username in the login packet.
Definition: sybdb.h:1256
LOGINREC * dblogin(void)
Allocate a LOGINREC structure.
Definition: dblib.c:719
#define DBDEAD(x)
Sybase macro mapping to the Microsoft (lower-case) function.
Definition: sybdb.h:762
#define DBROWS(x)
Sybase macro mapping to the Microsoft (lower-case) function.
Definition: sybdb.h:881
RETCODE dbresults(DBPROCESS *dbproc)
Set up query results.
Definition: dblib.c:1706
RETCODE dbinit(void)
Initialize db-lib.
Definition: dblib.c:674
RETCODE dbsetlogintime(int seconds)
Set maximum seconds db-lib waits for a server response to a login attempt.
Definition: dblib.c:4137
RETCODE dbuse(DBPROCESS *dbproc, const char *name)
Change current database.
Definition: dblib.c:1449
RETCODE dbbind(DBPROCESS *dbproc, int column, int vartype, DBINT varlen, BYTE *varaddr)
Tie a host variable to a resultset column.
Definition: dblib.c:2645
RETCODE dbclropt(DBPROCESS *dbproc, int option, const char param[])
Reset an option.
Definition: dblib.c:6008
DBINT dbcount(DBPROCESS *dbproc)
Get count of rows processed.
Definition: dblib.c:2835
RETCODE dbsetopt(DBPROCESS *dbproc, int option, const char *char_param, int int_param)
Set db-lib or server option.
Definition: dblib.c:4383
EHANDLEFUNC dberrhandle(EHANDLEFUNC handler)
Set an error handler, for messages from db-lib.
Definition: dblib.c:5030
void dbloginfree(LOGINREC *login)
free the LOGINREC
Definition: dblib.c:751
DBBOOL dbisopt(DBPROCESS *dbproc, int option, const char param[])
Get value of an option.
Definition: dblib.c:6076
RETCODE dbsqlsend(DBPROCESS *dbproc)
Transmit the command buffer to the server.
Definition: dblib.c:6965
void dbexit()
Close server connections and free all related structures.
Definition: dblib.c:1559
char * dbcolname(DBPROCESS *dbproc, int column)
Return name of a regular result column.
Definition: dblib.c:1884
RETCODE dbsettime(int seconds)
Set maximum seconds db-lib waits for a server response to query.
Definition: dblib.c:4090
int dbnumcols(DBPROCESS *dbproc)
Return number of regular columns in a result set.
Definition: dblib.c:1860
MHANDLEFUNC dbmsghandle(MHANDLEFUNC handler)
Set a message handler, for messages from the server.
Definition: dblib.c:5049
RETCODE dbsqlok(DBPROCESS *dbproc)
Wait for results of a query from the server.
Definition: dblib.c:4722
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
exit(2)
int i
double r(size_t dimension_, const Int4 *score_, const double *prob_, double theta_)
#define assert(x)
Definition: srv_diag.hpp:58
#define dbopen(x, y)
Definition: sybdb.h:855
#define REG_ROW
Definition: sybdb.h:580
int RETCODE
Definition: sybdb.h:121
unsigned char BYTE
Definition: sybdb.h:334
#define NO_MORE_ROWS
Definition: sybdb.h:582
int(* DB_DBCHKINTR_FUNC)(void *dbproc)
Definition: sybdb.h:134
#define SYBECOFL
Definition: sybdb.h:977
#define SUCCEED
Definition: sybdb.h:585
#define DBSETTIME
Definition: sybdb.h:434
#define SYBESMSG
Definition: sybdb.h:946
#define FAIL
Definition: sybdb.h:586
#define INT_CONTINUE
Definition: sybdb.h:61
#define STRINGBIND
Definition: sybdb.h:548
int(* DB_DBHNDLINTR_FUNC)(void *dbproc)
Definition: sybdb.h:135
#define INT_CANCEL
Definition: sybdb.h:62
#define NO_MORE_RESULTS
Definition: sybdb.h:584
DBPROCESS * dbproc
Definition: t0013.c:18
@ FALSE
Definition: testodbc.c:27
Modified on Tue Apr 09 07:59:30 2024 by modify_doxy.py rev. 669887
Modified on Wed Apr 10 07:34:51 2024 by modify_doxy.py rev. 669887
Modified on Thu Apr 11 15:16:58 2024 by modify_doxy.py rev. 669887
Modified on Fri Apr 12 17:21:36 2024 by modify_doxy.py rev. 669887