// OK, we've now got all the headers read in, so we're ready to start // on the body. But we need to see what info we can glean from the headers // first... void Response::BeginBody() { m_Chunked = false; m_Length = -1; // unknown m_WillClose = false; // using chunked encoding? const char* trenc = getheader( "transfer-encoding" ); if( trenc && 0==_stricmp( trenc, "chunked") ) { m_Chunked = true; m_ChunkLeft = -1; // unknown } m_WillClose = CheckClose(); // length supplied? const char* contentlen = getheader( "content-length" ); if( contentlen && !m_Chunked ) { m_Length = atoi( contentlen ); } // check for various cases where we expect zero-length body if( m_Status == NO_CONTENT || m_Status == NOT_MODIFIED || ( m_Status >= 100 && m_Status < 200 ) || // 1xx codes have no body m_Method == "HEAD" ) { m_Length = 0; } // if we're not using chunked mode, and no length has been specified, // assume connection will close at end. if( !m_WillClose && !m_Chunked && m_Length == -1 ) m_WillClose = true; // Invoke the user callback, if any if( m_Connection.m_ResponseBeginCB ) (m_Connection.m_ResponseBeginCB)( this, m_Connection.m_UserData ); /* printf("---------BeginBody()--------\n"); printf("Length: %d\n", m_Length ); printf("WillClose: %d\n", (int)m_WillClose ); printf("Chunked: %d\n", (int)m_Chunked ); printf("ChunkLeft: %d\n", (int)m_ChunkLeft ); printf("----------------------------\n"); */ // now start reading body data! if( m_Chunked ) m_State = CHUNKLEN; else m_State = BODY; }
void Connection::ThreadStarter() { log_trace(); while (threadRunning_ && !CheckClose()) { Work(100); } log_debug("Connection thread exiting, fd=" << socket_.GetFileDescriptor()); // force the close to close since the thread may not be deleted right away socket_.Close(); threadRunning_ = false; }
void Connection::Work(int ms) { int timeLeft; struct timeval startTime; struct timeval currentTime; gettimeofday( &startTime, 0 ); do { //log_debug("Work: timeLeft=" << timeLeft.count()); // Construct the sets of descriptors we are interested in fd_set inFd, outFd; FD_ZERO(&inFd); FD_ZERO(&outFd); // add connection socket int maxFd = socket_.GetFileDescriptor(); if (WaitForReadability()) FD_SET(maxFd, &inFd); if (WaitForWritability()) FD_SET(maxFd, &outFd); // Check for events int nEvents; if (ms < 0) nEvents = select(maxFd + 1, &inFd, &outFd, NULL, NULL); else { gettimeofday( ¤tTime, 0 ); timeLeft = ms - MilliTimeDiff(currentTime,startTime); struct timeval tv; tv.tv_sec = timeLeft / 1000; tv.tv_usec = (timeLeft - tv.tv_sec*1000) * 1000; nEvents = select(maxFd + 1, &inFd, &outFd, NULL, &tv); } if (nEvents < 0) break; // Process server events int fd = GetFileDescriptor(); if ((FD_ISSET(fd, &inFd )) || (FD_ISSET(fd, &outFd))) Process(); gettimeofday( ¤tTime, 0 ); timeLeft = ms - MilliTimeDiff(currentTime,startTime); } while (!CheckClose() && ((ms < 0) || (timeLeft > 0))); }
void cUIManager::Update() { mElapsed = mWindow->Elapsed(); bool wasDraggingControl = IsControlDragging(); mControl->Update(); cUIControl * pOver = mControl->OverFind( mKM->GetMousePosf() ); if ( pOver != mOverControl ) { if ( NULL != mOverControl ) { SendMsg( mOverControl, cUIMessage::MsgMouseExit ); mOverControl->OnMouseExit( mKM->GetMousePos(), 0 ); } mOverControl = pOver; if ( NULL != mOverControl ) { SendMsg( mOverControl, cUIMessage::MsgMouseEnter ); mOverControl->OnMouseEnter( mKM->GetMousePos(), 0 ); } } else { if ( NULL != mOverControl ) mOverControl->OnMouseMove( mKM->GetMousePos(), mKM->PressTrigger() ); } if ( mKM->PressTrigger() ) { /*if ( !wasDraggingControl && mOverControl != mFocusControl ) FocusControl( mOverControl );*/ if ( NULL != mOverControl ) { mOverControl->OnMouseDown( mKM->GetMousePos(), mKM->PressTrigger() ); SendMsg( mOverControl, cUIMessage::MsgMouseDown, mKM->PressTrigger() ); } if ( !mFirstPress ) { mDownControl = mOverControl; mMouseDownPos = mKM->GetMousePos(); mFirstPress = true; } } if ( mKM->ReleaseTrigger() ) { if ( NULL != mFocusControl ) { if ( !wasDraggingControl ) { if ( mOverControl != mFocusControl ) FocusControl( mOverControl ); mFocusControl->OnMouseUp( mKM->GetMousePos(), mKM->ReleaseTrigger() ); SendMsg( mFocusControl, cUIMessage::MsgMouseUp, mKM->ReleaseTrigger() ); if ( mKM->ClickTrigger() ) { // mDownControl == mOverControl && SendMsg( mFocusControl, cUIMessage::MsgClick, mKM->ClickTrigger() ); mFocusControl->OnMouseClick( mKM->GetMousePos(), mKM->ClickTrigger() ); if ( mKM->DoubleClickTrigger() ) { SendMsg( mFocusControl, cUIMessage::MsgDoubleClick, mKM->DoubleClickTrigger() ); mFocusControl->OnMouseDoubleClick( mKM->GetMousePos(), mKM->DoubleClickTrigger() ); } } } } mFirstPress = false; } CheckClose(); }
//--------------------------------------------------------------------------------------------------------------------------- //StartServer() //start listen //--------------------------------------------------------------------------------------------------------------------------- int CIocpServer::StartServer(const char *local_ip,const char *local_port) { if(!m_Inited) { fprintf(stderr, "Run Init() first !\n"); return -1; } SOCKET_OBJ *sockobj=NULL; HANDLE hrc; int endpointcount=0, rc, i; HANDLE event_accept; struct addrinfo *res=NULL, *ptr=NULL; #ifdef LOG_LEVEL2 printf("LOG_LEVEL2"); #else // #ifdef LOG_LEVEL1 printf("LOG_LEVEL1"); #else printf("LOG_NONE"); #endif // #endif printf("\n\n连接线程:%d: 监听线程:%d; 平均连接数:%d ; ", m_CLThreads,m_Threads,AVERAGE_CONNECTIONS); printf("IOCP版本: %s;\n",IOCP_VERSION); #ifdef ENABLE_KEEPALIVE printf("心跳检测:开启; "); #else printf("心跳检测:关闭; "); #endif printf("心跳超时:%d; 关闭延时:%d\n",KEEPALIVE_TIME,CLOSE_DELAY); res = ResolveAddress(local_ip, local_port, AF_INET, SOCK_STREAM, IPPROTO_TCP); if (res == NULL) { fprintf(stderr, "ResolveAddress failed to return any addresses!\n"); return -1; } ptr = res; if (ptr) { sockobj = GetSocketObj(INVALID_SOCKET); // create the socket sockobj->s = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); if (sockobj->s == INVALID_SOCKET) { fprintf(stderr,"socket failed: %d\n", WSAGetLastError()); return -1; } // Associate the socket and its SOCKET_OBJ to the completion port hrc = CreateIoCompletionPort((HANDLE)sockobj->s, CompletionPort, (ULONG_PTR)sockobj, 0); if (hrc == NULL) { fprintf(stderr, "CreateIoCompletionPort failed: %d\n", GetLastError()); return -1; } // bind the socket to a local address and port rc = bind(sockobj->s, ptr->ai_addr, (int)ptr->ai_addrlen); if (rc == SOCKET_ERROR) { fprintf(stderr, "bind failed: %d\n", WSAGetLastError()); return -1; } BUFFER_OBJ *acceptobj=NULL; GUID guidAcceptEx = WSAID_ACCEPTEX; GUID guidGetAcceptExSockaddrs = WSAID_GETACCEPTEXSOCKADDRS; DWORD bytes; // Need to load the Winsock extension functions from each provider // -- e.g. AF_INET and AF_INET6. rc = WSAIoctl( sockobj->s, SIO_GET_EXTENSION_FUNCTION_POINTER, &guidAcceptEx, sizeof(guidAcceptEx), &lpfnAcceptEx, sizeof(lpfnAcceptEx), &bytes, NULL, NULL ); if (rc == SOCKET_ERROR) { fprintf(stderr, "WSAIoctl: SIO_GET_EXTENSION_FUNCTION_POINTER failed: %d\n", WSAGetLastError()); return -1; } rc = WSAIoctl( sockobj->s, SIO_GET_EXTENSION_FUNCTION_POINTER, &guidGetAcceptExSockaddrs, sizeof(guidGetAcceptExSockaddrs), &lpfnGetAcceptExSockaddrs, sizeof(lpfnGetAcceptExSockaddrs), &bytes, NULL, NULL ); if (rc == SOCKET_ERROR) { fprintf(stderr, "WSAIoctl: SIO_GET_EXTENSION_FUNCTION_POINTER faled: %d\n", WSAGetLastError()); return -1; } // For TCP sockets, we need to "listen" on them rc = _(sockobj->s, 32); if (rc == SOCKET_ERROR) { fprintf(stderr, "listen failed: %d\n", WSAGetLastError()); return -1; } event_accept = CreateEvent(NULL, TRUE, FALSE, NULL); if(event_accept == NULL) { fprintf(stderr,"event_accept CreateEvent failed: %d\n",GetLastError()); return -1; } rc = WSAEventSelect(sockobj->s,event_accept,FD_ACCEPT); if (rc == SOCKET_ERROR) { fprintf(stderr, "WSAEventSelect failed: %d\n", WSAGetLastError()); return -1; } // Post the AcceptEx(s) for(i=0; i < DEFAULT_ACCEPTEX_COUNT ;i++) { acceptobj = GetBufferObj(); sockobj->recvobj = acceptobj; if(PostAccept(sockobj, acceptobj) != 0) { FreeBufferObj(acceptobj); fprintf(stderr, "PostAccept failed: %d\n", WSAGetLastError()); return -1; } } endpointcount++; ptr = ptr->ai_next; } // free the addrinfo structure for the 'bind' address freeaddrinfo(res); DWORD sleeptime = CLOSE_DELAY / 2; //每次sleep的时间 #ifdef LOG_STATUS long sock=0; long buf=0; #endif if(sleeptime < 50) //限制在50ms以外 sleeptime = 50; DWORD time_ontimer=GetTickCount(); DWORD time_close = time_ontimer; DWORD time_alive = time_ontimer; DWORD newtime; BUFFER_OBJ *acceptobj; printf("\n>>> 服务器地址: %s: 端口号: %s <<<\n\n", local_ip, local_port); while (1) { rc = WaitForSingleObject(event_accept,sleeptime); if(rc == WAIT_FAILED) { fprintf(stderr,"WaitForSingleObject Failed:%d\n",GetLastError()); break; } else if(rc != WAIT_TIMEOUT) //GOT FD_ACCEPT { // acceptobj = GetBufferObj(); // PostAccept(sockobj,acceptobj); if(m_accept_count < DEFAULT_ACCEPTEX_COUNT /2) { for(int i=0;i<DEFAULT_ACCEPTEX_COUNT/2;i++) { acceptobj = GetBufferObj(); PostAccept(sockobj,acceptobj); } } ResetEvent(event_accept); } newtime = GetTickCount(); if(newtime - time_ontimer > 3000) // 3秒 { OnTimer(); //call virtual timer(); time_ontimer = newtime; #ifdef LOG_STATUS //显示服务器状态 if(sock != gTotalSock || buf != gTotalBuf) { Log_Server.Write("服务器状态 : sock : %d ; buf : %d ; IoCount : %d ;",gTotalSock,gTotalBuf,gIoCount); sock = gTotalSock; buf = gTotalBuf; } #endif } //Check Close if(newtime - time_close > sleeptime) { time_close = newtime; CheckClose(); } if(newtime - time_alive > KEEPALIVE_TIME / 3) { CheckAlive(); time_alive = newtime; } } WSACleanup(); return 0; }
int main (int argc, char *argv[]) { int Thread; int c; char Input[MAXCMD]; char *Arg; struct sigaction SigAct; int Fed; int Len; int rc; int IsUrgent; int KeepRunning=1; int RunAsDaemon=0; int ResetQueue=0; int KillScheduler=0; int Test=0; /* 1=test and continue, 2=test and quit */ pid_t Pid; /* check args */ while((c = getopt(argc,argv,"dkHiIL:lvqRtTh")) != -1) { switch(c) { case 'd': RunAsDaemon=1; break; case 'H': IgnoreHost=1; break; case 'i': DB = DBopen(); if (!DB) { fprintf(stderr, "FATAL: Unable to connect to database\n"); exit(-1); } /* Nothing to initialize */ DBclose(DB); return(0); case 'I': UseStdin=1; break; case 'k': /* kill the scheduler */ KillScheduler = 1; case 'l': /* tell the scheduler to redo logs */ break; case 'L': LogFile=optarg; break; case 'q': ShowState=0; break; case 'R': ResetQueue=1; break; case 't': Test=2; break; case 'T': Test=1; break; case 'v': Verbose++; break; case 'h': default: Usage(argv[0]); DBclose(DB); exit(-1); } } if ((optind != argc-1) && (optind != argc)) { Usage(argv[0]); DBclose(DB); exit(-1); } /* set to PROJECTUSER and PROJECTGROUP */ SetPuserPgrp(ProcessName); if (KillScheduler) { DB = DBopen(); if (!DB) { fprintf(stderr, "FATAL: Unable to connect to database\n"); exit(-1); } /* kill scheduler */ LogPrint("Scheduler kill requested. Killing scheduler.\n"); StopScheduler(1); StopWatchdog(); exit(0); } /* Become a daemon? */ if (RunAsDaemon) { /* do not close stdout/stderr when using a LogFile */ rc = daemon(0,(LogFile!=NULL)); fclose(stdin); } /* must be after uid is set since this might create the log file */ LogPrint("Scheduler started. %s\n", BuildVersion); /* Lock the scheduler, so no other scheduler can run */ rc = LockName(ProcessName); if (rc > 0) /* already locked */ { Pid = rc; } else if (rc == 0) /* new lock */ { Pid = LockGetPID(ProcessName); if (!Pid) { LogPrint("*** %s lock error ***\n", ProcessName); exit(-1); } } else { LogPrint("*** %s lock failed. Scheduler exitting. ***\n", ProcessName); exit(-1); } if (Verbose) LogPrint("*** %s successfully locked, pid %d ***\n", ProcessName, Pid); /**** From here on, I am the only scheduler running ****/ /**************************************/ /* catch signals */ /**************************************/ memset(&SigAct,0,sizeof(SigAct)); SigAct.sa_sigaction = HandleSig; sigemptyset(&(SigAct.sa_mask)); SigAct.sa_flags = SA_SIGINFO | SA_RESTART; sigaction(SIGCHLD,&SigAct,NULL); /* handle signals to the parent */ SigAct.sa_flags = SA_SIGINFO | SA_RESTART; SigAct.sa_sigaction = ParentSig; if (sigaction(SIGSEGV,&SigAct,NULL) != 0) perror("SIGSEGV"); if (sigaction(SIGQUIT,&SigAct,NULL) != 0) perror("SIGQUIT"); if (sigaction(SIGTERM,&SigAct,NULL) != 0) perror("SIGTERM"); if (sigaction(SIGINT,&SigAct,NULL) != 0) perror("SIGINT"); if (sigaction(SIGUSR1,&SigAct,NULL) != 0) perror("SIGUSR1"); if (sigaction(SIGUSR2,&SigAct,NULL) != 0) perror("SIGUSR2"); if (sigaction(SIGALRM,&SigAct,NULL) != 0) perror("SIGALRM"); /* ignore dead pipes when using -lpq -- see http://archives.postgresql.org/pgsql-bugs/2003-03/msg00118.php */ signal(SIGPIPE,SIG_IGN); signal(SIGALRM,SIG_IGN); /* ignore self-wakeups */ /* Prepare logging */ LogPrint("*** Scheduler started, PID %d ***\n", Pid); /* Log to file? (Not if I'm killing schedulers) */ if ((dup2(fileno(stdout),fileno(stderr))) < 0) { LogPrint("FATAL: Unable to write to redirect stderr to log. Exiting. \n"); DBclose(DB); exit(-1); } /* init queue */ DB = DBopen(); if (!DB) { LogPrint("FATAL: Unable to connect to database. Exiting. \n"); exit(-1); } DBSetHostname(); /* Prepare for logging errors to DB */ DBErrorInit(); /* If we're resetting the queue */ if (ResetQueue) { /* If someone has a start without an end, then it is a hung process */ DBLockAccess(DB,"UPDATE jobqueue SET jq_starttime=null WHERE jq_endtime is NULL;"); LogPrint("Job queue reset.\n"); } /* init storage */ DBQinit(); if (optind == argc) InitEngines(DEFAULTSETUP); else InitEngines(argv[optind]); /* Check for good agents */ if (SelfTest()) { LogPrint("FATAL: Self Test failed. Inconsistent agent(s) detected. Exiting. \n"); DBclose(DB); exit(-1); } /* Check for competing schedulers */ if (DBCheckSchedulerUnique()) { /* Yes, a scheduler is running. So log and exit. */ LogPrint("*** Scheduler not starting since another currently running. ***\n"); exit(0); } else DBCheckStatus(); /* clean scheduler_status and jobqueue tables */ /* See if we're testing */ if (Test) { rc = TestEngines(); /* rc = number of engine failures */ if (rc == 0) LogPrint("STATUS: All scheduler agents are operational.\n"); else LogPrint("STATUS: %d agents failed to initialize.\n",rc); if ((Test > 1) || rc) { LogPrint("*** %d agent failures. Scheduler exiting. \n", rc); /* clean up scheduler */ StopScheduler(0); exit(0); } } /**************************************/ /* while there are commands to run... */ /**************************************/ Thread=0; Fed=0; while(KeepRunning) { SaveStatus(); /* check for data to process */ if (UseStdin) { rc = SelectAnyData(1,fileno(stdin)); if (feof(stdin)) SLOWDEATH=1; } else rc = SelectAnyData(0,0); if (rc & 0x01) /* got stdin input to feed to a child */ { IsUrgent=0; Len=ReadCmd(stdin,Input,MAXCMD); if (Len < 0) break; /* skip blank lines and EOF */ if (Len == 0) continue; /* skip blank lines and EOF */ if (Input[0]=='!') { IsUrgent=1; Input[0]=' '; } /* Got a command! */ if (Verbose) LogPrint("Parent got command: %s\n",Input); Arg = strchr(Input,'|'); if (!Arg) { LogPrint("ERROR: Unknown command (len=%d) '%s'\n",Len,Input); continue; /* skip unknown lines */ } Arg[0]='\0'; Arg++; /* skip space */ while((Arg[0] != '\0') && isspace(Arg[0])) Arg++; /* feed command to child */ /* handle special commands (scheduler is the child) */ Fed=SchedulerCommand(Input,Arg); /* if command needs child, find a child to feed it to */ while(!Fed) { Thread = GetChild(Input,IsUrgent); if (Thread < 0) { if (SelectAnyData(0,0) & 0x02) /* wait for a child to become ready */ { Thread = GetChild(Input,IsUrgent); } } if (Thread >= 0) { if (CM[Thread].Status != ST_RUNNING) { ChangeStatus(Thread,ST_RUNNING); } if (Verbose) LogPrint("(a) Feeding child[%d]: '%s'\n",Thread,Arg); memset(CM[Thread].Parm,'\0',MAXCMD); strcpy(CM[Thread].Parm,Arg); Input[Len++]='\n'; /* add a \n to end of Arg */ write(CM[Thread].ChildStdin,Arg,strlen(Arg)); Fed=1; } /* Thread == -1 is a timeout -- retry the request */ else if (Thread <= -2) { LogPrint("ERROR: No living engines for '%s'\n",Input); Fed=1; /* skip this bad command */ } } /* while not Fed */ } /* if processing stdin input */ else { /* this will pause if it detects a fast loop */ Fed = DBProcessQueue(DB); } // if (Verbose) printf("Time: %d Fed=%d\n",(int)time(NULL),Fed); if (Fed==0) { /* What happens if there was no job to process? */ StaleChild(); if (SLOWDEATH) { Thread=0; while((Thread < MaxThread) && (CM[Thread].Status != ST_RUNNING)) Thread++; /* nothing running? Quit! */ if (Thread >= MaxThread) KeepRunning=0; /* else, keep running */ } /* if SLOWDEATH */ } } /* while reading a command */ /* if it gets here, then either all children are dead or there is no more input */ /* wait for all children to finish */ while(RunCount > 0) { SelectAnyData(0,0); } /* tell children "no more food" by closing stdin */ if (Verbose) LogPrint("Telling all children: No more items to process.\n"); for(Thread=0; Thread < MaxThread; Thread++) { if (CM[Thread].Status > ST_FREE) CheckClose(CM[Thread].ChildStdin); } /* At this point, there should be no children */ SLOWDEATH=1; SelectAnyData(0,0); /* clean up: kill children (should be redundant) */ signal(SIGCHLD,SIG_IGN); /* ignore screams of death */ for(Thread=0; (Thread < MaxThread); Thread++) { if (CM[Thread].Status > ST_FREE) { /* kill the children! kill! kill! */ if (CM[Thread].Status == ST_RUNNING) { if (CM[Thread].IsDB) DBremoveChild(Thread,1,"Scheduler ended"); } CM[Thread].IsDB=0; CheckClose(CM[Thread].ChildStdin); CheckClose(CM[Thread].ChildStdinRev); CheckClose(CM[Thread].ChildStdout); CheckClose(CM[Thread].ChildStdoutRev); CM[Thread].ChildStdin = 0; CM[Thread].ChildStdinRev = 0; CM[Thread].ChildStdout = 0; CM[Thread].ChildStdoutRev = 0; ChangeStatus(Thread,ST_FREE); if (CM[Thread].ChildPid) kill(CM[Thread].ChildPid,SIGKILL); } } /* scheduler cleanup */ if (DB) DBErrorClose(); /* currently a noop */ DBQclose(); /* cleanup scheduler */ StopScheduler(0); /* print statistics */ DebugThreads(1); LogPrint("*** Scheduler completed. Exiting. ***\n"); return(0); } /* main() */