+ 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;
+
+ pthread_mutex_lock(&DBEventQueueMutex);
+ if (DBInboundEventQueue == NULL)
+ {
+ /* shutting down... */
+ free(h);
+ EVM_syslog(LOG_DEBUG, "DBEVENT Q exiting.\n");
+ pthread_mutex_unlock(&DBEventQueueMutex);
+ return eAbort;
+ }
+ EVM_syslog(LOG_DEBUG, "DBEVENT Q\n");
+ i = ++evdb_count ;
+ Put(DBInboundEventQueue, IKEY(i), h, NULL);
+ pthread_mutex_unlock(&DBEventQueueMutex);
+
+ pthread_mutex_lock(&DBEventExitQueueMutex);
+ if (event_db == NULL)
+ {
+ pthread_mutex_unlock(&DBEventExitQueueMutex);
+ return eAbort;
+ }
+ ev_async_send (event_db, &DBAddJob);
+ pthread_mutex_unlock(&DBEventExitQueueMutex);
+
+ EVM_syslog(LOG_DEBUG, "DBEVENT Q Done.\n");
+ return eDBQuery;
+}
+
+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;