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.

131 lines
4.0 KiB

  1. //====== Copyright �, Valve Corporation, All rights reserved. =======
  2. // GCSqlWriteQueue.h
  3. //
  4. // A utility class that allows for templating based upon a SQL schema type, and then
  5. // queuing up a number of those records to be written to SQL. This will buffer them until
  6. // either a certain number have been queued or a period of time has elapsed, at which point
  7. // it will flush them to SQL in a single transaction.
  8. //
  9. //===================================================================
  10. #ifndef GCSQLWRITEQUEUE_H
  11. #define GCSQLWRITEQUEUE_H
  12. #include "scheduledfunction.h"
  13. namespace GCSDK
  14. {
  15. class CGCBase;
  16. template < typename TSqlClass >
  17. class CGCSQLWriteQueue
  18. {
  19. public:
  20. CGCSQLWriteQueue( uint32 nMaxToCache, uint32 nMaxMSToWrite ) :
  21. m_nMaxToCache( nMaxToCache ),
  22. m_nMaxMSToWrite( nMaxMSToWrite )
  23. {
  24. m_QueuedRecords.EnsureCapacity( nMaxToCache );
  25. }
  26. //called to queue the record for writing, which will occur either when the maximum time between writebacks has occurred, or
  27. //when the cache has filled up
  28. void QueueRecord( const TSqlClass& sch )
  29. {
  30. m_QueuedRecords.AddToTail( sch );
  31. //now handle either dispatching, or scheduling a timeout dispatch
  32. if( ( uint32 )m_QueuedRecords.Count() >= m_nMaxToCache )
  33. {
  34. //unschedule first. This way if while we are yielded, we add another entry, it can schedule a new timeout
  35. m_TimeCommit.Cancel();
  36. CreateJobToCommitSQL();
  37. }
  38. else if( !m_TimeCommit.BIsScheduled() )
  39. {
  40. m_TimeCommit.Schedule( this, &CGCSQLWriteQueue< TSqlClass >::CreateJobToCommitSQL, m_nMaxMSToWrite );
  41. }
  42. }
  43. //a yielding version of the above function
  44. void YieldingQueueRecord( const TSqlClass& sch )
  45. {
  46. m_QueuedRecords.AddToTail( sch );
  47. //now handle either dispatching, or scheduling a timeout dispatch
  48. if( ( uint32 )m_QueuedRecords.Count() >= m_nMaxToCache )
  49. {
  50. //unschedule first. This way if while we are yielded, we add another entry, it can schedule a new timeout
  51. m_TimeCommit.Cancel();
  52. YieldingFlushQueuedViewsToSQL();
  53. }
  54. else if( !m_TimeCommit.BIsScheduled() )
  55. {
  56. m_TimeCommit.Schedule( this, &CGCSQLWriteQueue< TSqlClass >::CreateJobToCommitSQL, m_nMaxMSToWrite );
  57. }
  58. }
  59. private:
  60. //called internally when we kick off a job after N amount of time has expired
  61. template < typename TSqlClass >
  62. class CTimeExpiredCommitJob : public CGCJob
  63. {
  64. public:
  65. CTimeExpiredCommitJob( CGCBase* pGC, CGCSQLWriteQueue< TSqlClass >* pClass ) : CGCJob( pGC ), m_pClass( pClass ) {}
  66. virtual bool BYieldingRunJob( void* pvStartParm )
  67. {
  68. m_pClass->YieldingFlushQueuedViewsToSQL();
  69. return true;
  70. }
  71. private:
  72. CGCSQLWriteQueue< TSqlClass >* m_pClass;
  73. };
  74. //the function called when time expires to start a job and commit the requests to SQL
  75. void CreateJobToCommitSQL()
  76. {
  77. //kick off our job, which just calls the flush
  78. CGCJob* pJob = new CTimeExpiredCommitJob< TSqlClass >( GGCBase(), this );
  79. pJob->StartJobDelayed( NULL );
  80. }
  81. //handles committing the list of queued views to SQL
  82. void YieldingFlushQueuedViewsToSQL()
  83. {
  84. if( m_QueuedRecords.Count() == 0 )
  85. return;
  86. //move the contents into a local vector so we don't have any conflicts of global state
  87. CUtlVector< TSqlClass > localQueue;
  88. localQueue.Swap( m_QueuedRecords );
  89. //prepare the queue for the next batch (so we don't have intermediate resizes)
  90. m_QueuedRecords.EnsureCapacity( m_nMaxToCache );
  91. // start a transaction for all this work
  92. CSQLAccess sqlAccess;
  93. sqlAccess.BBeginTransaction( "CGCWatchDownloadedReplayJob::FlushQueuedViewsToSQL" );
  94. FOR_EACH_VEC( localQueue, nCurrView )
  95. {
  96. sqlAccess.BYieldingInsertRecord( &localQueue[ nCurrView ] );
  97. }
  98. sqlAccess.BCommitTransaction();
  99. }
  100. //the records that we have queued
  101. CUtlVector< TSqlClass > m_QueuedRecords;
  102. //schedules a write back to ensure we commit at least every N seconds
  103. CScheduledFunction< CGCSQLWriteQueue< TSqlClass > > m_TimeCommit;
  104. //maximum number of seconds between commits
  105. uint32 m_nMaxMSToWrite;
  106. //maximum number of records to buffer before writing back
  107. uint32 m_nMaxToCache;
  108. };
  109. } //namespace GCSDK
  110. #endif