summaryrefslogtreecommitdiff
path: root/public/gcsdk/gcsqlwritequeue.h
diff options
context:
space:
mode:
Diffstat (limited to 'public/gcsdk/gcsqlwritequeue.h')
-rw-r--r--public/gcsdk/gcsqlwritequeue.h131
1 files changed, 131 insertions, 0 deletions
diff --git a/public/gcsdk/gcsqlwritequeue.h b/public/gcsdk/gcsqlwritequeue.h
new file mode 100644
index 0000000..a8141d4
--- /dev/null
+++ b/public/gcsdk/gcsqlwritequeue.h
@@ -0,0 +1,131 @@
+//====== 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
+