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.

305 lines
10 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Base class for objects that are kept in synch between client and server
  4. //
  5. //=============================================================================
  6. #ifndef SHAREDOBJECT_H
  7. #define SHAREDOBJECT_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. // ENABLE_SO_OVERWRITE_PARANOIA can be set to either 0 or 1. If enabled, it will add
  12. // extra fields to every CSharedObject instance to try and detect overwrites at the
  13. // cost of additional runtime memory.
  14. #define ENABLE_SO_OVERWRITE_PARANOIA 0
  15. // ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA can be set to either 0 or 1. If enabled, it
  16. // will add extra fields to every CSharedObject instance to try and detect issues with
  17. // constructions/destruction (ie., double-deletes, etc.), including reference counting.
  18. #define ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA (defined( STAGING_ONLY ))
  19. #include "tier0/memdbgon.h"
  20. namespace GCSDK
  21. {
  22. class CSQLAccess;
  23. class CSharedObject;
  24. typedef CSharedObject *(*SOCreationFunc_t)( );
  25. class CSharedObjectCache;
  26. //----------------------------------------------------------------------------
  27. // Purpose: Abstract base class for objects that are shared between the GC and
  28. // a gameserver/client. These can also be stored in the database.
  29. //----------------------------------------------------------------------------
  30. class CSharedObject
  31. {
  32. friend class CGCSharedObjectCache;
  33. friend class CSharedObjectCache;
  34. public:
  35. #ifdef GC
  36. virtual ~CSharedObject()
  37. {
  38. #if ENABLE_SO_OVERWRITE_PARANOIA
  39. m_pThis = NULL;
  40. #endif // ENABLE_SO_OVERWRITE_PARANOIA
  41. #if ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA
  42. AssertMsg2( m_nRefCount == 0, "Deleting shared object type %d with refcount %d", m_nSOTypeID, m_nRefCount );
  43. m_nSOTypeID = -1;
  44. m_nRefCount = -1;
  45. #endif // ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA
  46. }
  47. #if ENABLE_SO_OVERWRITE_PARANOIA
  48. CSharedObject *m_pThis;
  49. #endif // ENABLE_SO_OVERWRITE_PARANOIA
  50. #if ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA
  51. int m_nRefCount;
  52. mutable int m_nSOTypeID;
  53. #endif // ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA
  54. void Check() const
  55. {
  56. #if ENABLE_SO_OVERWRITE_PARANOIA
  57. Assert( m_pThis == this );
  58. #endif // ENABLE_SO_OVERWRITE_PARANOIA
  59. #if ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA
  60. Assert( m_nRefCount >= 0 );
  61. if ( m_nSOTypeID == kSharedObject_UnassignedType )
  62. {
  63. m_nSOTypeID = GetTypeID();
  64. }
  65. Assert( m_nSOTypeID >= 0 );
  66. #endif // ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA
  67. }
  68. #else
  69. virtual ~CSharedObject() {}
  70. #endif
  71. virtual int GetTypeID() const = 0;
  72. virtual bool BParseFromMessage( const CUtlBuffer & buffer ) = 0;
  73. virtual bool BParseFromMessage( const std::string &buffer ) = 0;
  74. virtual bool BUpdateFromNetwork( const CSharedObject & objUpdate ) = 0;
  75. virtual bool BIsKeyLess( const CSharedObject & soRHS ) const = 0;
  76. virtual void Copy( const CSharedObject & soRHS ) = 0;
  77. virtual void Dump() const = 0;
  78. virtual bool BShouldDeleteByCache() const { return true; }
  79. virtual CUtlString GetDebugString() const { return PchClassName( GetTypeID() ); };
  80. bool BIsKeyEqual( const CSharedObject & soRHS ) const;
  81. static void RegisterFactory( int nTypeID, SOCreationFunc_t fnFactory, uint32 unFlags, const char *pchClassName );
  82. static CSharedObject *Create( int nTypeID );
  83. static uint32 GetTypeFlags( int nTypeID );
  84. static const char *PchClassName( int nTypeID );
  85. static const char *PchClassBuildCacheNodeName( int nTypeID );
  86. static const char *PchClassCreateNodeName( int nTypeID );
  87. static const char *PchClassUpdateNodeName( int nTypeID );
  88. #ifdef GC
  89. virtual bool BIsNetworked() const { return true; }
  90. virtual bool BIsDatabaseBacked() const { return true; }
  91. virtual bool BYieldingAddToDatabase();
  92. virtual bool BYieldingWriteToDatabase( const CUtlVector< int > &fields );
  93. virtual bool BYieldingRemoveFromDatabase();
  94. virtual bool BYieldingAddInsertToTransaction( CSQLAccess & sqlAccess ) { return false; }
  95. virtual bool BYieldingAddWriteToTransaction( CSQLAccess & sqlAccess, const CUtlVector< int > &fields ) { return false; }
  96. virtual bool BYieldingAddRemoveToTransaction( CSQLAccess & sqlAccess ) { return false; }
  97. virtual bool BAddToMessage( CUtlBuffer & bufOutput ) const = 0;
  98. virtual bool BAddToMessage( std::string *pBuffer ) const = 0;
  99. virtual bool BAddDestroyToMessage( CUtlBuffer & bufDestroy ) const = 0;
  100. virtual bool BAddDestroyToMessage( std::string *pBuffer ) const = 0;
  101. virtual bool BParseFromMemcached( CUtlBuffer & buffer ) { return false; }
  102. virtual bool BAddToMemcached( CUtlBuffer & bufOutput ) const { return false; }
  103. bool BSendCreateToSteamID( const CSteamID & steamID, const CSteamID & ownerID, uint64 ulVersion ) const;
  104. bool BSendDestroyToSteamID( const CSteamID & steamID, const CSteamID & ownerID, uint64 ulVersion ) const;
  105. #ifdef DBGFLAG_VALIDATE
  106. virtual void Validate( CValidator &validator, const char *pchName );
  107. static void ValidateStatics( CValidator & validator );
  108. #endif
  109. protected:
  110. /*
  111. // Dirty bit modification. Do not call these directly on SharedObjects. Call them
  112. // on the cache that owns the object so they can be added/removed from the right lists.
  113. virtual void DirtyField( int nField ) = 0;
  114. virtual void MakeDatabaseClean() = 0;
  115. virtual void MakeNetworkClean() = 0;
  116. */
  117. #endif // GC
  118. #ifdef GC
  119. CSharedObject()
  120. {
  121. #if ENABLE_SO_OVERWRITE_PARANOIA
  122. m_pThis = this;
  123. #endif // ENABLE_SO_OVERWRITE_PARANOIA
  124. #if ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA
  125. m_nRefCount = 0;
  126. m_nSOTypeID = kSharedObject_UnassignedType;
  127. #endif // ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA
  128. }
  129. #endif
  130. private:
  131. #if ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA
  132. enum { kSharedObject_UnassignedType = -999 };
  133. #endif // ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA
  134. struct SharedObjectInfo_t
  135. {
  136. SOCreationFunc_t m_pFactoryFunction;
  137. uint32 m_unFlags;
  138. const char *m_pchClassName;
  139. CUtlString m_sBuildCacheSubNodeName;
  140. CUtlString m_sUpdateNodeName;
  141. CUtlString m_sCreateNodeName;
  142. };
  143. static CUtlMap<int, SharedObjectInfo_t> sm_mapFactories;
  144. public:
  145. static const CUtlMap<int, SharedObjectInfo_t> & GetFactories() { return sm_mapFactories; }
  146. };
  147. typedef CUtlVectorFixedGrowable<CSharedObject *, 1> CSharedObjectVec;
  148. #ifdef GC
  149. //this class manages the stats for the shared objects, such as how many exist, how many have been sent, how many have been created, how many destroyed
  150. class CSharedObjectStats
  151. {
  152. public:
  153. CSharedObjectStats();
  154. //called to register a shared object class given a type ID and name. This will return false if
  155. //a type of this ID is already registered
  156. void RegisterSharedObjectType( int nTypeID, const char* pszTypeName );
  157. //called to track when a shared object is created/destroyed to update the running total
  158. void TrackSharedObjectLifetime( int nTypeID, int32 nCount );
  159. //called when a shared object is created to track its creation
  160. void TrackSharedObjectSendCreate( int nTypeID, uint32 nCount );
  161. //called when a shared object is destroyed to track counts
  162. void TrackSharedObjectSendDestroy( int nTypeID, uint32 nCount );
  163. //tracks a new subscription
  164. void TrackSubscription( int nTypeID, uint32 nFlags, uint32 nNumSubscriptions );
  165. //called when a shared object is sent
  166. void TrackSharedObjectSend( int nTypeID, uint32 nNumClients, uint32 nMsgSize );
  167. //reset the stats for all the caches
  168. void ResetStats();
  169. //called to start/stop collecting stats
  170. void StartCollectingStats();
  171. void StopCollectingStats();
  172. bool IsCollectingStats() const { return m_bCollectingStats; }
  173. //called to report the currently collected stats
  174. void ReportCollectedStats() const;
  175. private:
  176. struct SOStats_t
  177. {
  178. SOStats_t();
  179. void ResetStats();
  180. //the text name of this cache
  181. CUtlString m_sName;
  182. //the number of outstanding SO cache objects of this type. This is not cleared
  183. uint32 m_nNumActive;
  184. //the type ID of this stat
  185. int m_nTypeID;
  186. //the total number that have been created/destroyed. Active is difference between these
  187. uint32 m_nNumCreated;
  188. uint32 m_nNumDestroyed;
  189. //how many bytes we have sent (raw, and multiplexed to multiple subscribers)
  190. uint64 m_nRawBytesSent;
  191. uint64 m_nMultiplexedBytesSent;
  192. //the number of sends since our last clear
  193. uint32 m_nNumSends;
  194. //how many subscriptions we have gotten by various subscription types
  195. uint32 m_nNumSubOwner;
  196. uint32 m_nNumSubOtherUsers;
  197. uint32 m_nNumSubGameServer;
  198. };
  199. //sort function that controls the order that the SO stats are presented in the report
  200. static bool SortSOStatsSent( const SOStats_t* pLhs, const SOStats_t* pRhs );
  201. static bool SortSOStatsSubscribe( const SOStats_t* pLhs, const SOStats_t* pRhs );
  202. //to compact the memory space for wide ranging type IDs, the list of stats has two components, an array that can be looked up
  203. //via the type ID which maps to a stat index (or invalid index if no mapping is registered)
  204. static const uint16 knInvalidIndex = ( uint16 )-1;
  205. CUtlVector< uint16 > m_vTypeToIndex;
  206. CUtlVector< SOStats_t > m_Stats;
  207. //are we currently collecting stats or not?
  208. bool m_bCollectingStats;
  209. //the time that we've been collecting
  210. CJobTime m_CollectTime;
  211. uint64 m_nMicroSElapsed;
  212. };
  213. //global stat tracker
  214. extern CSharedObjectStats g_SharedObjectStats;
  215. #endif
  216. //----------------------------------------------------------------------------
  217. // Purpose: Templatized function to use as a factory method for
  218. // CSharedObject subclasses
  219. //----------------------------------------------------------------------------
  220. template<typename SharedObjectSubclass_t>
  221. CSharedObject *CreateSharedObjectSubclass()
  222. {
  223. return new SharedObjectSubclass_t();
  224. }
  225. // Version that always asserts and returns NULL, for SOs that should not be auto-created this way
  226. template<int nSharedObjectType>
  227. CSharedObject *CreateSharedObjectSubclassProhibited()
  228. {
  229. AssertMsg( false, "Attempting to auto-create object of type %d which does not allow SO-based creation", nSharedObjectType );
  230. return NULL;
  231. }
  232. #ifdef GC
  233. #define REG_SHARED_OBJECT_SUBCLASS( derivedClass, flags ) GCSDK::CSharedObject::RegisterFactory( derivedClass::k_nTypeID, GCSDK::CreateSharedObjectSubclass<derivedClass>, (flags), #derivedClass )
  234. // GC only -- sharedobjects that cannot be auto-created by the SO code, and might not have a specific derived class that
  235. // publicly implements the interface
  236. #define REG_SHARED_OBJECT_SUBCLASS_BY_ID_NOCREATE( strName, nTypeID, flags ) \
  237. GCSDK::CSharedObject::RegisterFactory( nTypeID, CreateSharedObjectSubclassProhibited<nTypeID>, (flags), strName )
  238. #else
  239. #define REG_SHARED_OBJECT_SUBCLASS( derivedClass ) GCSDK::CSharedObject::RegisterFactory( derivedClass::k_nTypeID, GCSDK::CreateSharedObjectSubclass<derivedClass>, 0, #derivedClass )
  240. #endif
  241. } // namespace GCSDK
  242. #include "tier0/memdbgoff.h"
  243. #endif //SHAREDOBJECT_H