LCOV - code coverage report
Current view: top level - src/ctlib/unittests - cancel.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 71 100 71.0 %
Date: 2024-04-18 21:21:48 Functions: 3 3 100.0 %

          Line data    Source code
       1             : #include <config.h>
       2             : 
       3             : #include <stdio.h>
       4             : 
       5             : #include <freetds/time.h>
       6             : 
       7             : #include <sys/types.h>
       8             : 
       9             : #if HAVE_UNISTD_H
      10             : #include <unistd.h>
      11             : #endif /* HAVE_UNISTD_H */
      12             : 
      13             : #include <signal.h>
      14             : #include <ctpublic.h>
      15             : #include "common.h"
      16             : 
      17             : #if defined(HAVE_ALARM) && defined(HAVE_SETITIMER)
      18             : 
      19             : /* protos */
      20             : int do_fetch(CS_COMMAND * cmd, int *cnt);
      21             : void catch_alrm(int);
      22             : 
      23             : /* Globals */
      24             : static volatile CS_COMMAND *g_cmd = NULL;
      25             : 
      26             : void
      27         129 : catch_alrm(int sig_num)
      28             : {
      29         129 :         signal(SIGALRM, catch_alrm);
      30             : 
      31         129 :         printf("- SIGALRM\n");
      32             : 
      33             :         /* Cancel current command */
      34         129 :         if (g_cmd)
      35         129 :                 ct_cancel(NULL, (CS_COMMAND *) g_cmd, CS_CANCEL_ATTN);
      36             : 
      37         129 :         fflush(stdout);
      38         129 : }
      39             : 
      40             : /* Testing: Test asynchronous ct_cancel() */
      41             : int
      42           8 : main(int argc, char **argv)
      43             : {
      44             :         CS_CONTEXT *ctx;
      45             :         CS_CONNECTION *conn;
      46             :         CS_COMMAND *cmd;
      47           8 :         int i, verbose = 0, cnt = 0;
      48             : 
      49             :         CS_RETCODE ret;
      50             :         CS_INT result_type;
      51             : 
      52             :         struct itimerval timer;
      53             :         char query[1024];
      54             : 
      55           8 :         unsigned clock = 200000;
      56             : 
      57           8 :         printf("%s: Check asynchronous called ct_cancel()\n", __FILE__);
      58             :         if (verbose) {
      59             :                 printf("Trying login\n");
      60             :         }
      61           8 :         ret = try_ctlogin(&ctx, &conn, &cmd, verbose);
      62           8 :         if (ret != CS_SUCCEED) {
      63           0 :                 fprintf(stderr, "Login failed\n");
      64           0 :                 return 1;
      65             :         }
      66             : 
      67             :         /* Create needed tables */
      68           8 :         ret = run_command(cmd, "CREATE TABLE #t0010 (id int, col1 varchar(255))");
      69           8 :         if (ret != CS_SUCCEED)
      70             :                 return 1;
      71             : 
      72          80 :         for (i = 0; i < 10; i++) {
      73          80 :                 sprintf(query, "INSERT #t0010 (id, col1) values (%d, 'This is field no %d')", i, i);
      74             : 
      75          80 :                 ret = run_command(cmd, query);
      76          80 :                 if (ret != CS_SUCCEED)
      77             :                         return 1;
      78             :         }
      79             : 
      80             :         /* Set SIGALRM signal handler */
      81           8 :         signal(SIGALRM, catch_alrm);
      82             : 
      83             :         for (;;) {
      84             :                 /* TODO better to use alarm AFTER ct_send ?? */
      85             :                 /* Set timer */
      86           8 :                 timer.it_interval.tv_sec = 0;
      87           8 :                 timer.it_interval.tv_usec = clock;
      88           8 :                 timer.it_value.tv_sec = 0;
      89           8 :                 timer.it_value.tv_usec = clock;
      90           8 :                 if (0 != setitimer(ITIMER_REAL, &timer, NULL)) {
      91           0 :                         fprintf(stderr, "Could not set realtime timer.\n");
      92           0 :                         return 1;
      93             :                 }
      94             : 
      95             :                 /* Issue a command returning many rows */
      96           8 :                 ret = ct_command(cmd, CS_LANG_CMD, "SELECT * FROM #t0010 t1, #t0010 t2, #t0010 t3, #t0010 t4", CS_NULLTERM, CS_UNUSED);
      97           8 :                 if (ret != CS_SUCCEED) {
      98           0 :                         fprintf(stderr, "ct_command() failed.\n");
      99           0 :                         return 1;
     100             :                 }
     101             : 
     102           8 :                 ret = ct_send(cmd);
     103           8 :                 if (ret != CS_SUCCEED) {
     104           0 :                         fprintf(stderr, "first ct_send() failed.\n");
     105           0 :                         return 1;
     106             :                 }
     107             : 
     108             :                 /* Save a global reference for the interrupt handler */
     109           8 :                 g_cmd = cmd;
     110             : 
     111          24 :                 while ((ret = ct_results(cmd, &result_type)) == CS_SUCCEED) {
     112           8 :                         printf("More results?...\n");
     113           8 :                         if (result_type == CS_STATUS_RESULT)
     114           0 :                                 continue;
     115             : 
     116           8 :                         switch ((int) result_type) {
     117           8 :                         case CS_ROW_RESULT:
     118           8 :                                 printf("do_fetch() returned: %d\n", do_fetch(cmd, &cnt));
     119           8 :                                 break;
     120             :                         }
     121             :                 }
     122             : 
     123             :                 /* We should not have received all rows, as the alarm signal cancelled it... */
     124           8 :                 if (cnt < 10000)
     125             :                         break;
     126             : 
     127           0 :                 if (clock <= 5000) {
     128           0 :                         fprintf(stderr, "All rows read, this may not occur.\n");
     129           0 :                         return 1;
     130             :                 }
     131           0 :                 g_cmd = NULL;
     132           0 :                 clock /= 2;
     133             :         }
     134             : 
     135             :         /* Remove timer */
     136           8 :         timer.it_interval.tv_sec = 0;
     137           8 :         timer.it_interval.tv_usec = 0;
     138           8 :         timer.it_value.tv_sec = 0;
     139           8 :         timer.it_value.tv_usec = 0;
     140           8 :         if (0 != setitimer(ITIMER_REAL, &timer, NULL)) {
     141           0 :                 fprintf(stderr, "Could not remove realtime timer.\n");
     142           0 :                 return 1;
     143             :         }
     144             : 
     145             :         /*
     146             :          * Issue another command, this will be executed after a ct_cancel, 
     147             :          * to test if wire state is consistent 
     148             :          */
     149           8 :         ret = ct_command(cmd, CS_LANG_CMD, "SELECT * FROM #t0010 t1, #t0010 t2, #t0010 t3", CS_NULLTERM, CS_UNUSED);
     150           8 :         if (ret != CS_SUCCEED) {
     151           0 :                 fprintf(stderr, "ct_command() failed.\n");
     152           0 :                 return 1;
     153             :         }
     154             : 
     155           8 :         ret = ct_send(cmd);
     156           8 :         if (ret != CS_SUCCEED) {
     157           0 :                 fprintf(stderr, "second ct_send() failed.\n");
     158           0 :                 return 1;
     159             :         }
     160             : 
     161          24 :         while ((ret = ct_results(cmd, &result_type)) == CS_SUCCEED) {
     162          16 :                 printf("More results?...\n");
     163          16 :                 if (result_type == CS_STATUS_RESULT)
     164           0 :                         continue;
     165             : 
     166          16 :                 switch ((int) result_type) {
     167           8 :                 case CS_ROW_RESULT:
     168           8 :                         printf("do_fetch() returned: %d\n", do_fetch(cmd, &cnt));
     169           8 :                         break;
     170             :                 }
     171             :         }
     172             : 
     173           8 :         if (1000 != cnt) {
     174             :                 /* This time, all rows must have been received */
     175           0 :                 fprintf(stderr, "Incorrect number of rows read.\n");
     176           0 :                 return 1;
     177             :         }
     178             : 
     179             :         if (verbose) {
     180             :                 printf("Trying logout\n");
     181             :         }
     182           8 :         ret = try_ctlogout(ctx, conn, cmd, verbose);
     183           8 :         if (ret != CS_SUCCEED) {
     184           0 :                 fprintf(stderr, "Logout failed\n");
     185           0 :                 return 1;
     186             :         }
     187             : 
     188           8 :         printf("%s: asynchronous cancel test: PASSED\n", __FILE__);
     189             : 
     190           8 :         return 0;
     191             : }
     192             : 
     193             : int
     194          16 : do_fetch(CS_COMMAND * cmd, int *cnt)
     195             : {
     196          16 :         CS_INT count, row_count = 0;
     197             :         CS_RETCODE ret;
     198             : 
     199        9626 :         while ((ret = ct_fetch(cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED, &count)) == CS_SUCCEED) {
     200             :                 /* printf ("ct_fetch() == CS_SUCCEED\n"); */
     201        9594 :                 row_count += count;
     202             :         }
     203             : 
     204          16 :         (*cnt) = row_count;
     205          16 :         if (ret == CS_ROW_FAIL) {
     206           0 :                 fprintf(stderr, "ct_fetch() CS_ROW_FAIL on row %d.\n", row_count);
     207           0 :                 return 1;
     208          16 :         } else if (ret == CS_END_DATA) {
     209           8 :                 printf("do_fetch retrieved %d rows\n", row_count);
     210           8 :                 return 0;
     211           8 :         } else if (ret == CS_CMD_FAIL) {
     212           0 :                 printf("do_fetch(): command aborted after receiving %d rows\n", row_count);
     213           0 :                 return 0;
     214             :         } else {
     215           8 :                 fprintf(stderr, "ct_fetch() unexpected return %d on row %d.\n", ret, row_count);
     216           8 :                 return 1;
     217             :         }
     218             : }
     219             : 
     220             : #else
     221             : 
     222             : int
     223             : main(void)
     224             : {
     225             :         return 0;
     226             : }
     227             : #endif
     228             : 

Generated by: LCOV version 1.13