Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
//====== Copyright �, Valve Corporation, All rights reserved. =======
// GCSqlWriteQueue.h
//
// A utility class that allows for templating based upon a SQL schema type, and then
// queuing up a number of those records to be written to SQL. This will buffer them until
// either a certain number have been queued or a period of time has elapsed, at which point
// it will flush them to SQL in a single transaction.
//
//===================================================================
#ifndef GCSQLWRITEQUEUE_H
#define GCSQLWRITEQUEUE_H
#include "scheduledfunction.h"
namespace GCSDK {
class CGCBase;
template < typename TSqlClass > class CGCSQLWriteQueue { public:
CGCSQLWriteQueue( uint32 nMaxToCache, uint32 nMaxMSToWrite ) : m_nMaxToCache( nMaxToCache ), m_nMaxMSToWrite( nMaxMSToWrite ) { m_QueuedRecords.EnsureCapacity( nMaxToCache ); } //called to queue the record for writing, which will occur either when the maximum time between writebacks has occurred, or
//when the cache has filled up
void QueueRecord( const TSqlClass& sch ) { m_QueuedRecords.AddToTail( sch );
//now handle either dispatching, or scheduling a timeout dispatch
if( ( uint32 )m_QueuedRecords.Count() >= m_nMaxToCache ) { //unschedule first. This way if while we are yielded, we add another entry, it can schedule a new timeout
m_TimeCommit.Cancel(); CreateJobToCommitSQL(); } else if( !m_TimeCommit.BIsScheduled() ) { m_TimeCommit.Schedule( this, &CGCSQLWriteQueue< TSqlClass >::CreateJobToCommitSQL, m_nMaxMSToWrite ); } }
//a yielding version of the above function
void YieldingQueueRecord( const TSqlClass& sch ) { m_QueuedRecords.AddToTail( sch );
//now handle either dispatching, or scheduling a timeout dispatch
if( ( uint32 )m_QueuedRecords.Count() >= m_nMaxToCache ) { //unschedule first. This way if while we are yielded, we add another entry, it can schedule a new timeout
m_TimeCommit.Cancel(); YieldingFlushQueuedViewsToSQL(); } else if( !m_TimeCommit.BIsScheduled() ) { m_TimeCommit.Schedule( this, &CGCSQLWriteQueue< TSqlClass >::CreateJobToCommitSQL, m_nMaxMSToWrite ); } } private:
//called internally when we kick off a job after N amount of time has expired
template < typename TSqlClass > class CTimeExpiredCommitJob : public CGCJob { public: CTimeExpiredCommitJob( CGCBase* pGC, CGCSQLWriteQueue< TSqlClass >* pClass ) : CGCJob( pGC ), m_pClass( pClass ) {} virtual bool BYieldingRunJob( void* pvStartParm ) { m_pClass->YieldingFlushQueuedViewsToSQL(); return true; } private: CGCSQLWriteQueue< TSqlClass >* m_pClass; };
//the function called when time expires to start a job and commit the requests to SQL
void CreateJobToCommitSQL() { //kick off our job, which just calls the flush
CGCJob* pJob = new CTimeExpiredCommitJob< TSqlClass >( GGCBase(), this ); pJob->StartJobDelayed( NULL ); }
//handles committing the list of queued views to SQL
void YieldingFlushQueuedViewsToSQL() { if( m_QueuedRecords.Count() == 0 ) return;
//move the contents into a local vector so we don't have any conflicts of global state
CUtlVector< TSqlClass > localQueue; localQueue.Swap( m_QueuedRecords ); //prepare the queue for the next batch (so we don't have intermediate resizes)
m_QueuedRecords.EnsureCapacity( m_nMaxToCache );
// start a transaction for all this work
CSQLAccess sqlAccess; sqlAccess.BBeginTransaction( "CGCWatchDownloadedReplayJob::FlushQueuedViewsToSQL" );
FOR_EACH_VEC( localQueue, nCurrView ) { sqlAccess.BYieldingInsertRecord( &localQueue[ nCurrView ] ); }
sqlAccess.BCommitTransaction(); }
//the records that we have queued
CUtlVector< TSqlClass > m_QueuedRecords; //schedules a write back to ensure we commit at least every N seconds
CScheduledFunction< CGCSQLWriteQueue< TSqlClass > > m_TimeCommit; //maximum number of seconds between commits
uint32 m_nMaxMSToWrite; //maximum number of records to buffer before writing back
uint32 m_nMaxToCache; };
} //namespace GCSDK
#endif
|