-
Notifications
You must be signed in to change notification settings - Fork 164
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce CS_INTERRUPT_CB and corresponding return values: CS_INT_*.
Define CS_INTERRUPT_CB's numeric value alongside other CS_*_CBs'; start a new 94xx range to avoid confusion with properties. (Sybase/SAP ctlib has no such callback.) Allow specification on either the connection or the context level as usual, with the help of a shim installed on demand to minimize interference with tds_select's optimization for the no-handler case. For CS_INT_*, copy TDS_INT_* and confirm their equality at compile time as with CS_NULLTERM et al. Add a test roughly modeled on dblib's timeout.c unit test, which (alone) exercises the corresponding db_setinterrupt API. Signed-off-by: Aaron M. Ucko <[email protected]>
- Loading branch information
Showing
9 changed files
with
155 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,4 +37,5 @@ | |
/variant | ||
/errors | ||
/ct_command | ||
/timeout | ||
/libcommon.a |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
/* | ||
* Purpose: Test handling of timeouts with callbacks | ||
*/ | ||
|
||
#include "common.h" | ||
#include <freetds/macros.h> | ||
#include <time.h> | ||
|
||
static int ntimeouts = 0, ncancels = 0; | ||
static int max_timeouts = 2, timeout_seconds = 2, cancel_timeout = 10; | ||
static time_t start_time; | ||
static const char sql[] = | ||
"select getdate() as 'begintime'\n" | ||
"waitfor delay '00:00:30'\n" | ||
"select getdate() as 'endtime'"; | ||
|
||
static int | ||
on_interrupt(CS_CONNECTION *con TDS_UNUSED) | ||
{ | ||
printf("In on_interrupt, %ld seconds elapsed.\n", (long int) (time(NULL) - start_time)); | ||
return CS_INT_CONTINUE; | ||
} | ||
|
||
static int | ||
on_client_msg(CS_CONTEXT *ctx, CS_CONNECTION *con, CS_CLIENTMSG *errmsg) | ||
{ | ||
if (errmsg->msgnumber == 20003) { /* TDSETIME */ | ||
fprintf(stderr, "%d timeout(s) received in %ld seconds; ", ++ntimeouts, (long int) (time(NULL) - start_time)); | ||
if (ntimeouts > max_timeouts) { | ||
if (++ncancels > 1) { | ||
fputs("could not time out cleanly;" | ||
" breaking connection.\n", stderr); | ||
ncancels = 0; | ||
return CS_FAIL; | ||
} | ||
fputs("lost patience;" | ||
" cancelling (allowing 10 seconds)\n", stderr); | ||
if (CS_FAIL == ct_con_props(con, CS_SET, CS_TIMEOUT, &cancel_timeout, CS_UNUSED, NULL)) | ||
fputs("... but ct_con_props() failed" | ||
" in error handler.\n", stderr); | ||
return CS_FAIL; | ||
} | ||
fputs("continuing to wait.\n", stderr); | ||
return CS_SUCCEED; | ||
} | ||
return clientmsg_cb(ctx, con, errmsg); | ||
} | ||
|
||
static void | ||
test(CS_CONNECTION *con, CS_COMMAND *cmd) | ||
{ | ||
CS_INT result_type = 0; | ||
CS_RETCODE ret; | ||
|
||
ntimeouts = 0; | ||
ncancels = 0; | ||
|
||
printf("Using %d-second query timeouts.\n", timeout_seconds); | ||
|
||
if (CS_FAIL == ct_con_props(con, CS_SET, CS_TIMEOUT, &timeout_seconds, CS_UNUSED, NULL)) { | ||
fputs("Failed: ct_con_props(..., CS_SET, CS_TIMEOUT, ...).", stderr); | ||
exit(1); | ||
} | ||
|
||
/* Send something that will take a while to execute. */ | ||
printf("Issuing a query that will take 30 seconds.\n"); | ||
if (CS_SUCCEED != ct_command(cmd, CS_LANG_CMD, (void *) sql, sizeof(sql) - 1, CS_UNUSED)) { | ||
fputs("Failed: ct_command.\n", stderr); | ||
exit(1); | ||
} | ||
|
||
start_time = time(NULL); /* Track for reporting purposes. */ | ||
ntimeouts = 0; | ||
if (CS_FAIL == ct_callback(NULL, con, CS_SET, CS_CLIENTMSG_CB, &on_client_msg) | ||
|| CS_FAIL == ct_callback(NULL, con, CS_SET, CS_INTERRUPT_CB, &on_interrupt)) { | ||
fputs("Failed: ct_callback.\n", stderr); | ||
exit(1); | ||
} | ||
|
||
if (CS_SUCCEED != ct_send(cmd)) { | ||
fputs("Failed: ct_send.\n", stderr); | ||
exit(1); | ||
} | ||
|
||
ret = ct_results(cmd, &result_type); | ||
if (ret == CS_SUCCEED) { | ||
fprintf(stderr, "Query unexpectedly succeeded, with result type %d.\n", result_type); | ||
} else { | ||
printf("Query failed as expected, with return code %d.\n", ret); | ||
} | ||
} | ||
|
||
int | ||
main(int argc, char **argv) | ||
{ | ||
CS_CONTEXT *ctx; | ||
CS_CONNECTION *con; | ||
CS_COMMAND *cmd; | ||
|
||
if (CS_SUCCEED != try_ctlogin_with_options(argc, argv, &ctx, &con, &cmd, false)) { | ||
fputs("Customary setup failed.\n", stderr); | ||
return 1; | ||
} | ||
test(con, cmd); | ||
try_ctlogout(ctx, con, cmd, false); | ||
return 0; | ||
} |