+static void IO_abort_shutdown_callback(struct ev_loop *loop, ev_cleanup *watcher, int revents)
+{
+ AsyncIO *IO = watcher->data;
+ EV_syslog(LOG_DEBUG, "EVENT Q: %s\n", __FUNCTION__);
+
+ assert(IO->ShutdownAbort);
+ IO->ShutdownAbort(IO);
+}
+
+
+/*--------------------------------------------------------------------------------
+ * Server DB IO
+ */
+extern int evdb_count;
+extern pthread_mutex_t DBEventQueueMutex;
+extern HashList *DBInboundEventQueue;
+extern struct ev_loop *event_db;
+extern ev_async DBAddJob;
+extern ev_async DBExitEventLoop;
+
+eNextState QueueDBOperation(AsyncIO *IO, IO_CallBack CB)
+{
+ IOAddHandler *h;
+ int i;
+
+ h = (IOAddHandler*)malloc(sizeof(IOAddHandler));
+ h->IO = IO;
+ h->EvAttch = CB;
+ ev_cleanup_init(&IO->db_abort_by_shutdown,
+ IO_abort_shutdown_callback);
+ IO->db_abort_by_shutdown.data = IO;
+ ev_cleanup_start(event_db, &IO->db_abort_by_shutdown);
+
+ pthread_mutex_lock(&DBEventQueueMutex);
+ EVM_syslog(LOG_DEBUG, "DBEVENT Q\n");
+ i = ++evdb_count ;
+ Put(DBInboundEventQueue, IKEY(i), h, NULL);
+ pthread_mutex_unlock(&DBEventQueueMutex);
+
+ ev_async_send (event_db, &DBAddJob);
+ EVM_syslog(LOG_DEBUG, "DBEVENT Q Done.\n");
+ return eDBQuery;
+}
+
+void ShutDownDBCLient(AsyncIO *IO)
+{
+ CitContext *Ctx =IO->CitContext;
+ become_session(Ctx);
+
+ EVM_syslog(LOG_DEBUG, "DBEVENT Terminating.\n");
+ ev_cleanup_stop(event_db, &IO->db_abort_by_shutdown);
+
+ assert(IO->Terminate);
+ IO->Terminate(IO);
+
+ Ctx->state = CON_IDLE;
+ Ctx->kill_me = 1;
+}
+
+void
+DB_PerformNext(struct ev_loop *loop, ev_idle *watcher, int revents)
+{
+ AsyncIO *IO = watcher->data;
+ EV_syslog(LOG_DEBUG, "event: %s\n", __FUNCTION__);
+ become_session(IO->CitContext);
+
+ ev_idle_stop(event_db, &IO->db_unwind_stack);
+
+ assert(IO->NextDBOperation);
+ switch (IO->NextDBOperation(IO))
+ {
+ case eDBQuery:
+ break;
+ case eSendDNSQuery:
+ case eReadDNSReply:
+ case eConnect:
+ case eSendReply:
+ case eSendMore:
+ case eSendFile:
+ case eReadMessage:
+ case eReadMore:
+ case eReadPayload:
+ case eReadFile:
+ ev_cleanup_stop(loop, &IO->db_abort_by_shutdown);
+ break;
+ case eTerminateConnection:
+ case eAbort:
+ ev_idle_stop(event_db, &IO->db_unwind_stack);
+ ev_cleanup_stop(loop, &IO->db_abort_by_shutdown);
+ ShutDownDBCLient(IO);
+ }
+}
+
+eNextState NextDBOperation(AsyncIO *IO, IO_CallBack CB)
+{
+ IO->NextDBOperation = CB;
+ ev_idle_init(&IO->db_unwind_stack,
+ DB_PerformNext);
+ IO->db_unwind_stack.data = IO;
+ ev_idle_start(event_db, &IO->db_unwind_stack);
+ return eDBQuery;
+}
+
+/*--------------------------------------------------------------------------------
+ * Client IO
+ */
+extern int evbase_count;
+extern pthread_mutex_t EventQueueMutex;