+void StopDBWatchers(AsyncIO *IO)
+{
+ ev_cleanup_stop(event_db, &IO->db_abort_by_shutdown);
+ ev_idle_stop(event_db, &IO->db_unwind_stack);
+}
+
+void ShutDownDBCLient(AsyncIO *IO)
+{
+ CitContext *Ctx =IO->CitContext;
+ become_session(Ctx);
+
+ EVM_syslog(LOG_DEBUG, "DBEVENT Terminating.\n");
+ StopDBWatchers(IO);
+
+ assert(IO->DBTerminate);
+ IO->DBTerminate(IO);
+}
+
+void
+DB_PerformNext(struct ev_loop *loop, ev_idle *watcher, int revents)
+{
+ AsyncIO *IO = watcher->data;
+ IO->Now = ev_now(event_db);
+ EV_syslog(LOG_DEBUG, "%s()", __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;
+extern pthread_mutex_t EventExitQueueMutex;