예제 #1
0
/*--------------------------------------------------------------------------------------
 * Purpose: Write a new item into the queue
 * Input: queue to write item and the item itself
 * Output: returns 0, exits on fatal error if write fails 
 * He Yan @ June 15, 2008
 * -------------------------------------------------------------------------------------*/
int 
writeQueue( QueueWriter writer, void *item )
{
	int i;

	// lock the queue	
	Queue q = writer->queue;
	if ( pthread_mutex_lock( &q->queueLock ) )
		log_fatal( "lockQueue: failed");

	// if the queue is full, move the positions of slowest readers to the tail
	if (( q->tail - q->head) >= QUEUE_MAX_ITEMS )
	{		
#ifdef DEBUG
		log_warning("queue %s is full, head=%ld, tail=%ld; adjusting slowest readers", q->name, q->head, q->tail);
#endif		
		for ( i = 0; i < MAX_QUEUE_READERS; i++ )
		{
#ifdef DEBUG
			debug(__FUNCTION__, "queue %s's head is %ld", q->name, q->head);
			if (q->nextItem[i] >= 0)
			{
				debug(__FUNCTION__, "queue %s's reader %d's next item is %ld", q->name, i, q->nextItem[i]);
			}
#endif
			// if this reader is the slowest one, adjust it
			if ( q->head == q->nextItem[i] )
			{
				if(q->newPacingEnable == FALSE)
					adjustSlowestQueueReader(q, i);
				else
				{
					long j = q->nextItem[i] %  QUEUE_MAX_ITEMS;
                			q->items[j].count--;
                			if ( q->items[j].count == 0 )
                			{    
                        			free( q->items[j].messagBuf );
                        			q->items[j].messagBuf = NULL;
                        			q->head++;
                			}
					q->nextItem[i]++;
#ifdef DEBUG
					log_warning("Move the slowest client 1 pos forward");				
#endif	
				}
			}
		}
	}

	// should not happen, fatal error if it happens
	if (( q->tail - q->head ) >= QUEUE_MAX_ITEMS ) 
		log_fatal("%s queue is still FULL after adjusting readers", q->name);
		// not reached

	// old pacing: update pacing limit and reset readcout and writecount if needed
	// new pacing: update write count moveing average
	updateInterval(q);
	
	// only for the new pacing algorithm  
	if(q->newPacingEnable == TRUE)
	{
		if ( ( (float)(q->tail - q->head)/(float)QUEUE_MAX_ITEMS ) >=  QueueConfig.pacingOnThresh)
		{
#ifdef DEBUG		
			log_warning("queue %s is over pacing threshold, head=%ld, tail=%ld; adjusting slowest readers", q->name, QueueConfig.pacingOnThresh, q->head, q->tail);
#endif			
  			for ( i = 0; i < MAX_QUEUE_READERS; i++ )
                        {
        			#ifdef DEBUG
                                debug(__FUNCTION__, "queue %s's head is %ld", q->name, q->head);
                                if (q->nextItem[i] >= 0)
                                {
                                        debug(__FUNCTION__, "queue %s's reader %d's next item is %ld", q->name, i, q->nextItem[i]);
                                }
        			#endif
                                // if this reader is the slowest one, adjust it
				if ( q->head == q->nextItem[i] )
                                {                           
					adjustSlowestQueueReader(q, i);
         			}
			}
		}
	
	}	

	// only for the old pacing algorithm, otherwise skip this step	
	if(q->newPacingEnable == FALSE)
	{
		// check if need to stop pacing
		if( checkPacingStop(q) )
			log_fatal("%s queue error stopping pacing rules", q->name);	
	}	

	// write the data to the next spot in the queue
	q->writeCount++;
	if(  q->readercount > 0 )
	{
		q->writeCounts[writer->index]++;
		long l = q->tail % QUEUE_MAX_ITEMS;
		q->items[l].count = q->readercount;
		q->items[l].messagBuf = (void *)item;
		q->tail++;
		if ( (q->tail - q->head) > q->logMaxItems)
		q->logMaxItems = q->tail - q->head;
	}
	else
		free( item );
	
        // only if use the old pacing, otherwise skip this step 
        if(q->newPacingEnable == FALSE)
	{
		// apply pacing rules to the current writer
		if ( applyPacing(q, writer->index) )
			log_fatal("%s queue error applying pacing rules", q->name);		
			// not reached
	}

	// unlock the queue
	if ( pthread_mutex_unlock( &q->queueLock ) )
		log_fatal( "unlockQueue: failed");

	// notify blocked readers new data has appeared
	if(  q->readercount > 0 )
        pthread_cond_broadcast( &q->queueCond );

#ifdef DEBUG
	debug(__FUNCTION__, "Writer %d (%d writes in last interval(%d)) wrote to queue %s;  tail/head: %ld/%ld ",
		writer->index, q->writeCounts[writer->index], QueueConfig.pacingInterval, q->name, q->tail, q->head);
#endif	

	/* log a message if we are past the log interval */
	int now = time( NULL );
	if ( now > q->lastLogTime + QueueConfig.logInterval)
	{
		q->lastLogTime = now;
		log_msg("Queue %s status: tail=%ld head=%ld", q->name, q->tail, q->head); 
		log_msg("Queue %s usage: currentItems=%ld, usedBytes=%ld, peakItems=%ld, allowedItems=%ld", 
		  q->name, getItemsUsed(q->name), getBytesUsed(q->name), q->logMaxItems, QUEUE_MAX_ITEMS); 
		log_msg("Queue %s writers: current=%d, peak=%d, allowed=%d", 
		  q->name, getWriterCount(q->name), q->logMaxWriters, MAX_QUEUE_WRITERS); 
		log_msg("Queue %s readers: current=%d, peak=%d, allowed=%d", 
		  q->name, getReaderCount(q->name), q->logMaxReaders, MAX_QUEUE_READERS); 
	}

	return(0); 
}
예제 #2
0
/*--------------------------------------------------------------------------------------
 * Purpose: Write a new item into the queue
 * Input: queue to write item and the item itself
 * Output: returns 0 on success, 1 on queue_full, but success, -1 on failure
 * He Yan @ June 15, 2008
 * -------------------------------------------------------------------------------------*/
int 
writeQueue( QueueWriter writer, void *item )
{
  Queue q = writer->queue;

  // lock the queue	
  if ( pthread_mutex_lock( &q->queueLock ) ){
    log_warning( "lockQueue: failed");
    return -1;
  }

  int q_full = pacing_write_post_lock(q);

  // write the data to the next spot in the queue
  q->writeCount++;
  if(  q->readercount > 0 ){
    q->writeCounts[writer->index]++;
    long l = q->tail % QUEUE_MAX_ITEMS;
    q->items[l].count = q->readercount;
    q->items[l].messagBuf = (void *)item;
    q->tail++;
    if ( (q->tail - q->head) > q->logMaxItems){
      q->logMaxItems = q->tail - q->head;
    }
  } else{
    free( item );
  }

  pacing_write_post_write(q,writer->index);

  // unlock the queue
  if ( pthread_mutex_unlock( &q->queueLock ) ){
    log_warning( "unlockQueue: failed");
    return -1;
  }

  // notify blocked readers new data has appeared
  if(  q->readercount > 0 ){
    pthread_cond_broadcast( q->queueGroupCond );
  }

#ifdef DEBUG
  debug(__FUNCTION__, "Writer %d (%d writes in last interval(%d)) wrote to queue %s;  tail/head: %ld/%ld ",
        writer->index, q->writeCounts[writer->index], QueueConfig.pacingInterval, q->name, q->tail, q->head);
#endif	

  /* log a message if we are past the log interval */
  int now = time( NULL );
  if ( now > q->lastLogTime + QueueConfig.logInterval) {
    q->lastLogTime = now;
    log_msg("Queue %s status: tail=%ld head=%ld", q->name, q->tail, q->head); 
    log_msg("Queue %s usage: currentItems=%ld, usedBytes=%ld, peakItems=%ld, allowedItems=%ld", 
            q->name, getItemsUsed(q->name), getBytesUsed(q->name), q->logMaxItems, QUEUE_MAX_ITEMS); 
    log_msg("Queue %s writers: current=%d, peak=%d, allowed=%d", 
            q->name, getWriterCount(q->name), q->logMaxWriters, MAX_QUEUE_WRITERS); 
    log_msg("Queue %s readers: current=%d, peak=%d, allowed=%d", 
            q->name, getReaderCount(q->name), q->logMaxReaders, MAX_QUEUE_READERS); 
  }

  return q_full; 
}