From a700e7ac41d5b310a3b9359374083f9312bcce72 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sat, 18 Jun 2022 13:20:18 +0000 Subject: [PATCH] wrote some code for connect timeout handling in mar.c --- hio/bin/t04.c | 11 +++---- hio/lib/hio-mar.h | 20 ++++++------ hio/lib/hio-shw.h | 2 +- hio/lib/mar-cli.c | 1 + hio/lib/mar.c | 81 +++++++++++++++++++++++++++++++++++++---------- 5 files changed, 83 insertions(+), 32 deletions(-) diff --git a/hio/bin/t04.c b/hio/bin/t04.c index f97559c..20aa636 100644 --- a/hio/bin/t04.c +++ b/hio/bin/t04.c @@ -210,7 +210,7 @@ int main (int argc, char* argv[]) hio_t* hio = HIO_NULL; hio_svc_marc_t* marc; hio_svc_marc_connect_t ci; -/* hio_svc_marc_tmout_t tmout;*/ + hio_svc_marc_tmout_t tmout; if (argc != 6) { @@ -232,13 +232,12 @@ int main (int argc, char* argv[]) ci.password = argv[4]; ci.dbname = argv[5]; -/* timeout not implemented yet in the mardiab device and services - HIO_INIT_NTIME (&tmout.c, 2, 0); + memset (&tmout, 0, HIO_SIZEOF(tmout)); + HIO_INIT_NTIME (&tmout.c, 4, 0); HIO_INIT_NTIME (&tmout.r, -1, 0); HIO_INIT_NTIME (&tmout.w, -1, 0); -*/ - - marc = hio_svc_marc_start(hio, &ci, HIO_NULL, HIO_NULL); + marc = hio_svc_marc_start(hio, &ci, &tmout, HIO_NULL); + /*marc = hio_svc_marc_start(hio, &ci, HIO_NULL, HIO_NULL);*/ if (!marc) { printf ("Cannot start a mariadb client service\n"); diff --git a/hio/lib/hio-mar.h b/hio/lib/hio-mar.h index d731f36..6a5a1a5 100644 --- a/hio/lib/hio-mar.h +++ b/hio/lib/hio-mar.h @@ -76,6 +76,14 @@ typedef void (*hio_dev_mar_on_row_fetched_t) ( void* row_data ); +typedef struct hio_dev_mar_tmout_t hio_dev_mar_tmout_t; +struct hio_dev_mar_tmout_t +{ + hio_ntime_t c; + hio_ntime_t r; + hio_ntime_t w; +}; + struct hio_dev_mar_t { HIO_DEV_HEADER; @@ -84,6 +92,9 @@ struct hio_dev_mar_t void* res; hio_dev_mar_progress_t progress; + hio_dev_mar_tmout_t tmout; + hio_tmridx_t ctmridx; + unsigned int connected: 1; unsigned int connected_deferred: 1; unsigned int query_started_deferred: 1; @@ -109,15 +120,6 @@ enum hio_dev_mar_make_flag_t }; typedef enum hio_dev_mar_make_flag_t hio_dev_mar_make_flag_t; - -typedef struct hio_dev_mar_tmout_t hio_dev_mar_tmout_t; -struct hio_dev_mar_tmout_t -{ - hio_ntime_t c; - hio_ntime_t r; - hio_ntime_t w; -}; - typedef struct hio_dev_mar_make_t hio_dev_mar_make_t; struct hio_dev_mar_make_t { diff --git a/hio/lib/hio-shw.h b/hio/lib/hio-shw.h index 156ccd5..85b8e7b 100644 --- a/hio/lib/hio-shw.h +++ b/hio/lib/hio-shw.h @@ -26,7 +26,7 @@ #define _HIO_SHW_H_ /* system handle wrapper - - * turn a raw system handle/file descript to a device object + * turn a raw system handle/file descriptor to a device object */ #include diff --git a/hio/lib/mar-cli.c b/hio/lib/mar-cli.c index 47cd924..d101ef7 100644 --- a/hio/lib/mar-cli.c +++ b/hio/lib/mar-cli.c @@ -258,6 +258,7 @@ static void mar_on_disconnect (hio_dev_mar_t* dev) sess->connected = 0; + /* give RCODE_ERROR to pending queries */ while (1) { sess_qry_t* sq; diff --git a/hio/lib/mar.c b/hio/lib/mar.c index 31363d7..f4e5cae 100644 --- a/hio/lib/mar.c +++ b/hio/lib/mar.c @@ -43,6 +43,49 @@ /* ========================================================================= */ +static void on_connect_timeout (hio_t* hio, const hio_ntime_t* now, hio_tmrjob_t* job) +{ + hio_dev_mar_t* rdev = (hio_dev_mar_t*)job->ctx; + hio_dev_mar_halt (rdev); +} + +static int sched_connect_timeout (hio_dev_t* dev) +{ + hio_t* hio = dev->hio; + hio_dev_mar_t* rdev = (hio_dev_mar_t*)dev; + hio_tmrjob_t tmrjob; + + if (rdev->tmout.c.sec >= 0) + { + HIO_MEMSET (&tmrjob, 0, HIO_SIZEOF(tmrjob)); + tmrjob.ctx = rdev; + hio_gettime (hio, &tmrjob.when); + HIO_ADD_NTIME (&tmrjob.when, &tmrjob.when, &rdev->tmout.c); + tmrjob.handler = on_connect_timeout; + tmrjob.idxptr = &rdev->ctmridx; + rdev->ctmridx = hio_instmrjob(hio, &tmrjob); + if (rdev->ctmridx == HIO_TMRIDX_INVALID) + { + /* don't care about failure. timing out won't work */ + /* TODO: fix this */ + } + } + + return 0; +} + +static void desched_connect_timeout (hio_dev_t* dev) +{ + hio_t* hio = dev->hio; + hio_dev_mar_t* rdev = (hio_dev_mar_t*)dev; + + if (rdev->ctmridx != HIO_TMRIDX_INVALID) + { + hio_deltmrjob (hio, rdev->ctmridx); + HIO_ASSERT (hio, rdev->ctmridx == HIO_TMRIDX_INVALID); + } +} + static int dev_mar_make (hio_dev_t* dev, void* ctx) { hio_t* hio = dev->hio; @@ -72,24 +115,26 @@ static int dev_mar_make (hio_dev_t* dev, void* ctx) mysql_options(rdev->hnd, MYSQL_OPT_RECONNECT, &x); } -#if 0 -/* TOOD: timeout not implemented... - * timeout can't be implemented using the mysql timeout options in the nonblocking mode. - * i must create a timeer jobs for these */ - if (mi->flags & HIO_DEV_MAR_USE_TMOUT) - { + + /* remember the timeout settings. use a negative second to indicate no timeout. + * the saved values will be used in scheduling a timer job for each relevant operation. + * Timing out can't be implemented with the standard MYSQL TIMEOUT options in + * the asynchronous mode. that is, this sample code doesn't work. unsigned int tmout; - - tmout = mi->tmout.c.sec; /* mysql supports the granularity of seconds only */ + tmout = mi->tmout.c.sec; // mysql supports the granularity of seconds only if (tmout >= 0) mysql_options(rdev->hnd, MYSQL_OPT_CONNECT_TIMEOUT, &tmout); - tmout = mi->tmout.r.sec; if (tmout >= 0) mysql_options(rdev->hnd, MYSQL_OPT_READ_TIMEOUT, &tmout); - tmout = mi->tmout.w.sec; if (tmout >= 0) mysql_options(rdev->hnd, MYSQL_OPT_WRITE_TIMEOUT, &tmout); + */ + rdev->tmout = mi->tmout; + if (!(mi->flags & HIO_DEV_MAR_USE_TMOUT)) + { + rdev->tmout.c.sec = -1; + rdev->tmout.r.sec = -1; + rdev->tmout.w.sec = -1; } -#endif rdev->dev_cap = HIO_DEV_CAP_IN | HIO_DEV_CAP_OUT | HIO_DEV_CAP_VIRTUAL; /* mysql_init() doesn't create a socket. so no IO is possible at this point */ rdev->on_read = mi->on_read; @@ -100,15 +145,18 @@ static int dev_mar_make (hio_dev_t* dev, void* ctx) rdev->on_row_fetched = mi->on_row_fetched; rdev->progress = HIO_DEV_MAR_INITIAL; + rdev->ctmridx = HIO_TMRIDX_INVALID; return 0; } static int dev_mar_kill (hio_dev_t* dev, int force) { - /*hio_t* hio = dev->hio;*/ + hio_t* hio = dev->hio; hio_dev_mar_t* rdev = (hio_dev_mar_t*)dev; + desched_connect_timeout (dev); + /* if rdev->connected is 0 at this point, * the underlying socket of this device is down */ if (HIO_LIKELY(rdev->on_disconnect)) rdev->on_disconnect (rdev); @@ -241,6 +289,7 @@ static int dev_mar_ioctl (hio_dev_t* dev, int cmd, void* arg) if (status) { /* not connected */ + sched_connect_timeout (dev); HIO_DEV_MAR_SET_PROGRESS (rdev, HIO_DEV_MAR_CONNECTING); watch_mysql (rdev, status); } @@ -432,8 +481,8 @@ static int dev_evcb_mar_ready (hio_dev_t* dev, int events) if (tmp) { /* established ok */ + desched_connect_timeout (dev); watch_mysql (rdev, status); - rdev->connected = 1; /* really connected */ HIO_DEV_MAR_SET_PROGRESS (rdev, HIO_DEV_MAR_CONNECTED); if (rdev->on_connect) rdev->on_connect (rdev); @@ -443,7 +492,7 @@ static int dev_evcb_mar_ready (hio_dev_t* dev, int events) /* connection attempt failed */ /* the mysql client library closes the underlying socket handle - * whenever the connection attempt fails. this prevent hio from + * whenever the connection attempt fails. this prevents hio from * managing the the mysql connections properly. this also causes * race condition if this library is used in multi-threaded programs. */ @@ -463,8 +512,8 @@ static int dev_evcb_mar_ready (hio_dev_t* dev, int events) watch_mysql (rdev, 0); /* on_disconnect() will be called without on_connect(). - * you may assume that the initial connectinon attempt failed. - * reconnectin doesn't apply in this context. */ + * you may assume that the initial connection attempt failed. + * reconnection doesn't apply in this context. */ hio_dev_mar_halt (rdev); } }