DEFINE_CONSTRUCTOR_END /** * @brief simulate class CCycbuffer destructor * * free all the simulate class member variable, * @author hankejia * @date 2012-07-05 * @param[in] pthis the pointer point to the CCycBuffer. * @return NONE */ DEFINE_DESTRUCTOR_BEGIN( CCycBuffer ) { CCycBuffer *this = (CCycBuffer *)pthis; CycBuffer_handle * handle = (CycBuffer_handle *)this->handle; //虚构时,如果当前还有线程在Push流程中等待 //那么首先Pop出Buffer中的所有数据,唤醒在Push //中等待的线程,等待其完成push操作。 Condition_Lock( handle->mDataCon ); if ( !( handle->mPushComplete ) ) { Condition_Unlock( handle->mDataCon ); Clean( this ); //唤醒在Push中等待的线程 Condition_Signal( &(handle->mDataCon) ); Condition_Wait( &(handle->mDataCon) ); Condition_Unlock( handle->mDataCon ); } else Condition_Unlock( handle->mDataCon ); //如果当前还有线程在pop流程中等待,那么首先 //向Buffer中Push数据,唤醒在Pop中等待的线程,等 //待其完成pop操作。 Condition_Lock( handle->mDataCon ); if ( !( handle->mPopComplete ) ) { Condition_Unlock( handle->mDataCon ); FakePushFull( this ); //唤醒在Pop中等待的线程 Condition_Signal( &(handle->mDataCon) ); Condition_Wait( &handle->mDataCon ); Condition_Unlock( handle->mDataCon ); } else Condition_Unlock( handle->mDataCon ); DestroyCycBuffer( this ); Condition_Destroy( &( handle->mDataCon ) ); Condition_Destroy( &( handle->mWriteDataCon ) ); //Condition_Destroy( &( handle->mWaitForPopCon ) ); //Condition_Destroy( &( handle->mWaitForPushCon ) ); free( handle ); }
/* * This function is called only when the reporter thread * This function is the loop that the reporter thread processes */ void reporter_spawn( thread_Settings *thread ) { do { // This section allows for safe exiting with Ctrl-C Condition_Lock ( ReportCond ); if ( ReportRoot == NULL ) { // Allow main thread to exit if Ctrl-C is received thread_setignore(); Condition_Wait ( &ReportCond ); // Stop main thread from exiting until done with all reports thread_unsetignore(); } Condition_Unlock ( ReportCond ); again: if ( ReportRoot != NULL ) { ReportHeader *temp = ReportRoot; //Condition_Unlock ( ReportCond ); if(temp->report.mThreadMode == kMode_Client){ synchronize(); } if ( reporter_process_report ( temp ) ) { // This section allows for more reports to be added while // the reporter is processing reports without needing to // stop the reporter or immediately notify it Condition_Lock ( ReportCond ); if ( temp == ReportRoot ) { // no new reports ReportRoot = temp->next; } else { // new reports added ReportHeader *itr = ReportRoot; while ( itr->next != temp ) { itr = itr->next; } itr->next = temp->next; } // finished with report so free it free( temp ); Condition_Unlock ( ReportCond ); Condition_Signal( &ReportDoneCond ); if (ReportRoot) goto again; } Condition_Signal( &ReportDoneCond ); usleep(10000); } else { //Condition_Unlock ( ReportCond ); } } while ( 1 ); }
int photograph( void *pbuf, int size) { unsigned long outsize; int ret; VideoStream_Enc_Reset(); //printf("%d\n", h_eid); void * buf; if( 2 == index_file ) ret = frame_encode(h_eid , pbuf+(parse.width*parse.height*3/2), &buf, &outsize); else ret = frame_encode(h_eid, pbuf, &buf, &outsize); if(ret == 0) { Condition_Lock( g_conMangerPh ); g_phsize = outsize; Condition_Signal( &g_conMangerPh ); Condition_Unlock( g_conMangerPh ); } VideoStream_Enc_Reset(); return 0; }
/* * ReportServerUDP will generate a report of the UDP * statistics as reported by the server on the client * side. */ void ReportServerUDP( thread_Settings *agent, server_hdr *server ) { if ( (ntohl(server->flags) & HEADER_VERSION1) != 0 && isServerReport( agent ) ) { /* * Create in one big chunk */ ReportHeader *reporthdr = (ReportHeader *) malloc( sizeof(ReportHeader) ); Transfer_Info *stats = &reporthdr->report.info; if ( reporthdr != NULL ) { stats->transferID = agent->mSock; stats->groupID = (agent->multihdr != NULL ? agent->multihdr->groupID : -1); reporthdr->agentindex = -1; reporthdr->reporterindex = -1; reporthdr->report.type = SERVER_RELAY_REPORT; reporthdr->report.mode = agent->mReportMode; stats->mFormat = agent->mFormat; stats->jitter = ntohl( server->jitter1 ); stats->jitter += ntohl( server->jitter2 ) / (double)rMillion; #ifdef HAVE_INT64_T stats->TotalLen = (((max_size_t) ntohl( server->total_len1 )) << 32) + ntohl( server->total_len2 ); #else stats->TotalLen = ntohl( server->total_len2 ); #endif stats->startTime = 0; stats->endTime = ntohl( server->stop_sec ); stats->endTime += ntohl( server->stop_usec ) / (double)rMillion; stats->cntError = ntohl( server->error_cnt ); stats->cntOutofOrder = ntohl( server->outorder_cnt ); stats->cntDatagrams = ntohl( server->datagrams ); stats->mUDP = (char)kMode_Server; reporthdr->report.connection.peer = agent->local; reporthdr->report.connection.size_peer = agent->size_local; reporthdr->report.connection.local = agent->peer; reporthdr->report.connection.size_local = agent->size_peer; #ifdef HAVE_THREAD /* * Update the ReportRoot to include this report. */ Condition_Lock( ReportCond ); reporthdr->next = ReportRoot; ReportRoot = reporthdr; Condition_Signal( &ReportCond ); Condition_Unlock( ReportCond ); #else /* * Process the report in this thread */ reporthdr->next = NULL; process_report ( reporthdr ); #endif } else { FAIL(1, "Out of Memory!!\n", agent); } } }
/* ------------------------------------------------------------------- * unset a thread from being ignorable, so joinall will wait on it * this simply increments the thread count that joinall uses. * This is utilized by the reporter thread which knows when it * is ok to quit (aka no pending reports). * ------------------------------------------------------------------- */ void thread_unsetignore( void ) { Condition_Lock( thread_sNum_cond ); IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Unsetting ignorable thread.\r\n" ) ); thread_sNum++; IPERF_DEBUGF( CONDITION_DEBUG | IPERF_DBG_TRACE, ( "Signaling thread_sNum_cond condition.\r\n" ) ); Condition_Signal( &thread_sNum_cond ); Condition_Unlock( thread_sNum_cond ); } // end thread_unsetignore
/** * @brief write cyc buffer is data to file * * @author hankejia * @date 2012-07-05 * @param[in] pthis the pointer point to the CCycBuffer. * @param[in] fd file is descriptor.the cyc buffer is data will write to this file * @param[in] iSize how many data in bytes from cyc buffer you want to write to the file * @param[in] pWriteBuffer the space alloc by caller,fuction will use this space to load the data,and write to file system, * if this param is NULL, function will alloc space by himself * @return T_S32 * @retval return >=0 the size of bytes write to file, < 0 failed */ static T_S32 WriteToFs( T_pVOID pthis, T_S32 fd, T_S32 iSize ) { CCycBuffer *this = ( CCycBuffer * )pthis; CycBuffer_handle * handle = (CycBuffer_handle *)this->handle; T_CHR * pBuffer = NULL; T_S32 iLineSize = 0, iLeavings = 0; Condition_Lock( handle->mWriteDataCon ); //need to flash all data if ( -1 == iSize ) { iSize = handle->mUseSize; } pBuffer = PopSingle( pthis, iSize ); if ( pBuffer == NULL ) { ResumeForceQuitState( pthis ); Condition_Unlock( handle->mWriteDataCon ); delay_loop( 0, 10000 ); // 10ms return 0; } iLeavings = iSize; while( iLeavings > 0 ) { iLineSize = ( handle->mCycBuffer + handle->mBufferSize ) - pBuffer; if ( iLineSize == 0 ) { pBuffer = handle->mCycBuffer; continue; } else if ( iLineSize > iLeavings ) { iLineSize = iLeavings; } if ( WriteComplete( fd, pBuffer, iLineSize ) < 0 ) { Condition_Unlock( handle->mWriteDataCon ); loge( "WriteToFs::WriteComplete error!\n" ); return -1; } pBuffer += iLineSize; iLeavings -= iLineSize; } Condition_Lock( handle->mDataCon ); handle->mRead = pBuffer; handle->mUseSize -= iSize; handle->mPopComplete = AK_TRUE; Condition_Unlock( handle->mDataCon ); Condition_Unlock( handle->mWriteDataCon ); //logi( "pop signal send!\n" ); Condition_Signal( &(handle->mDataCon) ); return iSize; }
/* ------------------------------------------------------------------- * this function releases all non-terminating threads from the list * of active threads, so that when all terminating threads quit * the joinall will complete. This is called on a Ctrl-C input. It is * also used by the -P usage on the server side * ------------------------------------------------------------------- */ int thread_release_nonterm( int interrupt ) { Condition_Lock( thread_sNum_cond ); thread_sNum -= nonterminating_num; if ( thread_sNum > 1 && nonterminating_num > 0 && interrupt != 0 ) { fprintf( stderr,"%s", wait_server_threads ); } nonterminating_num = 0; Condition_Signal( &thread_sNum_cond ); Condition_Unlock( thread_sNum_cond ); return thread_sNum; }
/* * ReportSettings will generate a summary report for * settings being used with Listeners or Clients */ void ReportSettings( thread_Settings *agent ) { if ( isSettingsReport( agent ) ) { /* * Create in one big chunk */ ReportHeader *reporthdr = malloc( sizeof(ReportHeader) ); if ( reporthdr != NULL ) { ReporterData *data = &reporthdr->report; data->info.transferID = agent->mSock; data->info.groupID = -1; reporthdr->agentindex = -1; reporthdr->reporterindex = -1; data->mHost = agent->mHost; data->mLocalhost = agent->mLocalhost; data->mode = agent->mReportMode; data->type = SETTINGS_REPORT; data->mBufLen = agent->mBufLen; data->mMSS = agent->mMSS; data->mTCPWin = agent->mTCPWin; data->flags = agent->flags; data->mThreadMode = agent->mThreadMode; data->mPort = agent->mPort; data->info.mFormat = agent->mFormat; data->info.mTTL = agent->mTTL; data->connection.peer = agent->peer; data->connection.size_peer = agent->size_peer; data->connection.local = agent->local; data->connection.size_local = agent->size_local; data->mUDPRate = agent->mUDPRate; data->mUDPRateUnits = agent->mUDPRateUnits; #ifdef HAVE_THREAD /* * Update the ReportRoot to include this report. */ Condition_Lock( ReportCond ); reporthdr->next = ReportRoot; ReportRoot = reporthdr; Condition_Signal( &ReportCond ); Condition_Unlock( ReportCond ); #else /* * Process the report in this thread */ reporthdr->next = NULL; process_report ( reporthdr ); #endif } else { FAIL(1, "Out of Memory!!\n", agent); } } }
/* * ReportPacket is called by a transfer agent to record * the arrival or departure of a "packet" (for TCP it * will actually represent many packets). This needs to * be as simple and fast as possible as it gets called for * every "packet". */ void ReportPacket( ReportHeader* agent, ReportStruct *packet ) { if ( agent != NULL ) { int index = agent->reporterindex; /* * First find the appropriate place to put the information */ if ( agent->agentindex == NUM_REPORT_STRUCTS ) { // Just need to make sure that reporter is not on the first // item while ( index == 0 ) { Condition_Signal( &ReportCond ); Condition_Lock( ReportCond ); Condition_Wait( &ReportDoneCond ); Condition_Unlock( ReportCond ); index = agent->reporterindex; } agent->agentindex = 0; } // Need to make sure that reporter is not about to be "lapped" while ( index - 1 == agent->agentindex ) { Condition_Signal( &ReportCond ); Condition_Lock( ReportCond ); Condition_Wait( &ReportDoneCond ); Condition_Unlock( ReportCond ); index = agent->reporterindex; } // Put the information there memcpy( agent->data + agent->agentindex, packet, sizeof(ReportStruct) ); // Updating agentindex MUST be the last thing done agent->agentindex++; #ifndef HAVE_THREAD /* * Process the report in this thread */ process_report ( agent ); #endif } }
/* ------------------------------------------------------------------- * this function releases all non-terminating threads from the list * of active threads, so that when all terminating threads quit * the joinall will complete. This is called on a Ctrl-C input. It is * also used by the -P usage on the server side * ------------------------------------------------------------------- */ int thread_release_nonterm( int interrupt ) { Condition_Lock( thread_sNum_cond ); IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Releasing all non-terminating threads.\r\n" ) ); thread_sNum -= nonterminating_num; if ( thread_sNum > 1 && nonterminating_num > 0 && interrupt != 0 ) { fprintf( stderr, "%s", wait_server_threads ); } nonterminating_num = 0; IPERF_DEBUGF( CONDITION_DEBUG | IPERF_DBG_TRACE, ( "Signaling thread_sNum_cond condition.\r\n" ) ); Condition_Signal( &thread_sNum_cond ); Condition_Unlock( thread_sNum_cond ); return thread_sNum; } // end thread_release_nonterm
/* ------------------------------------------------------------------- * Stop the specified object's thread execution (if any) immediately. * Decrements thread count and resets the thread ID. * ------------------------------------------------------------------- */ void thread_stop( struct thread_Settings* thread ) { #ifdef HAVE_THREAD // Make sure we have been started if ( ! thread_equalid( thread->mTID, thread_zeroid() ) ) { // decrement thread count Condition_Lock( thread_sNum_cond ); IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Decrementing thread count from %d to %d.\r\n", thread_sNum, (thread_sNum - 1) ) ); thread_sNum--; IPERF_DEBUGF( CONDITION_DEBUG | IPERF_DBG_TRACE, ( "Signaling thread_sNum_cond condition.\r\n" ) ); Condition_Signal( &thread_sNum_cond ); Condition_Unlock( thread_sNum_cond ); // use exit() if called from within this thread // use cancel() if called from a different thread if ( thread_equalid( thread_getid(), thread->mTID ) ) { // Destroy the object Settings_Destroy( thread ); // Exit #if defined( HAVE_POSIX_THREAD ) IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Exiting %s thread.\r\n", thread_names[thread->mThreadMode] ) ); pthread_exit( NULL ); #elif defined( HAVE_WIN32_THREAD ) IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Exiting %s thread.\r\n", thread_names[thread->mThreadMode] ) ); CloseHandle( thread->mHandle ); ExitThread( 0 ); #endif /* HAVE_POSIX_THREAD */ } else { // Cancel #if defined( HAVE_POSIX_THREAD ) // Cray J90 doesn't have pthread_cancel; Iperf works okay without #ifdef HAVE_PTHREAD_CANCEL IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Canceling %s thread.\r\n", thread_names[thread->mThreadMode] ) ); pthread_cancel( thread->mTID ); #endif /* HAVE_PTHREAD_CANCEL */ #elif defined(HAVE_WIN32_THREAD) // this is a somewhat dangerous function; it's not // suggested to Stop() threads a lot. IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Terminating %s thread.\r\n", thread_names[thread->mThreadMode] ) ); TerminateThread( thread->mHandle, 0 ); #endif /* HAVE_POSIX_THREAD */ // Destroy the object only after killing the thread Settings_Destroy( thread ); } } #endif /* HAVE_THREAD */ } // end thread_stop
/* ------------------------------------------------------------------- * Stop the specified object's thread execution (if any) immediately. * Decrements thread count and resets the thread ID. * ------------------------------------------------------------------- */ void thread_stop( struct thread_Settings* thread ) { #ifdef HAVE_THREAD // Make sure we have been started if ( ! thread_equalid( thread->mTID, thread_zeroid() ) ) { // decrement thread count Condition_Lock( thread_sNum_cond ); thread_sNum--; Condition_Signal( &thread_sNum_cond ); Condition_Unlock( thread_sNum_cond ); // use exit() if called from within this thread // use cancel() if called from a different thread if ( thread_equalid( thread_getid(), thread->mTID ) ) { // Destroy the object Settings_Destroy( thread ); // Exit #if defined( HAVE_POSIX_THREAD ) pthread_exit( NULL ); #else // Win32 CloseHandle( thread->mHandle ); ExitThread( 0 ); #endif } else { // Cancel #if defined( HAVE_POSIX_THREAD ) // Cray J90 doesn't have pthread_cancel; Iperf works okay without #ifdef HAVE_PTHREAD_CANCEL pthread_cancel( thread->mTID ); #endif #else // Win32 // this is a somewhat dangerous function; it's not // suggested to Stop() threads a lot. TerminateThread( thread->mHandle, 0 ); #endif // Destroy the object only after killing the thread Settings_Destroy( thread ); } } #endif } // end Stop
/* ------------------------------------------------------------------- * unset a thread from being ignorable, so joinall will wait on it * this simply increments the thread count that joinall uses. * This is utilized by the reporter thread which knows when it * is ok to quit (aka no pending reports). * ------------------------------------------------------------------- */ void thread_unsetignore( void ) { Condition_Lock( thread_sNum_cond ); thread_sNum++; Condition_Signal( &thread_sNum_cond ); Condition_Unlock( thread_sNum_cond ); }
/* ------------------------------------------------------------------- * set a thread to be ignorable, so joinall won't wait on it * this simply decrements the thread count that joinall uses. * This is utilized by the reporter thread which knows when it * is ok to quit (aka no pending reports). * ------------------------------------------------------------------- */ void thread_setignore( ) { Condition_Lock( thread_sNum_cond ); thread_sNum--; Condition_Signal( &thread_sNum_cond ); Condition_Unlock( thread_sNum_cond ); }
DWORD WINAPI #else void* #endif thread_run_wrapper( void* paramPtr ) { struct thread_Settings* thread = (struct thread_Settings*) paramPtr; // which type of object are we switch ( thread->mThreadMode ) { case kMode_Server: { /* Spawn a Server thread with these settings */ server_spawn( thread ); } break; case kMode_Client: { /* Spawn a Client thread with these settings */ client_spawn( thread ); } break; case kMode_Reporter: { /* Spawn a Reporter thread with these settings */ reporter_spawn( thread ); } break; case kMode_Listener: { // Increment the non-terminating thread count thread_register_nonterm(); /* Spawn a Listener thread with these settings */ listener_spawn( thread ); // Decrement the non-terminating thread count thread_unregister_nonterm(); } break; default: { FAIL(1, "Unknown Thread Type!\n", thread); } break; } #ifdef HAVE_POSIX_THREAD // detach Thread. If someone already joined it will not do anything // If noone has then it will free resources upon return from this // function (Run_Wrapper) pthread_detach(thread->mTID); #endif // decrement thread count and send condition signal Condition_Lock( thread_sNum_cond ); thread_sNum--; Condition_Signal( &thread_sNum_cond ); Condition_Unlock( thread_sNum_cond ); // Check if we need to start up a thread after executing this one if ( thread->runNext != NULL ) { thread_start( thread->runNext ); } // Destroy this thread object Settings_Destroy( thread ); return 0; } // end run_wrapper
DWORD WINAPI #else void* #endif /* HAVE_WIN32_THREAD */ thread_run_wrapper( void* paramPtr ) { struct thread_Settings* thread = (struct thread_Settings*) paramPtr; IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE | IPERF_DBG_STATE, ( "%s thread is now running. ID is %lu.\r\n", thread_names[thread->mThreadMode], (long unsigned) thread_getid() ) ); // which type of object are we switch ( thread->mThreadMode ) { case kMode_Server: { /* Spawn a Server thread with these settings */ server_spawn( thread ); } break; case kMode_Client: { /* Spawn a Client thread with these settings */ client_spawn( thread ); } break; case kMode_Reporter: { /* Spawn a Reporter thread with these settings */ reporter_spawn( thread ); } break; case kMode_Listener: { // Increment the non-terminating thread count thread_register_nonterm(); /* Spawn a Listener thread with these settings */ listener_spawn( thread ); // Decrement the non-terminating thread count thread_unregister_nonterm(); } break; default: { FAIL(1, ( "Unknown Thread Type!\r\n" ), thread); } break; } #ifdef HAVE_POSIX_THREAD // detach Thread. If someone already joined it will not do anything // If noone has then it will free resources upon return from this // function (Run_Wrapper) IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Detaching %s thread.\r\n", thread_names[thread->mThreadMode] ) ); pthread_detach(thread->mTID); #endif /* HAVE_POSIX_THREAD */ // decrement thread count and send condition signal Condition_Lock( thread_sNum_cond ); IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Decrementing thread count from %d to %d.\r\n", thread_sNum, (thread_sNum - 1) ) ); thread_sNum--; IPERF_DEBUGF( CONDITION_DEBUG | IPERF_DBG_TRACE, ( "Signaling thread_sNum_cond condition.\r\n" ) ); Condition_Signal( &thread_sNum_cond ); Condition_Unlock( thread_sNum_cond ); // Check if we need to start up a thread after executing this one if ( thread->runNext != NULL ) { thread_start( thread->runNext ); } // Destroy this thread object Settings_Destroy( thread ); return 0; } // end thread_run_wrapper
static T_S32 PushSingle( T_pVOID pthis, T_CHR * pBuffer, T_S32 iSize ) { CCycBuffer *this = ( CCycBuffer * )pthis; CycBuffer_handle * handle = (CycBuffer_handle *)this->handle; T_S32 iLeavings = 0; T_S32 iWriteSize = 0; T_S32 iLineSize = 0; T_CHR * mTempWrite = NULL; if ( iSize > handle->mBufferSize ) { loge( "CCycBuffer::Push() can't not push %d data to buffer, %d > %d(buffer size)", iSize, iSize, handle->mBufferSize ); return -1; } //the cyc buffer is full. wait for pop Condition_Lock( handle->mDataCon ); handle->mPushComplete = AK_FALSE; while ( ( ( handle->mBufferSize - handle->mUseSize ) < iSize ) && ( !(handle->mForceQuit) ) ) { //Condition_Unlock( handle->mDataCon ); logi( "PushSingle buffer full! %d\n", handle->mBufferSize ); Condition_Wait( &(handle->mDataCon) ); //logi( "wake up from pop signed!\n" ); //Condition_Lock( handle->mDataCon ); } if ( handle->mForceQuit ) { handle->mPushComplete = AK_TRUE; Condition_Unlock( handle->mDataCon ); return 0; } assert( ( pBuffer != NULL ) && ( handle->mCycBuffer != NULL ) && ( iSize > 0 ) ); assert( ( ( handle->mRead >= handle->mCycBuffer ) && ( handle->mRead < (handle->mCycBuffer + handle->mBufferSize) ) ) ); assert( ( ( handle->mWrite >= handle->mCycBuffer ) && ( handle->mWrite < (handle->mCycBuffer + handle->mBufferSize) ) ) ); mTempWrite = handle->mWrite; Condition_Unlock( handle->mDataCon ); iLeavings = iSize; while ( iLeavings > 0 ) { iLineSize = ( handle->mCycBuffer + handle->mBufferSize ) - mTempWrite; iWriteSize = ( iLineSize > iLeavings )?iLeavings:iLineSize; memcpy( mTempWrite, pBuffer, iWriteSize ); if ( iWriteSize == iLineSize ) mTempWrite = handle->mCycBuffer; else mTempWrite += iWriteSize; pBuffer += iWriteSize; iLeavings -= iWriteSize; } Condition_Lock( handle->mDataCon ); handle->mWrite = mTempWrite; handle->mUseSize = ( ( handle->mUseSize + iSize ) > handle->mBufferSize )?handle->mBufferSize:( handle->mUseSize + iSize ); if ( handle->mUseSize == handle->mBufferSize ) handle->mRead = handle->mWrite; handle->mPushComplete = AK_TRUE; Condition_Unlock( handle->mDataCon ); Condition_Signal( &(handle->mDataCon) ); return iSize; }
/** * @brief pop data from cyc buffer * * @author hankejia * @date 2012-07-05 * @param[in] pthis the pointer point to the CCycBuffer. * @param[out] pBuffer the memory to saved the data * @param[in] iSize how many bytes you want to pop from cyc buffer * @return T_S32 * @retval return >=0 the size of bytes pop from cyc buffer, < 0 failed */ static T_S32 Pop( T_pVOID pthis, char * pBuffer, T_S32 iSize ) { CCycBuffer *this = ( CCycBuffer * )pthis; CycBuffer_handle * handle = (CycBuffer_handle *)this->handle; T_S32 iGetSize= 0; T_S32 iLeavings = 0; T_S32 iReadSize = 0; T_S32 iLineSize = 0; if ( iSize > handle->mBufferSize ) { loge( "CCycBuffer::Pop() can't not Pop %d data from buffer, %d > %d(buffer size)", iSize, iSize, handle->mBufferSize ); return -1; } //the cyc buffer is empty, wait for push Condition_Lock( handle->mDataCon ); handle->mPopComplete = AK_FALSE; while ( ( handle->mUseSize < iSize ) && ( !(handle->mForceQuit) ) ) { //Condition_Unlock( handle->mDataCon ); //logi( "buffer empty!\n" ); Condition_Wait( &(handle->mDataCon) ); //logi( "wake up from push signed!\n" ); //Condition_Lock( handle->mDataCon ); } if ( handle->mForceQuit ) { handle->mPopComplete = AK_TRUE; Condition_Unlock( handle->mDataCon ); return 0; } assert( ( pBuffer != NULL ) && ( handle->mCycBuffer != NULL ) && ( iSize > 0 ) ); assert( ( ( handle->mRead >= handle->mCycBuffer ) && ( handle->mRead < (handle->mCycBuffer + handle->mBufferSize) ) ) ); assert( ( ( handle->mWrite >= handle->mCycBuffer ) && ( handle->mWrite < (handle->mCycBuffer + handle->mBufferSize) ) ) ); iGetSize = ( (handle->mUseSize) > iSize )?iSize:(handle->mUseSize); iLeavings = iGetSize; while ( iLeavings > 0 ) { iLineSize = ( handle->mCycBuffer + handle->mBufferSize ) - handle->mRead; iReadSize = ( iLineSize > iLeavings )?iLeavings:iLineSize; memcpy( pBuffer, handle->mRead, iReadSize ); if ( iReadSize == iLineSize ) handle->mRead = handle->mCycBuffer; else handle->mRead += iReadSize; pBuffer += iReadSize; iLeavings -= iReadSize; } handle->mUseSize -= iGetSize; handle->mPopComplete = AK_TRUE; Condition_Unlock( handle->mDataCon ); //logi( "pop signal send!\n" ); Condition_Signal( &(handle->mDataCon) ); return iGetSize; }
/* * InitReport is called by a transfer agent (client or * server) to setup the needed structures to communicate * traffic. */ ReportHeader* InitReport( thread_Settings *agent ) { ReportHeader *reporthdr = NULL; ReporterData *data = NULL; if ( isDataReport( agent ) ) { /* * Create in one big chunk */ reporthdr = malloc( sizeof(ReportHeader) + NUM_REPORT_STRUCTS * sizeof(ReportStruct) ); if ( reporthdr != NULL ) { // Only need to make sure the headers are clean memset( reporthdr, 0, sizeof(ReportHeader)); reporthdr->data = (ReportStruct*)(reporthdr+1); reporthdr->multireport = agent->multihdr; data = &reporthdr->report; reporthdr->reporterindex = NUM_REPORT_STRUCTS - 1; data->info.transferID = agent->mSock; data->info.groupID = (agent->multihdr != NULL ? agent->multihdr->groupID : 128); data->type = TRANSFER_REPORT; if ( agent->mInterval != 0.0 ) { struct timeval *interval = &data->intervalTime; interval->tv_sec = (long) agent->mInterval; interval->tv_usec = (long) ((agent->mInterval - interval->tv_sec) * rMillion); } data->mHost = agent->mHost; data->mLocalhost = agent->mLocalhost; data->mBufLen = agent->mBufLen; data->mMSS = agent->mMSS; data->mTCPWin = agent->mTCPWin; data->flags = agent->flags; data->mThreadMode = agent->mThreadMode; data->mode = agent->mReportMode; data->info.mFormat = agent->mFormat; data->info.mTTL = agent->mTTL; if (data->mThreadMode == kMode_Server) data->info.tcp.read.binsize = data->mBufLen / 8; if ( isUDP( agent ) ) { gettimeofday(&data->IPGstart, NULL); reporthdr->report.info.mUDP = (char)agent->mThreadMode; } else { reporthdr->report.info.mTCP = (char)agent->mThreadMode; } if ( isEnhanced( agent ) ) { data->info.mEnhanced = 1; } else { data->info.mEnhanced = 0; } } else { FAIL(1, "Out of Memory!!\n", agent); } } if ( isConnectionReport( agent ) ) { if ( reporthdr == NULL ) { /* * Create in one big chunk */ reporthdr = malloc( sizeof(ReportHeader) ); if ( reporthdr != NULL ) { // Only need to make sure the headers are clean memset( reporthdr, 0, sizeof(ReportHeader)); data = &reporthdr->report; data->info.transferID = agent->mSock; data->info.groupID = 128; } else { FAIL(1, "Out of Memory!!\n", agent); } } if ( reporthdr != NULL ) { data->type |= CONNECTION_REPORT; data->connection.peer = agent->peer; data->connection.size_peer = agent->size_peer; data->connection.local = agent->local; data->connection.size_local = agent->size_local; } else { FAIL(1, "Out of Memory!!\n", agent); } } if ( isConnectionReport( agent ) || isDataReport( agent ) ) { #ifdef HAVE_THREAD /* * Update the ReportRoot to include this report. */ if ( reporthdr->report.mThreadMode == kMode_Client && reporthdr->multireport != NULL ) { // syncronize watches on my mark...... BarrierClient( reporthdr ); } else { if ( reporthdr->multireport != NULL && isMultipleReport( agent )) { reporthdr->multireport->threads++; if ( reporthdr->multireport->report->startTime.tv_sec == 0 ) { gettimeofday( &(reporthdr->multireport->report->startTime), NULL ); } reporthdr->report.startTime = reporthdr->multireport->report->startTime; } else { // set start time gettimeofday( &(reporthdr->report.startTime), NULL ); } reporthdr->report.nextTime = reporthdr->report.startTime; TimeAdd( reporthdr->report.nextTime, reporthdr->report.intervalTime ); } Condition_Lock( ReportCond ); reporthdr->next = ReportRoot; ReportRoot = reporthdr; Condition_Signal( &ReportCond ); Condition_Unlock( ReportCond ); #else // set start time gettimeofday( &(reporthdr->report.startTime), NULL ); /* * Process the report in this thread */ reporthdr->next = NULL; process_report ( reporthdr ); #endif } if ( !isDataReport( agent ) ) { reporthdr = NULL; } return reporthdr; }