bool TimerManager::EnableTimer(uint64_t id) { assert(!IsStoped()); MutexLocker locker(&m_mutex); TimerEntry* entry = FindEntry(id); if (entry) { entry->is_enabled = true; SetNextTimeout(id, entry->interval, entry->revision); return true; } return false; }
void POP3SetTimeout(eNextState NextTCPState, pop3aggr *pMsg) { AsyncIO *IO = &pMsg->IO; double Timeout = 0.0; EVP3C_syslog(LOG_DEBUG, "POP3: %s\n", __FUNCTION__); switch (NextTCPState) { case eSendFile: case eSendReply: case eSendMore: Timeout = POP3_C_SendTimeouts[pMsg->State]; /* if (pMsg->State == eDATABody) { / * if we're sending a huge message, we need more time. * / Timeout += StrLength(pMsg->msgtext) / 1024; } */ break; case eReadFile: case eReadMessage: Timeout = POP3_C_ReadTimeouts[pMsg->State]; /* if (pMsg->State == eDATATerminateBody) { / * * some mailservers take a nap before accepting the message * content inspection and such. * / Timeout += StrLength(pMsg->msgtext) / 1024; } */ break; case eReadPayload: Timeout = 100000; /* TODO!!! */ break; case eSendDNSQuery: case eReadDNSReply: case eConnect: case eTerminateConnection: case eDBQuery: case eAbort: case eReadMore://// TODO return; } SetNextTimeout(&pMsg->IO, Timeout); }
uint64_t TimerManager::AddTimer(int64_t interval, bool is_period, CallbackClosure* closure) { assert(interval >= 0); assert(!IsStoped()); MutexLocker locker(&m_mutex); uint64_t id = NewTimerId(); TimerEntry& timer = m_timers[id]; timer.interval = interval; timer.is_period = is_period; timer.closure = closure; timer.is_enabled = true; SetNextTimeout(id, interval, 0); return id; }
void SMTPSetTimeout(eNextState NextTCPState, SmtpOutMsg *Msg) { double Timeout = 0.0; AsyncIO *IO = &Msg->IO; EVS_syslog(LOG_DEBUG, "%s\n", __FUNCTION__); switch (NextTCPState) { case eSendFile: case eSendReply: case eSendMore: Timeout = SMTP_C_SendTimeouts[Msg->State]; if (Msg->State == eDATABody) { /* if we're sending a huge message, * we need more time. */ Timeout += StrLength(Msg->msgtext) / 512; } break; case eReadMessage: Timeout = SMTP_C_ReadTimeouts[Msg->State]; if (Msg->State == eDATATerminateBody) { /* * some mailservers take a nap before accepting * the message content inspection and such. */ Timeout += StrLength(Msg->msgtext) / 512; } break; case eSendDNSQuery: case eReadDNSReply: case eDBQuery: case eReadFile: case eReadMore: case eReadPayload: case eConnect: case eTerminateConnection: case eAbort: return; } SetNextTimeout(&Msg->IO, Timeout); }
bool TimerManager::ModifyTimer(uint64_t id, int64_t interval, CallbackClosure* closure) { assert(!IsStoped()); MutexLocker locker(&m_mutex); TimerEntry* entry = FindEntry(id); if (entry) { entry->interval = interval; if (entry->closure != closure) { delete entry->closure; // release the old closure entry->closure = closure; } entry->revision++; if (entry->is_enabled) { SetNextTimeout(id, interval, entry->revision); } return true; } return false; }
/* virtual */ OP_BOOLEAN ES_TimeoutTimerEvent::Expire() { ES_Context *context = runtime->CreateContext(NULL); if (!context) return OpStatus::ERR_NO_MEMORY; ES_TimeoutThread *thread = OP_NEW(ES_TimeoutThread, (context, shared)); if (!thread) { ES_Runtime::DeleteContext(context); return OpStatus::ERR_NO_MEMORY; } thread->SetOriginInfo(origin_info); thread->SetTimerEvent(this); #ifdef SCOPE_PROFILER thread->SetThreadId(GetScopeThreadId()); #endif // SCOPE_PROFILER if (from_plugin_origin) thread->SetIsPluginThread(); OP_BOOLEAN stat = runtime->GetESScheduler()->AddRunnable(thread); if (stat == OpBoolean::IS_TRUE) /* Thread added to scheduler. Add listener after AddRunnable() since it deletes the thread and all its listeners if scheduler is draining. */ thread->AddListener(this); else if (stat == OpBoolean::IS_FALSE) /* Thread not added. Make it repeat here. */ if (IsRepeating()) { SetNextTimeout(); SetPreviousDelay(GetTotalRequestedDelay()); if (OpStatus::IsMemoryError(GetTimerManager()->RepeatEvent(this))) return OpBoolean::ERR_NO_MEMORY; return OpBoolean::IS_TRUE; } return stat; }
void TimerManager::Dispatch() { uint64_t id; // Make a copy. It's necessary because the entry in the map maybe changed // by it's closure. TimerEntry entry; while (DequeueTimeoutEntry(&id, &entry)) { // Run the closure in unlocked state if (entry.closure != NULL) { entry.closure->Run(id); } MutexLocker locker(&m_mutex); m_running_timer = 0; if (entry.is_period) { TimerMap::iterator it = m_timers.find(id); if (it != m_timers.end()) { // restore the closure if necessory if (entry.closure != NULL) { if (it->second.closure == NULL) { it->second.closure = entry.closure; } else { // the entry in the map has been assign a new one, // release the old closure; delete entry.closure; } } if (it->second.is_enabled) { SetNextTimeout(it->first, it->second.interval, it->second.revision); } } else { // the timer has been removed delete entry.closure; } } } }
static void IO_recv_callback(struct ev_loop *loop, ev_io *watcher, int revents) { const char *errmsg; ssize_t nbytes; AsyncIO *IO = watcher->data; SET_EV_TIME(IO, event_base); switch (IO->NextState) { case eReadFile: nbytes = FileRecvChunked(&IO->IOB, &errmsg); if (nbytes < 0) StrBufPlain(IO->ErrMsg, errmsg, -1); else { if (IO->IOB.ChunkSendRemain == 0) { IO->NextState = eSendReply; assert(IO->ReadDone); ev_io_stop(event_base, &IO->recv_event); PostInbound(IO); return; } else return; } break; default: nbytes = StrBuf_read_one_chunk_callback(IO->RecvBuf.fd, 0, &IO->RecvBuf); break; } #ifdef BIGBAD_IODBG { long nbytes; int rv = 0; char fn [SIZ]; FILE *fd; const char *pch = ChrPtr(IO->RecvBuf.Buf); const char *pchh = IO->RecvBuf.ReadWritePointer; if (pchh == NULL) pchh = pch; nbytes = StrLength(IO->RecvBuf.Buf) - (pchh - pch); snprintf(fn, SIZ, "/tmp/foolog_ev_%s.%d", ((CitContext*)(IO->CitContext))->ServiceName, IO->SendBuf.fd); fd = fopen(fn, "a+"); if (fd == NULL) { syslog(LOG_EMERG, "failed to open file %s: %s", fn, strerror(errno)); cit_backtrace(); exit(1); } fprintf(fd, "Read: BufSize: %ld BufContent: [", nbytes); rv = fwrite(pchh, nbytes, 1, fd); if (!rv) printf("failed to write debug to %s!\n", fn); fprintf(fd, "]\n"); fclose(fd); } #endif if (nbytes > 0) { HandleInbound(IO); } else if (nbytes == 0) { StopClientWatchers(IO, 1); SetNextTimeout(IO, 0.01); return; } else if (nbytes == -1) { if (errno != EAGAIN) { // FD is gone. kick it. StopClientWatchers(IO, 1); EV_syslog(LOG_DEBUG, "IO_recv_callback(): Socket Invalid! [%d] [%s] [%d]\n", errno, strerror(errno), IO->SendBuf.fd); StrBufPrintf(IO->ErrMsg, "Socket Invalid! [%s]", strerror(errno)); SetNextTimeout(IO, 0.01); } return; } }
static void IO_send_callback(struct ev_loop *loop, ev_io *watcher, int revents) { int rc; AsyncIO *IO = watcher->data; const char *errmsg = NULL; SET_EV_TIME(IO, event_base); become_session(IO->CitContext); #ifdef BIGBAD_IODBG { int rv = 0; char fn [SIZ]; FILE *fd; const char *pch = ChrPtr(IO->SendBuf.Buf); const char *pchh = IO->SendBuf.ReadWritePointer; long nbytes; if (pchh == NULL) pchh = pch; nbytes = StrLength(IO->SendBuf.Buf) - (pchh - pch); snprintf(fn, SIZ, "/tmp/foolog_ev_%s.%d", ((CitContext*)(IO->CitContext))->ServiceName, IO->SendBuf.fd); fd = fopen(fn, "a+"); if (fd == NULL) { syslog(LOG_EMERG, "failed to open file %s: %s", fn, strerror(errno)); cit_backtrace(); exit(1); } fprintf(fd, "Send: BufSize: %ld BufContent: [", nbytes); rv = fwrite(pchh, nbytes, 1, fd); if (!rv) printf("failed to write debug to %s!\n", fn); fprintf(fd, "]\n"); #endif switch (IO->NextState) { case eSendFile: rc = FileSendChunked(&IO->IOB, &errmsg); if (rc < 0) StrBufPlain(IO->ErrMsg, errmsg, -1); break; default: rc = StrBuf_write_one_chunk_callback(IO->SendBuf.fd, 0, &IO->SendBuf); } #ifdef BIGBAD_IODBG fprintf(fd, "Sent: BufSize: %d bytes.\n", rc); fclose(fd); } #endif if (rc == 0) { ev_io_stop(event_base, &IO->send_event); switch (IO->NextState) { case eSendMore: assert(IO->SendDone); IO->NextState = IO->SendDone(IO); if ((IO->NextState == eTerminateConnection) || (IO->NextState == eAbort) ) ShutDownCLient(IO); else { ev_io_start(event_base, &IO->send_event); } break; case eSendFile: if (IO->IOB.ChunkSendRemain > 0) { ev_io_start(event_base, &IO->recv_event); SetNextTimeout(IO, 100.0); } else { assert(IO->ReadDone); IO->NextState = IO->ReadDone(IO); switch(IO->NextState) { case eSendDNSQuery: case eReadDNSReply: case eDBQuery: case eConnect: break; case eSendReply: case eSendMore: case eSendFile: ev_io_start(event_base, &IO->send_event); break; case eReadMessage: case eReadMore: case eReadPayload: case eReadFile: break; case eTerminateConnection: case eAbort: break; } } break; case eSendReply: if (StrBufCheckBuffer(&IO->SendBuf) != eReadSuccess) break; IO->NextState = eReadMore; case eReadMore: case eReadMessage: case eReadPayload: case eReadFile: if (StrBufCheckBuffer(&IO->RecvBuf) == eBufferNotEmpty) { HandleInbound(IO); } else { ev_io_start(event_base, &IO->recv_event); } break; case eDBQuery: /* * we now live in another queue, * so we have to unregister. */ ev_cleanup_stop(loop, &IO->abort_by_shutdown); break; case eSendDNSQuery: case eReadDNSReply: case eConnect: case eTerminateConnection: case eAbort: break; } } else if (rc < 0) { if (errno != EAGAIN) { StopClientWatchers(IO, 1); EV_syslog(LOG_DEBUG, "IO_send_callback(): Socket Invalid! [%d] [%s] [%d]\n", errno, strerror(errno), IO->SendBuf.fd); StrBufPrintf(IO->ErrMsg, "Socket Invalid! [%s]", strerror(errno)); SetNextTimeout(IO, 0.01); } } /* else : must write more. */ }