2020-06-14 16:09:17 +00:00
|
|
|
/*
|
|
|
|
Copyright (c) 2016-2020 Chung, Hyung-Hwan. All rights reserved.
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions
|
|
|
|
are met:
|
|
|
|
1. Redistributions of source code must retain the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer in the
|
|
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
2022-06-11 05:32:01 +00:00
|
|
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
2020-06-14 16:09:17 +00:00
|
|
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
#include <hio-mar.h>
|
|
|
|
#include "hio-prv.h"
|
2020-06-14 16:09:17 +00:00
|
|
|
|
2020-08-18 02:48:15 +00:00
|
|
|
#if 0
|
2020-06-14 16:09:17 +00:00
|
|
|
#include <mariadb/mysql.h>
|
2020-06-24 03:00:46 +00:00
|
|
|
#include <mariadb/errmsg.h>
|
2020-08-18 02:48:15 +00:00
|
|
|
#else
|
|
|
|
#include <mysql.h>
|
|
|
|
#include <errmsg.h>
|
|
|
|
#endif
|
2020-06-14 16:09:17 +00:00
|
|
|
|
2020-06-18 09:28:36 +00:00
|
|
|
typedef struct sess_t sess_t;
|
|
|
|
typedef struct sess_qry_t sess_qry_t;
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
struct hio_svc_marc_t
|
2020-06-14 16:09:17 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_SVC_HEADER;
|
2020-06-17 13:53:38 +00:00
|
|
|
|
2020-06-24 03:00:46 +00:00
|
|
|
int stopping;
|
2020-06-24 07:37:11 +00:00
|
|
|
int tmout_set;
|
|
|
|
|
2021-07-26 15:19:31 +00:00
|
|
|
const hio_bch_t* default_group;
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_svc_marc_connect_t ci;
|
|
|
|
hio_svc_marc_tmout_t tmout;
|
2020-06-24 07:37:11 +00:00
|
|
|
|
|
|
|
MYSQL* edev;
|
2020-06-19 09:17:42 +00:00
|
|
|
|
2020-06-18 09:28:36 +00:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
sess_t* ptr;
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_oow_t capa;
|
2020-06-18 09:28:36 +00:00
|
|
|
} sess;
|
2021-07-27 14:38:12 +00:00
|
|
|
|
|
|
|
hio_oow_t autoi;
|
|
|
|
hio_oow_t autoi2;
|
2020-06-18 09:28:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct sess_qry_t
|
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_bch_t* qptr;
|
|
|
|
hio_oow_t qlen;
|
2020-06-18 09:28:36 +00:00
|
|
|
void* qctx;
|
2020-06-21 08:42:36 +00:00
|
|
|
unsigned int sent: 1;
|
|
|
|
unsigned int need_fetch: 1;
|
2020-06-18 09:28:36 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_svc_marc_on_result_t on_result;
|
2020-06-18 09:28:36 +00:00
|
|
|
sess_qry_t* sq_next;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct sess_t
|
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_oow_t sid;
|
|
|
|
hio_svc_marc_t* svc;
|
|
|
|
hio_dev_mar_t* dev;
|
2020-06-19 09:17:42 +00:00
|
|
|
int connected;
|
2020-06-18 09:28:36 +00:00
|
|
|
|
|
|
|
sess_qry_t* q_head;
|
2020-06-19 09:17:42 +00:00
|
|
|
sess_qry_t* q_tail;
|
2020-06-14 16:09:17 +00:00
|
|
|
};
|
|
|
|
|
2020-06-19 09:17:42 +00:00
|
|
|
typedef struct dev_xtn_t dev_xtn_t;
|
|
|
|
|
|
|
|
struct dev_xtn_t
|
|
|
|
{
|
2021-07-24 08:43:12 +00:00
|
|
|
hio_oow_t sid;
|
|
|
|
hio_svc_marc_t* svc;
|
2020-06-19 09:17:42 +00:00
|
|
|
};
|
|
|
|
|
2021-07-24 08:43:12 +00:00
|
|
|
#define INVALID_SID HIO_TYPE_MAX(hio_oow_t)
|
2020-06-19 09:17:42 +00:00
|
|
|
|
2021-07-26 15:19:31 +00:00
|
|
|
hio_svc_marc_t* hio_svc_marc_start (hio_t* hio, const hio_svc_marc_connect_t* ci, const hio_svc_marc_tmout_t* tmout, const hio_bch_t* default_group)
|
2020-06-14 16:09:17 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_svc_marc_t* marc = HIO_NULL;
|
2020-06-14 16:09:17 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
marc = (hio_svc_marc_t*)hio_callocmem(hio, HIO_SIZEOF(*marc));
|
|
|
|
if (HIO_UNLIKELY(!marc)) goto oops;
|
2020-06-14 16:09:17 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
marc->edev = mysql_init(HIO_NULL);
|
|
|
|
if (HIO_UNLIKELY(!marc->edev)) goto oops;
|
2020-06-24 07:37:11 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
marc->hio = hio;
|
|
|
|
marc->svc_stop = hio_svc_marc_stop;
|
2020-06-19 09:17:42 +00:00
|
|
|
marc->ci = *ci;
|
2020-06-24 07:37:11 +00:00
|
|
|
if (tmout)
|
|
|
|
{
|
|
|
|
marc->tmout = *tmout;
|
|
|
|
marc->tmout_set = 1;
|
|
|
|
}
|
2021-07-26 15:19:31 +00:00
|
|
|
marc->default_group = default_group;
|
2020-06-14 16:09:17 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_SVCL_APPEND_SVC (&hio->actsvc, (hio_svc_t*)marc);
|
2020-06-14 16:09:17 +00:00
|
|
|
return marc;
|
|
|
|
|
|
|
|
oops:
|
2020-06-24 07:37:11 +00:00
|
|
|
if (marc->edev) mysql_close (marc->edev);
|
2021-07-22 07:30:20 +00:00
|
|
|
if (marc) hio_freemem (hio, marc);
|
|
|
|
return HIO_NULL;
|
2020-06-14 16:09:17 +00:00
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
void hio_svc_marc_stop (hio_svc_marc_t* marc)
|
2020-06-14 16:09:17 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_t* hio = marc->hio;
|
|
|
|
hio_oow_t i;
|
2020-06-24 03:00:46 +00:00
|
|
|
|
|
|
|
marc->stopping = 1;
|
|
|
|
|
|
|
|
for (i = 0; i < marc->sess.capa; i++)
|
|
|
|
{
|
2021-07-23 11:19:21 +00:00
|
|
|
if (marc->sess.ptr[i].dev)
|
|
|
|
{
|
|
|
|
hio_dev_mar_kill (marc->sess.ptr[i].dev);
|
|
|
|
}
|
2020-06-24 03:00:46 +00:00
|
|
|
}
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_freemem (hio, marc->sess.ptr);
|
2020-06-14 16:09:17 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_SVCL_UNLINK_SVC (marc);
|
2020-06-24 07:37:11 +00:00
|
|
|
|
|
|
|
mysql_close (marc->edev);
|
2021-07-23 11:19:21 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_freemem (hio, marc);
|
2020-06-14 16:09:17 +00:00
|
|
|
}
|
2020-06-17 13:53:38 +00:00
|
|
|
|
2020-06-19 09:17:42 +00:00
|
|
|
/* ------------------------------------------------------------------- */
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
static sess_qry_t* make_session_query (hio_t* hio, hio_svc_marc_qtype_t qtype, const hio_bch_t* qptr, hio_oow_t qlen, void* qctx, hio_svc_marc_on_result_t on_result)
|
2020-06-19 09:17:42 +00:00
|
|
|
{
|
|
|
|
sess_qry_t* sq;
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
sq = hio_allocmem(hio, HIO_SIZEOF(*sq) + (HIO_SIZEOF(*qptr) * qlen));
|
|
|
|
if (HIO_UNLIKELY(!sq)) return HIO_NULL;
|
2020-06-19 09:17:42 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMCPY (sq + 1, qptr, (HIO_SIZEOF(*qptr) * qlen));
|
2020-06-19 09:17:42 +00:00
|
|
|
|
|
|
|
sq->sent = 0;
|
2021-07-22 07:30:20 +00:00
|
|
|
sq->need_fetch = (qtype == HIO_SVC_MARC_QTYPE_SELECT);
|
|
|
|
sq->qptr = (hio_bch_t*)(sq + 1);
|
2020-06-19 09:17:42 +00:00
|
|
|
sq->qlen = qlen;
|
|
|
|
sq->qctx = qctx;
|
2020-06-21 08:42:36 +00:00
|
|
|
sq->on_result = on_result;
|
2021-07-22 07:30:20 +00:00
|
|
|
sq->sq_next = HIO_NULL;
|
2020-06-19 09:17:42 +00:00
|
|
|
|
|
|
|
return sq;
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
static HIO_INLINE void free_session_query (hio_t* hio, sess_qry_t* sq)
|
2020-06-19 09:17:42 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_freemem (hio, sq);
|
2020-06-19 09:17:42 +00:00
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
static HIO_INLINE void enqueue_session_query (sess_t* sess, sess_qry_t* sq)
|
2020-06-19 09:17:42 +00:00
|
|
|
{
|
|
|
|
/* the initialization creates a place holder. so no need to check if q_tail is NULL */
|
|
|
|
sess->q_tail->sq_next = sq;
|
|
|
|
sess->q_tail = sq;
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
static HIO_INLINE void dequeue_session_query (hio_t* hio, sess_t* sess)
|
2020-06-19 09:17:42 +00:00
|
|
|
{
|
|
|
|
sess_qry_t* sq;
|
|
|
|
|
|
|
|
sq = sess->q_head;
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_ASSERT (hio, sq->sq_next != HIO_NULL); /* must not be empty */
|
2020-06-19 09:17:42 +00:00
|
|
|
sess->q_head = sq->sq_next;
|
2021-07-22 07:30:20 +00:00
|
|
|
free_session_query (hio, sq);
|
2020-06-19 09:17:42 +00:00
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
static HIO_INLINE sess_qry_t* get_first_session_query (sess_t* sess)
|
2020-06-19 09:17:42 +00:00
|
|
|
{
|
|
|
|
return sess->q_head->sq_next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
static int send_pending_query_if_any (sess_t* sess)
|
|
|
|
{
|
|
|
|
sess_qry_t* sq;
|
|
|
|
|
|
|
|
sq = get_first_session_query(sess);
|
|
|
|
if (sq)
|
|
|
|
{
|
|
|
|
sq->sent = 1;
|
2021-07-23 11:19:21 +00:00
|
|
|
/*printf ("sending... %.*s\n", (int)sq->qlen, sq->qptr);*/
|
2021-07-22 07:30:20 +00:00
|
|
|
if (hio_dev_mar_querywithbchars(sess->dev, sq->qptr, sq->qlen) <= -1)
|
2020-06-19 09:17:42 +00:00
|
|
|
{
|
2021-07-23 11:19:21 +00:00
|
|
|
HIO_DEBUG2 (sess->svc->hio, "MARC(%p) - SEND FAIL %js\n", sess->dev, hio_geterrmsg(sess->svc->hio));
|
2020-06-19 09:17:42 +00:00
|
|
|
sq->sent = 0;
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_dev_mar_halt (sess->dev); /* this device can't carray on */
|
2020-06-24 03:00:46 +00:00
|
|
|
return -1; /* halted the device for failure */
|
2020-06-19 09:17:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1; /* sent */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 0; /* nothing to send */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------- */
|
2021-07-24 08:43:12 +00:00
|
|
|
static hio_dev_mar_t* alloc_device (hio_svc_marc_t* marc, hio_oow_t sid);
|
2020-06-19 09:17:42 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
static void mar_on_disconnect (hio_dev_mar_t* dev)
|
2020-06-17 13:53:38 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_t* hio = dev->hio;
|
|
|
|
dev_xtn_t* xtn = (dev_xtn_t*)hio_dev_mar_getxtn(dev);
|
2021-07-24 08:43:12 +00:00
|
|
|
sess_t* sess;
|
2020-06-19 09:17:42 +00:00
|
|
|
|
2021-07-24 08:43:12 +00:00
|
|
|
if (xtn->sid == INVALID_SID) return; /* this session data is not set if there's failure in alloc_device() */
|
2021-07-23 11:19:21 +00:00
|
|
|
|
2021-07-24 08:43:12 +00:00
|
|
|
sess = &xtn->svc->sess.ptr[xtn->sid];
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_DEBUG6 (hio, "MARC(%p) - device disconnected - sid %lu session %p session-connected %d device %p device-broken %d\n", sess->svc, (unsigned long int)sess->sid, sess, (int)sess->connected, dev, (int)dev->broken);
|
|
|
|
HIO_ASSERT (hio, dev == sess->dev);
|
2020-06-24 03:00:46 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
if (HIO_UNLIKELY(!sess->svc->stopping && hio->stopreq == HIO_STOPREQ_NONE))
|
2020-06-24 03:00:46 +00:00
|
|
|
{
|
|
|
|
if (sess->connected && sess->dev->broken) /* risk of infinite cycle if the underlying db suffers never-ending 'broken' issue after getting connected */
|
|
|
|
{
|
|
|
|
/* restart the dead device */
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_dev_mar_t* dev;
|
2020-06-24 03:00:46 +00:00
|
|
|
|
|
|
|
sess->connected = 0;
|
|
|
|
|
2021-07-24 08:43:12 +00:00
|
|
|
dev = alloc_device(sess->svc, sess->sid);
|
2021-07-22 07:30:20 +00:00
|
|
|
if (HIO_LIKELY(dev))
|
2020-06-24 03:00:46 +00:00
|
|
|
{
|
|
|
|
sess->dev = dev;
|
|
|
|
/* the pending query will be sent in on_connect() */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if device allocation fails, just carry on */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-19 09:17:42 +00:00
|
|
|
sess->connected = 0;
|
|
|
|
|
2022-06-18 13:20:18 +00:00
|
|
|
/* give RCODE_ERROR to pending queries */
|
2020-06-24 03:00:46 +00:00
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
sess_qry_t* sq;
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_svc_marc_dev_error_t err;
|
2020-06-19 09:17:42 +00:00
|
|
|
|
2020-06-24 03:00:46 +00:00
|
|
|
sq = get_first_session_query(sess);
|
|
|
|
if (!sq) break;
|
|
|
|
|
|
|
|
/* what is the best error code and message to use for this? */
|
|
|
|
err.mar_errcode = CR_SERVER_LOST;
|
|
|
|
err.mar_errmsg = "server lost";
|
2021-07-22 07:30:20 +00:00
|
|
|
sq->on_result (sess->svc, sess->sid, HIO_SVC_MARC_RCODE_ERROR, &err, sq->qctx);
|
|
|
|
dequeue_session_query (hio, sess);
|
2020-06-24 03:00:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* it should point to a placeholder node(either the initial one or the transited one after dequeing */
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_ASSERT (hio, sess->q_head == sess->q_tail);
|
|
|
|
HIO_ASSERT (hio, sess->q_head->sq_next == HIO_NULL);
|
|
|
|
free_session_query (hio, sess->q_head);
|
|
|
|
sess->q_head = sess->q_tail = HIO_NULL;
|
2020-06-24 03:00:46 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
sess->dev = HIO_NULL;
|
2020-06-17 13:53:38 +00:00
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
static void mar_on_connect (hio_dev_mar_t* dev)
|
2020-06-17 13:53:38 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_t* hio = dev->hio;
|
|
|
|
dev_xtn_t* xtn = (dev_xtn_t*)hio_dev_mar_getxtn(dev);
|
2021-07-24 08:43:12 +00:00
|
|
|
sess_t* sess;
|
2020-06-19 09:17:42 +00:00
|
|
|
|
2021-07-24 08:43:12 +00:00
|
|
|
HIO_ASSERT (hio, xtn->sid != INVALID_SID);
|
|
|
|
sess = &xtn->svc->sess.ptr[xtn->sid];
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_DEBUG5 (hio, "MARC(%p) - device connected - sid %lu session %p device %p device-broken %d\n", sess->svc, (unsigned long int)sess->sid, sess, dev, dev->broken);
|
2020-06-19 09:17:42 +00:00
|
|
|
|
2020-06-24 03:00:46 +00:00
|
|
|
sess->connected = 1;
|
|
|
|
send_pending_query_if_any (sess);
|
2020-06-17 13:53:38 +00:00
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
static void mar_on_query_started (hio_dev_mar_t* dev, int mar_ret, const hio_bch_t* mar_errmsg)
|
2020-06-17 13:53:38 +00:00
|
|
|
{
|
2021-07-24 08:43:12 +00:00
|
|
|
hio_t* hio = dev->hio;
|
2021-07-22 07:30:20 +00:00
|
|
|
dev_xtn_t* xtn = (dev_xtn_t*)hio_dev_mar_getxtn(dev);
|
2021-07-24 08:43:12 +00:00
|
|
|
sess_t* sess;
|
|
|
|
sess_qry_t* sq;
|
|
|
|
|
|
|
|
HIO_ASSERT (hio, xtn->sid != INVALID_SID);
|
|
|
|
sess = &xtn->svc->sess.ptr[xtn->sid];
|
|
|
|
sq = get_first_session_query(sess);
|
2020-06-21 08:42:36 +00:00
|
|
|
|
|
|
|
if (mar_ret)
|
2020-06-19 09:17:42 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_svc_marc_dev_error_t err;
|
2021-07-23 11:19:21 +00:00
|
|
|
/*printf ("QUERY FAILED...%d -> %s\n", mar_ret, mar_errmsg);*/
|
2020-06-21 08:42:36 +00:00
|
|
|
|
2020-06-21 15:30:44 +00:00
|
|
|
err.mar_errcode = mar_ret;
|
|
|
|
err.mar_errmsg = mar_errmsg;
|
2021-07-22 07:30:20 +00:00
|
|
|
sq->on_result(sess->svc, sess->sid, HIO_SVC_MARC_RCODE_ERROR, &err, sq->qctx);
|
2020-06-21 08:42:36 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
dequeue_session_query (sess->svc->hio, sess);
|
2020-06-21 08:42:36 +00:00
|
|
|
send_pending_query_if_any (sess);
|
2020-06-19 09:17:42 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-07-23 11:19:21 +00:00
|
|
|
/*printf ("QUERY STARTED\n");*/
|
2020-06-21 08:42:36 +00:00
|
|
|
if (sq->need_fetch)
|
2020-06-19 09:17:42 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
if (hio_dev_mar_fetchrows(dev) <= -1)
|
2020-06-21 08:42:36 +00:00
|
|
|
{
|
2021-07-23 11:19:21 +00:00
|
|
|
/*printf ("FETCH ROW FAILURE - %s\n", mysql_error(dev->hnd));*/
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_dev_mar_halt (dev);
|
2020-06-21 08:42:36 +00:00
|
|
|
}
|
2020-06-19 09:17:42 +00:00
|
|
|
}
|
2020-06-21 08:42:36 +00:00
|
|
|
else
|
2020-06-17 13:53:38 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
sq->on_result (sess->svc, sess->sid, HIO_SVC_MARC_RCODE_DONE, HIO_NULL, sq->qctx);
|
|
|
|
dequeue_session_query (sess->svc->hio, sess);
|
2020-06-21 08:42:36 +00:00
|
|
|
send_pending_query_if_any (sess);
|
2020-06-17 13:53:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
static void mar_on_row_fetched (hio_dev_mar_t* dev, void* data)
|
2020-06-17 13:53:38 +00:00
|
|
|
{
|
2021-07-24 08:43:12 +00:00
|
|
|
hio_t* hio = dev->hio;
|
2021-07-22 07:30:20 +00:00
|
|
|
dev_xtn_t* xtn = (dev_xtn_t*)hio_dev_mar_getxtn(dev);
|
2021-07-24 08:43:12 +00:00
|
|
|
sess_t* sess;
|
|
|
|
sess_qry_t* sq;
|
|
|
|
|
|
|
|
HIO_ASSERT (hio, xtn->sid != INVALID_SID);
|
|
|
|
sess = &xtn->svc->sess.ptr[xtn->sid];
|
|
|
|
sq = get_first_session_query(sess);
|
2020-06-19 09:17:42 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
sq->on_result (sess->svc, sess->sid, (data? HIO_SVC_MARC_RCODE_ROW: HIO_SVC_MARC_RCODE_DONE), data, sq->qctx);
|
2020-06-21 08:42:36 +00:00
|
|
|
|
|
|
|
if (!data)
|
2020-06-19 09:17:42 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
dequeue_session_query (sess->svc->hio, sess);
|
2020-06-21 08:42:36 +00:00
|
|
|
send_pending_query_if_any (sess);
|
2020-06-19 09:17:42 +00:00
|
|
|
}
|
2020-06-17 13:53:38 +00:00
|
|
|
}
|
|
|
|
|
2021-07-24 08:43:12 +00:00
|
|
|
static hio_dev_mar_t* alloc_device (hio_svc_marc_t* marc, hio_oow_t sid)
|
2020-06-17 13:53:38 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_t* hio = (hio_t*)marc->hio;
|
|
|
|
hio_dev_mar_t* mar;
|
|
|
|
hio_dev_mar_make_t mi;
|
2020-06-19 09:17:42 +00:00
|
|
|
dev_xtn_t* xtn;
|
2020-06-17 13:53:38 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMSET (&mi, 0, HIO_SIZEOF(mi));
|
2020-06-24 07:37:11 +00:00
|
|
|
if (marc->tmout_set)
|
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
mi.flags = HIO_DEV_MAR_USE_TMOUT;
|
2020-06-24 07:37:11 +00:00
|
|
|
mi.tmout = marc->tmout;
|
|
|
|
}
|
2021-07-26 15:19:31 +00:00
|
|
|
mi.default_group = marc->default_group;
|
2020-06-24 07:37:11 +00:00
|
|
|
|
2020-06-17 13:53:38 +00:00
|
|
|
mi.on_connect = mar_on_connect;
|
|
|
|
mi.on_disconnect = mar_on_disconnect;
|
|
|
|
mi.on_query_started = mar_on_query_started;
|
|
|
|
mi.on_row_fetched = mar_on_row_fetched;
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
mar = hio_dev_mar_make(hio, HIO_SIZEOF(*xtn), &mi);
|
2021-07-23 11:19:21 +00:00
|
|
|
if (HIO_UNLIKELY(!mar)) return HIO_NULL;
|
2020-06-17 13:53:38 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
xtn = (dev_xtn_t*)hio_dev_mar_getxtn(mar);
|
2021-07-24 08:43:12 +00:00
|
|
|
xtn->svc = marc;
|
2021-07-26 15:19:31 +00:00
|
|
|
xtn->sid = sid;
|
2020-06-17 13:53:38 +00:00
|
|
|
|
2021-07-23 11:19:21 +00:00
|
|
|
if (hio_dev_mar_connect(mar, &marc->ci) <= -1)
|
|
|
|
{
|
2021-07-26 15:19:31 +00:00
|
|
|
/* connection failed immediately */
|
2021-07-24 08:43:12 +00:00
|
|
|
xtn->sid = INVALID_SID;
|
2021-07-23 11:19:21 +00:00
|
|
|
hio_dev_mar_halt (mar);
|
|
|
|
return HIO_NULL;
|
|
|
|
}
|
2020-06-18 09:28:36 +00:00
|
|
|
|
2020-06-19 09:17:42 +00:00
|
|
|
return mar;
|
2020-06-18 09:28:36 +00:00
|
|
|
}
|
|
|
|
|
2020-06-19 09:17:42 +00:00
|
|
|
/* ------------------------------------------------------------------- */
|
2020-06-18 09:28:36 +00:00
|
|
|
|
2021-07-27 14:38:12 +00:00
|
|
|
static sess_t* get_session (hio_svc_marc_t* marc, hio_oow_t flagged_sid)
|
2020-06-18 09:28:36 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_t* hio = marc->hio;
|
2021-07-27 14:38:12 +00:00
|
|
|
hio_oow_t sid;
|
2020-06-18 09:28:36 +00:00
|
|
|
sess_t* sess;
|
|
|
|
|
2021-07-27 14:38:12 +00:00
|
|
|
sid = flagged_sid & ~HIO_SVC_MARC_SID_FLAG_ALL;
|
|
|
|
|
|
|
|
if ((flagged_sid & HIO_SVC_MARC_SID_FLAG_AUTO_BOUNDED) && marc->sess.capa > 0)
|
|
|
|
{
|
|
|
|
hio_oow_t i, ubound, mbound;
|
|
|
|
hio_oow_t unused = INVALID_SID;
|
|
|
|
|
|
|
|
/* automatic sid assignment. sid holds the largest session id that can be assigned */
|
|
|
|
ubound = marc->sess.capa;
|
|
|
|
if (sid < ubound) ubound = sid + 1;
|
|
|
|
|
|
|
|
mbound = marc->autoi;
|
|
|
|
if (mbound > ubound) mbound = ubound;
|
|
|
|
for (i = mbound; i < ubound; i++)
|
|
|
|
{
|
|
|
|
sess = &marc->sess.ptr[i];
|
|
|
|
if (sess->dev)
|
|
|
|
{
|
|
|
|
if (!get_first_session_query(sess))
|
|
|
|
{
|
|
|
|
marc->autoi = i;
|
|
|
|
sid = marc->autoi;
|
|
|
|
goto got_sid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else unused = i;
|
|
|
|
}
|
|
|
|
for (i = 0; i < mbound; i++)
|
|
|
|
{
|
|
|
|
sess = &marc->sess.ptr[i];
|
|
|
|
if (sess->dev)
|
|
|
|
{
|
|
|
|
if (!get_first_session_query(sess))
|
|
|
|
{
|
|
|
|
marc->autoi = i;
|
|
|
|
sid = marc->autoi;
|
|
|
|
goto got_sid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else unused = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (unused == INVALID_SID)
|
|
|
|
{
|
|
|
|
if (sid >= ubound)
|
|
|
|
{
|
|
|
|
marc->autoi = sid;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* TODO: more optimizations - take the one with the least enqueued queries */
|
|
|
|
marc->autoi2 = (marc->autoi2 + 1) % ubound;
|
|
|
|
marc->autoi = marc->autoi;
|
|
|
|
sid = marc->autoi2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
marc->autoi = unused;
|
|
|
|
sid = marc->autoi;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
got_sid:
|
2020-06-18 09:28:36 +00:00
|
|
|
if (sid >= marc->sess.capa)
|
|
|
|
{
|
|
|
|
sess_t* tmp;
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_oow_t newcapa, i;
|
2020-06-18 09:28:36 +00:00
|
|
|
|
2021-07-24 08:43:12 +00:00
|
|
|
newcapa = marc->sess.capa + 64; /* TODO: make this configurable? */
|
2020-06-18 09:28:36 +00:00
|
|
|
if (newcapa <= sid) newcapa = sid + 1;
|
2021-07-22 07:30:20 +00:00
|
|
|
newcapa = HIO_ALIGN_POW2(newcapa, 16);
|
2020-06-18 09:28:36 +00:00
|
|
|
|
2021-07-27 14:38:12 +00:00
|
|
|
tmp = (sess_t*)hio_reallocmem(hio, marc->sess.ptr, HIO_SIZEOF(sess_t) * newcapa);
|
2021-07-22 07:30:20 +00:00
|
|
|
if (HIO_UNLIKELY(!tmp)) return HIO_NULL;
|
2020-06-18 09:28:36 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_MEMSET (&tmp[marc->sess.capa], 0, HIO_SIZEOF(sess_t) * (newcapa - marc->sess.capa));
|
2020-06-24 07:37:11 +00:00
|
|
|
for (i = marc->sess.capa; i < newcapa; i++)
|
|
|
|
{
|
|
|
|
tmp[i].svc = marc;
|
|
|
|
tmp[i].sid = i;
|
|
|
|
}
|
2020-06-18 09:28:36 +00:00
|
|
|
|
|
|
|
marc->sess.ptr = tmp;
|
|
|
|
marc->sess.capa = newcapa;
|
|
|
|
}
|
|
|
|
|
2020-06-24 07:37:11 +00:00
|
|
|
sess = &marc->sess.ptr[sid];
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_ASSERT (hio, sess->svc == marc);
|
2021-07-26 15:19:31 +00:00
|
|
|
HIO_ASSERT (hio, sess->sid == sid);
|
2020-06-24 07:37:11 +00:00
|
|
|
|
2020-06-18 09:28:36 +00:00
|
|
|
if (!sess->dev)
|
|
|
|
{
|
|
|
|
sess_qry_t* sq;
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
sq = make_session_query(hio, HIO_SVC_MARC_QTYPE_ACTION, "", 0, HIO_NULL, 0); /* this is a place holder */
|
|
|
|
if (HIO_UNLIKELY(!sq)) return HIO_NULL;
|
2020-06-18 09:28:36 +00:00
|
|
|
|
2021-07-24 08:43:12 +00:00
|
|
|
sess->dev = alloc_device(marc, sess->sid);
|
2021-07-22 07:30:20 +00:00
|
|
|
if (HIO_UNLIKELY(!sess->dev))
|
2020-06-18 09:28:36 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
free_session_query (hio, sq);
|
|
|
|
return HIO_NULL;
|
2020-06-18 09:28:36 +00:00
|
|
|
}
|
|
|
|
|
2020-06-24 03:00:46 +00:00
|
|
|
/* queue initialization with a place holder. the queue maintains a placeholder node.
|
|
|
|
* the first actual data node enqueued is inserted at the back and becomes the second
|
|
|
|
* node in terms of the entire queue.
|
|
|
|
*
|
|
|
|
* PH -> DN1 -> DN2 -> ... -> DNX
|
|
|
|
* ^ ^
|
|
|
|
* q_head q_tail
|
|
|
|
*
|
|
|
|
* get_first_session_query() returns the data of DN1, not the data held in PH.
|
|
|
|
*
|
|
|
|
* the first dequeing operations kills PH.
|
|
|
|
*
|
|
|
|
* DN1 -> DN2 -> ... -> DNX
|
|
|
|
* ^ ^
|
|
|
|
* q_head q_tail
|
|
|
|
*
|
|
|
|
* get_first_session_query() at this point returns the data of DN2, not the data held in DN1.
|
|
|
|
* dequeing kills DN1, however.
|
|
|
|
*/
|
|
|
|
|
2020-06-18 09:28:36 +00:00
|
|
|
sess->q_head = sess->q_tail = sq;
|
|
|
|
}
|
|
|
|
|
|
|
|
return sess;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-27 14:38:12 +00:00
|
|
|
int hio_svc_marc_querywithbchars (hio_svc_marc_t* marc, hio_oow_t flagged_sid, hio_svc_marc_qtype_t qtype, const hio_bch_t* qptr, hio_oow_t qlen, hio_svc_marc_on_result_t on_result, void* qctx)
|
2020-06-18 09:28:36 +00:00
|
|
|
{
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_t* hio = marc->hio;
|
2020-06-18 09:28:36 +00:00
|
|
|
sess_t* sess;
|
2020-06-19 09:17:42 +00:00
|
|
|
sess_qry_t* sq;
|
2020-06-18 09:28:36 +00:00
|
|
|
|
2021-07-27 14:38:12 +00:00
|
|
|
sess = get_session(marc, flagged_sid);
|
2021-07-22 07:30:20 +00:00
|
|
|
if (HIO_UNLIKELY(!sess)) return -1;
|
2020-06-18 09:28:36 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
sq = make_session_query(hio, qtype, qptr, qlen, qctx, on_result);
|
|
|
|
if (HIO_UNLIKELY(!sq)) return -1;
|
2020-06-18 09:28:36 +00:00
|
|
|
|
2020-06-24 03:00:46 +00:00
|
|
|
if (get_first_session_query(sess) || !sess->connected)
|
2020-06-18 09:28:36 +00:00
|
|
|
{
|
2020-06-19 09:17:42 +00:00
|
|
|
/* there are other ongoing queries */
|
|
|
|
enqueue_session_query (sess, sq);
|
2020-06-18 09:28:36 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-06-24 03:00:46 +00:00
|
|
|
/* this is the first query or the device is not connected yet */
|
2020-06-19 09:17:42 +00:00
|
|
|
sess_qry_t* old_q_tail = sess->q_tail;
|
2020-06-24 03:00:46 +00:00
|
|
|
|
2020-06-19 09:17:42 +00:00
|
|
|
enqueue_session_query (sess, sq);
|
2020-06-17 13:53:38 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
HIO_ASSERT (hio, sq->sent == 0);
|
2020-06-24 03:00:46 +00:00
|
|
|
|
|
|
|
sq->sent = 1;
|
2021-07-22 07:30:20 +00:00
|
|
|
if (hio_dev_mar_querywithbchars(sess->dev, sq->qptr, sq->qlen) <= -1)
|
2020-06-19 09:17:42 +00:00
|
|
|
{
|
2020-06-24 03:00:46 +00:00
|
|
|
sq->sent = 0;
|
|
|
|
if (!sess->dev->broken)
|
2020-06-19 09:17:42 +00:00
|
|
|
{
|
2020-06-24 03:00:46 +00:00
|
|
|
/* unlink the the last item added */
|
2021-07-22 07:30:20 +00:00
|
|
|
old_q_tail->sq_next = HIO_NULL;
|
2020-06-19 09:17:42 +00:00
|
|
|
sess->q_tail = old_q_tail;
|
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
free_session_query (hio, sq);
|
2020-06-19 09:17:42 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2020-06-24 03:00:46 +00:00
|
|
|
|
2021-09-03 15:35:36 +00:00
|
|
|
/* the underlying socket of the device might have gotten disconnected.
|
2020-06-24 03:00:46 +00:00
|
|
|
* in such a case, keep the enqueued query with sq->sent 0
|
|
|
|
* and defer actual sending and processing */
|
2020-06-19 09:17:42 +00:00
|
|
|
}
|
2020-06-18 09:28:36 +00:00
|
|
|
}
|
|
|
|
|
2020-06-19 09:17:42 +00:00
|
|
|
return 0;
|
2020-06-18 09:28:36 +00:00
|
|
|
}
|
2020-06-24 07:37:11 +00:00
|
|
|
|
2021-07-22 07:30:20 +00:00
|
|
|
hio_oow_t hio_svc_marc_escapebchars (hio_svc_marc_t* marc, const hio_bch_t* qptr, hio_oow_t qlen, hio_bch_t* buf)
|
2020-06-24 07:37:11 +00:00
|
|
|
{
|
|
|
|
return mysql_real_escape_string(marc->edev, buf, qptr, qlen);
|
|
|
|
}
|