DynamicProfileStorage.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. #ifdef DYNAMIC_PROFILE_STORAGE
  7. class DynamicProfileStorage
  8. {
  9. public:
  10. static bool Initialize();
  11. static bool Uninitialize();
  12. static bool IsEnabled() { return enabled; }
  13. static bool DoCollectInfo() { return collectInfo; }
  14. template <typename Fn>
  15. static Js::SourceDynamicProfileManager * Load(__in_z char16 const * filename, Fn loadFn);
  16. static void SaveRecord(__in_z char16 const * filename, __in_ecount(sizeof(DWORD) + *record) char const * record);
  17. static char * AllocRecord(DECLSPEC_GUARD_OVERFLOW DWORD bufferSize);
  18. static void DeleteRecord(__in_ecount(sizeof(DWORD) + *record) char const * record);
  19. static char const * GetRecordBuffer(__in_ecount(sizeof(DWORD) + *record) char const * record);
  20. static char * GetRecordBuffer(__in_ecount(sizeof(DWORD) + *record) char * record);
  21. static DWORD GetRecordSize(__in_ecount(sizeof(DWORD) + *record) char const * record);
  22. private:
  23. static char16 const * GetMessageType();
  24. static void ClearInfoMap(bool deleteFileStorage);
  25. static bool ImportFile(__in_z char16 const * filename, bool allowNonExistingFile);
  26. static bool ExportFile(__in_z char16 const * filename);
  27. static bool SetupCacheDir(__in_z char16 const * dirname);
  28. static void DisableCacheDir();
  29. static bool CreateCacheCatalog();
  30. static void ClearCacheCatalog();
  31. static bool LoadCacheCatalog();
  32. static bool AppendCacheCatalog(__in_z char16 const * url);
  33. static bool AcquireLock();
  34. static bool ReleaseLock();
  35. static bool VerifyHeader();
  36. static bool initialized;
  37. static bool uninitialized;
  38. static bool enabled;
  39. static bool collectInfo;
  40. static bool useCacheDir;
  41. static char16 cacheDrive[_MAX_DRIVE];
  42. static char16 cacheDir[_MAX_DIR];
  43. static char16 catalogFilename[_MAX_PATH];
  44. static DWORD const MagicNumber;
  45. static DWORD const FileFormatVersion;
  46. #ifdef _WIN32
  47. typedef DWORD TimeType;
  48. static inline TimeType GetCreationTime() { return _time32(NULL); }
  49. #else
  50. typedef time_t TimeType;
  51. static inline TimeType GetCreationTime() { return time(NULL); }
  52. #endif
  53. static TimeType creationTime;
  54. static int32 lastOffset;
  55. static HANDLE mutex;
  56. static CriticalSection cs;
  57. static DWORD nextFileId;
  58. #if DBG
  59. static bool locked;
  60. #endif
  61. #if DBG_DUMP
  62. static bool DoTrace();
  63. #endif
  64. class StorageInfo
  65. {
  66. public:
  67. void GetFilename(_Out_writes_z_(_MAX_PATH) char16 filename[_MAX_PATH]) const;
  68. char const * ReadRecord() const;
  69. bool WriteRecord(__in_ecount(sizeof(DWORD) + *record) char const * record) const;
  70. bool isFileStorage;
  71. union
  72. {
  73. DWORD fileId;
  74. char const * record;
  75. };
  76. };
  77. typedef JsUtil::BaseDictionary<char16 const *, StorageInfo, NoCheckHeapAllocator, PrimeSizePolicy, DefaultComparer, JsUtil::DictionaryEntry> InfoMap;
  78. static InfoMap infoMap;
  79. };
  80. template <class Fn>
  81. Js::SourceDynamicProfileManager *
  82. DynamicProfileStorage::Load(char16 const * filename, Fn loadFn)
  83. {
  84. Assert(DynamicProfileStorage::IsEnabled());
  85. AutoCriticalSection autocs(&cs);
  86. if (useCacheDir && AcquireLock())
  87. {
  88. LoadCacheCatalog(); // refresh the cache catalog
  89. }
  90. StorageInfo * info;
  91. if (!infoMap.TryGetReference(filename, &info))
  92. {
  93. if (useCacheDir)
  94. {
  95. ReleaseLock();
  96. }
  97. #if !DBG || !defined(_M_AMD64)
  98. char16 const * messageType = GetMessageType();
  99. if (messageType)
  100. {
  101. Output::Print(_u("%s: DynamicProfileStorage: Dynamic Profile Data not found for '%s'\n"), messageType, filename);
  102. Output::Flush();
  103. }
  104. #endif
  105. return nullptr;
  106. }
  107. char const * record;
  108. if (info->isFileStorage)
  109. {
  110. Assert(useCacheDir);
  111. Assert(locked);
  112. record = info->ReadRecord();
  113. ReleaseLock();
  114. if (record == nullptr)
  115. {
  116. #if DBG_DUMP
  117. if (DynamicProfileStorage::DoTrace())
  118. {
  119. Output::Print(_u("TRACE: DynamicProfileStorage: Faile to load from cache dir for '%s'"), filename);
  120. Output::Flush();
  121. }
  122. #endif
  123. return nullptr;
  124. }
  125. }
  126. else
  127. {
  128. record = info->record;
  129. }
  130. Js::SourceDynamicProfileManager * sourceDynamicProfileManager = loadFn(GetRecordBuffer(record), GetRecordSize(record));
  131. if (info->isFileStorage)
  132. {
  133. // The data is backed by a file, we can delete the memory
  134. Assert(useCacheDir);
  135. DeleteRecord(record);
  136. }
  137. #if DBG_DUMP
  138. if (DynamicProfileStorage::DoTrace() && sourceDynamicProfileManager)
  139. {
  140. Output::Print(_u("TRACE: DynamicProfileStorage: Dynamic Profile Data Loaded: '%s'\n"), filename);
  141. }
  142. #endif
  143. if (sourceDynamicProfileManager == nullptr)
  144. {
  145. char16 const * messageType = GetMessageType();
  146. if (messageType)
  147. {
  148. Output::Print(_u("%s: DynamicProfileStorage: Dynamic Profile Data corrupted: '%s'\n"), messageType, filename);
  149. Output::Flush();
  150. }
  151. }
  152. return sourceDynamicProfileManager;
  153. }
  154. #endif