Пример #1
0
void AsyncLogging::threadFunc()
{
    assert(running_ == true);
    latch_.countDown();
    LogFile output(basename_, rollSize_, false);
    BufferPtr newBuffer1(new Buffer);
    BufferPtr newBuffer2(new Buffer);
    newBuffer1->bzero();
    newBuffer2->bzero();
    BufferVector buffersToWrite;
    buffersToWrite.reserve(16);
    while(running_)
    {
        assert(newBuffer1 && newBuffer1->length() == 0);
        assert(newBuffer2 && newBuffer2->length() == 0);
        assert(buffersToWrite.empty());

        {
            dbdky::MutexLockGuard lock(mutex_);
            if (buffers_.empty())
            {
                cond_.waitForSeconds(flushInterval_);
            }

            buffers_.push_back(currentBuffer_.release());
            currentBuffer_ = boost::ptr_container::move(newBuffer1);
            buffersToWrite.swap(buffers_);
      
            if (!nextBuffer_)
            {
                nextBuffer_ = boost::ptr_container::move(newBuffer2);
            }
        }

        assert(!buffersToWrite.empty());

        if (buffersToWrite.size() > 25)
        {
            char buf[256];
            snprintf(buf, sizeof buf, "Dropped log messages at %s, %zd larger buffers\n", Timestamp::now().toFormattedString().c_str(),
		buffersToWrite.size() - 2);
	    fputs(buf, stderr);
 	    output.append(buf, static_cast<int>(strlen(buf)));
            buffersToWrite.erase(buffersToWrite.begin() + 2, buffersToWrite.end());
        }

	for (size_t i = 0; i < buffersToWrite.size(); i++)
        {
            output.append(buffersToWrite[i].data(), buffersToWrite[i].length());
        }

        if (buffersToWrite.size() > 2)
        {
            buffersToWrite.resize(2);
        }

        if (!newBuffer1)
        {
            assert(!buffersToWrite.empty());
            newBuffer1 = buffersToWrite.pop_back();
 	    newBuffer1->reset();
        }

        if (!newBuffer2)
        {
            assert(!buffersToWrite.empty());
            newBuffer2 = buffersToWrite.pop_back();
	    newBuffer2->reset();
        }

        buffersToWrite.clear();
        output.flush();
    }

    output.flush();
}
Пример #2
0
void AsyncLogging::threadFunc()
{
	assert(running_ == true);
	latch_.countDown();

	LogFile output(basename_, rollSize_, false); //Important 这里的传入的threadsafe为false,为什么,因为异步本身就保证了线程安全
	BufferPtr newBuffer1(new Buffer);
	BufferPtr newBuffer2(new Buffer);

	newBuffer1->bzeroinit();
	newBuffer2->bzeroinit();

	BufferVector buffersToWrite;
	buffersToWrite.reserve(16);

	while (running_)
	{

		{
			lock_guard_t lock(mutex_); //用来和生产者互斥
			if (buffers_.empty()) //unsual usage,没有使用while循环
			{
				cond_.wait(flushInterval_ * 1000);//flushInterval_是seconds

			}
			//执行到这里有2个条件:其一是超时,其二是写满了一个或多个buffer
			buffers_.push_back(currentBuffer_.release());//移动,而非复制 ,release类似std::auto_ptr的release,  返回包含指针的地址,并将包含指针设为NUll
			currentBuffer_ = boost::ptr_container::move(newBuffer1);//移动,而非复制
			buffersToWrite.swap(buffers_);//内部指针交换,而非复制 ,交换后,可在临界区外安全地访问buffersToWrite,将其中的日志数据写入文件

			if (!nextBuffer_)//临界区最终干的一件事情是用newBuffer2替换nextBuffer_,这样前端始终有一个备用buffer,nextbuffer_减少前端分配内存的概率
			{
				nextBuffer_ = boost::ptr_container::move(newBuffer2);
			}


		}


		assert(!buffersToWrite.empty());

		if (buffersToWrite.size() > 25)//日志堆积,直接丢掉
		{
			char buf[256];
			snprintf(buf, sizeof buf, "Dropped log messages at %s, %zd larger buffers\n",
				Timestamp::now().toFormattedString().c_str(),
				buffersToWrite.size() - 2);
			fputs(buf, stderr);
			output.append(buf, static_cast<int>(strlen(buf)));

			buffersToWrite.erase(buffersToWrite.begin() + 2, buffersToWrite.end());
		}


		for (size_t i = 0; i < buffersToWrite.size(); i++)
		{
			// FIXME: use unbuffered stdio FILE ? or use ::writev ?

			output.append(buffersToWrite[i].data(), buffersToWrite[i].length());

		}

		if (buffersToWrite.size() > 2)
		{
			// drop non-bzero-ed buffers, avoid trashing
			buffersToWrite.resize(2);
		}

		if (!newBuffer1)
		{
			assert(!buffersToWrite.empty());
			newBuffer1 = buffersToWrite.pop_back();
			newBuffer1->reset(); //将buffer的指针指向头部
		}
		if (!newBuffer2)
		{
			assert(!buffersToWrite.empty());
			newBuffer2 = buffersToWrite.pop_back();
			newBuffer2->reset();
		}


		buffersToWrite.clear();
		
		output.flush();

	}

	output.flush();
}