Counter Strike : Global Offensive Source Code
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.

326 lines
13 KiB

  1. //========= Copyright � 2006, Electonic Arts(C) 2006 - All Rights Reserved ============//
  2. #ifndef FILEGROUP_H
  3. #define FILEGROUP_H
  4. #include <sys/stat.h>
  5. #include "zlib/zlib.h"
  6. #ifdef _PS3
  7. // #ifndef _RETAIL
  8. // #define TIME_FILE_OPERATIONS
  9. // #endif
  10. //#define MEMCMP_FILE_OPERATIONS
  11. #include "tier0/platform.h"
  12. #include <sys/synchronization.h>
  13. #include <sys/types.h>
  14. #include <sys/ppu_thread.h>
  15. #include <sys/stat.h>
  16. #endif //_PS3
  17. #define FILEGROUP_FORMAT_ID "FGP"
  18. #define PREVIOUS_FILEGROUP_FORMAT_VERSION 1 //TEMP: Used for backwards compatibility
  19. #define FILEGROUP_FORMAT_VERSION 2 //Preload section enhancement
  20. #define FILEGROUP_FORMAT_VERSION_COMPILED_DIRECTORY 3 //Preprocessed directory section
  21. const int MAX_FILE_GROUPS = 7;
  22. const int FILEGROUP_UNCOMPRESSED_BUFFER_SIZE = (8 * 1024);
  23. const int FILEGROUP_READ_CHUNK_SIZE = (64 * 1024);
  24. const int FILEGROUP_READ_STORE_SIZE = FILEGROUP_READ_CHUNK_SIZE * 2;
  25. const int FILEGROUP_READ_SIGNAL_SIZE = FILEGROUP_READ_CHUNK_SIZE * 2;
  26. const int FILEGROUP_READ_THREAD_BUFFER_SIZE = FILEGROUP_READ_CHUNK_SIZE * 4;
  27. #define FILEGROUP_USE_HASH_DIRECTORY
  28. #ifdef FILEGROUP_USE_HASH_DIRECTORY
  29. const int FILEGROUP_DIRECTORY_BUCKETS = 256; //Must be power of 2
  30. const int FILEGROUP_BUCKET_MOD = FILEGROUP_DIRECTORY_BUCKETS-1;
  31. #endif
  32. struct FileIdentifier
  33. {
  34. char* mName;
  35. unsigned int mNameId;
  36. bool mNameIdSet;
  37. };
  38. struct DirectoryHeader
  39. {
  40. char mId[4];
  41. int mVersion;
  42. int mNumEntries;
  43. int mNumPreloadEntries; //Added for FILEGROUP_FORMAT_VERSION 2
  44. };
  45. struct PreviousDirectoryHeader //TEMP: Used for backwards compatibility
  46. {
  47. char mId[4];
  48. int mVersion;
  49. int mNumEntries;
  50. };
  51. struct DirectoryEntry
  52. {
  53. char mName[MAX_PATH];
  54. size_t mPosition;
  55. size_t mLength;
  56. size_t mCompressedLength; //Set to zero if compression not used
  57. };
  58. struct SmallDirectoryEntry
  59. {
  60. // char mName[116];
  61. unsigned int mNameId;
  62. size_t mPosition;
  63. size_t mLength;
  64. size_t mCompressedLength; //Set to zero if compression not used
  65. };
  66. #ifdef _PS3
  67. #ifdef MEMCMP_FILE_OPERATIONS
  68. struct DirectoryEntryExtraInfo
  69. {
  70. char mFullFileName[MAX_PATH];
  71. };
  72. #endif
  73. struct FileGroupReadBuffer
  74. {
  75. void AllocateBuffer(size_t bufferSize);
  76. void FreeBuffer();
  77. void CloseFile();
  78. void WaitOnDiskEjectRecovery();
  79. sys_ppu_thread_t mReadThread;
  80. unsigned char* mBuffer;
  81. size_t mBufferSize;
  82. size_t mReadChunkSize;
  83. // unsigned char mBuffer[FILEGROUP_READ_THREAD_BUFFER_SIZE];
  84. int mFile;
  85. char mFileName[MAX_PATH]; //Need to store filegroup name so that file can be reopened following disk eject
  86. uint64_t mFileBlockSize;
  87. uint64_t mFileSectorSize;
  88. sys_lwmutex_t mBufferMutex; //Used for all updates to the buffer data
  89. sys_lwmutex_attribute_t mBufferMutexAttr;
  90. sys_lwmutex_t mNextConsumeByteMutex; //Used for synchronization of multiple consumer threads
  91. sys_lwmutex_attribute_t mNextConsumeByteMutexAttr;
  92. sys_lwmutex_t mBufferStartEndPosMutex; //Used for synchronization of buffer start and end positions - don't want to update these while in use by consumer
  93. sys_lwmutex_attribute_t mBufferStartEndPosMutexAttr;
  94. sys_mutex_t mReadThreadSignalMutex;
  95. sys_mutex_attribute_t mReadThreadSignalMutexAttr;
  96. sys_cond_t mReadThreadSignal; //Signaled by consumer thread indicating that either:
  97. //- there is space for the read thread to carry on reading
  98. //- or the filegroup has been deleted
  99. sys_cond_attribute_t mReadThreadSignalAttr;
  100. sys_lwmutex_t mEjectRecoveryMutex; //Used to ensure only one thread performs the disk eject recovery procedure
  101. sys_lwmutex_attribute_t mEjectRecoveryMutexAttr;
  102. bool mFileGroupDeleted;
  103. size_t mNextConsumePos; //Position of next byte due for read by the consumer thread
  104. //Read thread does not overwrite any bytes FILEGROUP_READ_STORE_SIZE bytes before this point.
  105. //unsigned char* mNextConsumeByte; //Position of next byte due for read by the consumer thread
  106. // //Read thread does not overwrite bytes beyond this point
  107. size_t mBufferStartPos; //Position in file corresponding to the beginning of the buffer
  108. size_t mCurrentPos; //Current position in file
  109. unsigned char* mCurrentByte; //Next byte to be read to in buffer
  110. size_t mBufferEndPos; //Position in file corresponding to the end of the buffer (set to zero until initial population of buffer)
  111. bool mAwaitingConsumer; //If set, indicates that the read thread is waiting for data to be read by the consumer thread
  112. #ifdef TIME_FILE_OPERATIONS
  113. system_time_t m_fReadTime;
  114. int m_fReadBytes;
  115. #endif
  116. };
  117. class CFileGroup;
  118. class CFileGroupOpenedFile
  119. {
  120. public:
  121. CFileGroupOpenedFile();
  122. ~CFileGroupOpenedFile();
  123. #ifdef MEMCMP_FILE_OPERATIONS
  124. void Init(const SmallDirectoryEntry& dirEntry, CFileGroup* parentFileGroup, FileGroupReadBuffer* parentBuffer, char* fullFileName, bool preload);
  125. #else
  126. void Init(const SmallDirectoryEntry& dirEntry, CFileGroup* parentFileGroup, FileGroupReadBuffer* parentBuffer, bool preload);
  127. #endif
  128. virtual void FS_fseek( __int64 pos, int seekType );
  129. virtual long FS_ftell();
  130. virtual int FS_feof();
  131. virtual size_t FS_fread( void *dest, size_t destSize, size_t size);
  132. virtual char *FS_fgets( char *dest, int destSize );
  133. // const char* GetName() const {return mDirEntry->mName;}
  134. size_t GetPosition() const {return mDirEntry->mPosition;}
  135. size_t GetLength() const {return mDirEntry->mLength;}
  136. size_t GetCompressedLength() const {return mDirEntry->mCompressedLength;}
  137. bool IsPreloaded() const {return mPreloaded;}
  138. void FS_fclose();
  139. #ifdef _DEBUG
  140. static int refCount;
  141. #endif
  142. private:
  143. void Rewind();
  144. size_t ReadFromCompressedData( void *dest, size_t readSize);
  145. size_t ReadFromUncompressedData( void *dest, size_t readSize);
  146. void TraceMemCopy(void* pDest, const void* pSource, size_t nBytes);
  147. SmallDirectoryEntry const * mDirEntry;
  148. CFileGroup* mParentFileGroup;
  149. size_t mSeekPosIndicator;// This is current position as returned by FS_ftell.
  150. size_t mActualPosIndicator;// This is the uncompressed position within the file corresponding to the last read.
  151. size_t mCompressedPosIndicator; //This is the number of compressed bytes which have been read.
  152. bool mEof; //Set to true on attempting to read beyond the end of the file
  153. unsigned char mUncompressedBuffer[FILEGROUP_UNCOMPRESSED_BUFFER_SIZE];
  154. //unsigned char* mRemainingUncompressedBuffer; //Pointer to bytes within the uncompressed buffer which have yet to be read
  155. //size_t mNumRemainingUncompressedBytes; //Number of bytes in the compressed buffer which have yet to be read
  156. int mUncompressedBufferStartPos;
  157. z_stream mStrm; //Zlib stream
  158. FileGroupReadBuffer* mParentReadBuffer;
  159. bool mPreloaded;
  160. #ifdef MEMCMP_FILE_OPERATIONS
  161. int mOrdinaryFile;
  162. #endif
  163. };
  164. class CFileGroupSystem
  165. {
  166. public:
  167. CFileGroupSystem();
  168. ~CFileGroupSystem();
  169. void Init();
  170. int AddFileGroup(const char* fileGroupName, bool useReadThread = true, int* filegroup_index = NULL, bool usepreload = false, int bufferSize = FILEGROUP_READ_CHUNK_SIZE, int readChunkSize = FILEGROUP_READ_CHUNK_SIZE);
  171. void DeleteFileGroup();
  172. void DeleteFileGroup(int ID);
  173. void DeleteFileGroup(CFileGroup* fileGroup);
  174. void DeleteFileGroup(CFileGroup* fileGroup, int groupIndex);
  175. int CurrentFileGroup();
  176. CFileGroupOpenedFile* FS_fopen( FileIdentifier *filename, const char *options, unsigned int flags, __int64 *size );
  177. CFileGroupOpenedFile* FS_fopen( int filegroup_index, FileIdentifier *filename, const char *options, unsigned int flags, __int64 *size );
  178. int FS_stat( FileIdentifier *path, struct stat *buf );
  179. int FS_stat( FileIdentifier *path, CellFsStat *buf );
  180. int FS_stat( int filegroup_index, FileIdentifier *path, struct stat *buf );
  181. int FS_stat( int filegroup_index, FileIdentifier *path, CellFsStat *buf );
  182. void Lock() {int ret = sys_lwmutex_lock( &mFileGroupSystemMutex, 0 ); if (ret != CELL_OK) printf("Error locking filegroup system mutex %d\n", ret);}
  183. void Unlock() {int ret = sys_lwmutex_unlock( &mFileGroupSystemMutex); if (ret != CELL_OK) printf("Error unlocking filegroup system mutex %d\n", ret);}
  184. void DecrementNumFileGroups(){m_numFileGroups--;}
  185. CFileGroupOpenedFile* GetOpenedFile(); //Get next available CFileGroupOpenedFile from pool
  186. void FreeOpenedFile(CFileGroupOpenedFile*); //Return CFileGroupOpenedFile to pool
  187. #ifdef _DEBUG
  188. static int refCount;
  189. #endif
  190. private:
  191. CFileGroup* m_mapGroup;
  192. CFileGroup* m_shaderGroup;
  193. CFileGroup* m_fileGroups[MAX_FILE_GROUPS];
  194. int m_numFileGroups;
  195. int m_currentFileGroup;
  196. sys_lwmutex_t mFileGroupSystemMutex;
  197. int m_lastGroupPopulated;
  198. //Pool of CFileGroupOpenedFile objects
  199. struct FileGroupFilePoolNode
  200. {
  201. CFileGroupOpenedFile thisFile;
  202. FileGroupFilePoolNode* nextNode;
  203. };
  204. FileGroupFilePoolNode* m_openedFilePool;
  205. FileGroupFilePoolNode* m_availableFileNodes;
  206. FileGroupFilePoolNode* m_openedFileNodes;
  207. int m_totalOpenedFiles;
  208. bool m_initComplete;
  209. };
  210. class CFileGroup
  211. {
  212. public:
  213. CFileGroup(CFileGroupSystem* pFs);
  214. ~CFileGroup();
  215. void Clear();
  216. int Populate(const char* fileGroupName, bool usepreload = false);
  217. CFileGroupOpenedFile* FS_fopen( FileIdentifier *pFileName, const char *pOptions, unsigned int flags, __int64 *size );
  218. int FS_stat( FileIdentifier *path, CellFsStat *buf );
  219. void DecrementOpenedCount();
  220. void IncrementOpenedCount(){mOpenedCount++;}
  221. int GetFile() const {return mReadBuffer.mFile;}
  222. size_t GetPosOffset() const {return mPosOffset;}
  223. int GetOpenedCount(){return mOpenedCount;}
  224. void* GetPreloadData(){return mPreloadSection;}
  225. void FlagForDeletion(){mFlaggedForDeletion = true;}
  226. void Lock() {mFs->Lock();}
  227. void Unlock() {mFs->Unlock();}
  228. bool IsPopulated() {return (mReadBuffer.mFile);}
  229. void FreeOpenedFile(CFileGroupOpenedFile* freeFile){mFs->FreeOpenedFile(freeFile);}
  230. void StartReadThread();
  231. void StopReadThread();
  232. void TidyUpSynchObjects();
  233. sys_ppu_thread_t GetReadThread(){return mReadBuffer.mReadThread;}
  234. bool UsingReadThread(){return (mReadBuffer.mReadThread);}
  235. // unsigned char* GetIgnoreUncompressBuffer(){return mFs->GetIgnoreUncompressBuffer();}
  236. size_t Size(){return mFileStat.st_size;}
  237. bool HasBeenDeleted(){return mReadBuffer.mFileGroupDeleted;}
  238. void CloseFile(){mReadBuffer.CloseFile();}
  239. void AllocateReadBuffer(size_t bufSize){mReadBuffer.AllocateBuffer(bufSize);}
  240. void SetReadChunkSize(size_t readChunkSize){mReadBuffer.mReadChunkSize = readChunkSize;}
  241. void FreeReadBuffer(){mReadBuffer.FreeBuffer();}
  242. #ifdef _DEBUG
  243. static int refCount;
  244. #endif
  245. #ifdef TIME_FILE_OPERATIONS
  246. void PrintFileGroupStats();
  247. void ResetFileTimings();
  248. system_time_t GetfReadTime(){return mReadBuffer.m_fReadTime;}
  249. int GetfReadBytes(){return mReadBuffer.m_fReadBytes;}
  250. void IncrReadTime(system_time_t timeVal){mReadBuffer.m_fReadTime += timeVal;}
  251. void IncrReadBytes(int bytesVal){mReadBuffer.m_fReadBytes += bytesVal; /*if(mReadBuffer.m_fReadBytes%10485760 == 0) PrintFileGroupStats();*/};
  252. system_time_t m_memCopyTime;
  253. system_time_t m_uncompressTime;
  254. int m_fsReads;
  255. int m_fgets;
  256. int m_uncompressCalls;
  257. int m_rewinds;
  258. int m_fileJumps;
  259. int m_bytesfRead;
  260. int m_bytesReadFromFileByConsumer;
  261. int m_bytesReadFromBuffer;
  262. #endif
  263. private:
  264. CellFsErrno PopulateDirectory(DirectoryHeader* hdr, int* entriesPopulated);
  265. int FindFile(FileIdentifier *pFileName);
  266. char* ReformatFileName(char* inputFileName);
  267. unsigned int HashFileName(const char * fName);
  268. SmallDirectoryEntry* mDirectoryEntries;
  269. unsigned int mNumDirectoryEntries;
  270. void* mPreloadSection;
  271. int mPreloadEntries;
  272. #ifdef FILEGROUP_USE_HASH_DIRECTORY
  273. struct HashBucket
  274. {
  275. unsigned int mPosition;
  276. unsigned int mCount;
  277. };
  278. unsigned int* mHashDirectory; //ordered into buckets
  279. HashBucket mHashBuckets[FILEGROUP_DIRECTORY_BUCKETS];
  280. #endif
  281. unsigned int mLastOpenedDirectoryIndex;
  282. unsigned int mLastFailedId;
  283. CellFsStat mFileStat;
  284. size_t mPosOffset; //Position at which the data starts
  285. CFileGroupSystem* mFs;
  286. int mOpenedCount;
  287. bool mFlaggedForDeletion;
  288. FileGroupReadBuffer mReadBuffer;
  289. #ifdef MEMCMP_FILE_OPERATIONS
  290. DirectoryEntryExtraInfo* mDirectoryExtraInfo;
  291. #endif
  292. };
  293. #endif //_PS3
  294. #endif //FILEGROUP_H