Usage.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. //---------------------------------------------------------------------------
  2. #include <CorePCH.h>
  3. #pragma hdrstop
  4. #include <Configuration.h>
  5. #include <Usage.h>
  6. #include <FileInfo.h>
  7. //---------------------------------------------------------------------------
  8. const UnicodeString LastInternalExceptionCounter(L"LastInternalException2");
  9. const UnicodeString LastUpdateExceptionCounter(L"LastUpdateException");
  10. //---------------------------------------------------------------------------
  11. __fastcall TUsage::TUsage(TConfiguration * Configuration)
  12. {
  13. FCriticalSection = new TCriticalSection();
  14. FConfiguration = Configuration;
  15. FValues = new TStringList();
  16. FValues->Delimiter = L'&';
  17. FValues->StrictDelimiter = true;
  18. FCollect = true;
  19. Default();
  20. }
  21. //---------------------------------------------------------------------------
  22. __fastcall TUsage::~TUsage()
  23. {
  24. delete FValues;
  25. delete FCriticalSection;
  26. }
  27. //---------------------------------------------------------------------------
  28. void __fastcall TUsage::Default()
  29. {
  30. TGuard Guard(FCriticalSection);
  31. FPeriodCounters.clear();
  32. FLifetimeCounters.clear();
  33. FValues->Clear();
  34. if (Collect) // optimization
  35. {
  36. Set(L"FirstUse", StandardTimestamp());
  37. Set(L"FirstVersion", IntToStr(FConfiguration->CompoundVersion));
  38. UpdateLastReport();
  39. }
  40. }
  41. //---------------------------------------------------------------------------
  42. void __fastcall TUsage::Load(THierarchicalStorage * Storage)
  43. {
  44. TGuard Guard(FCriticalSection);
  45. Default();
  46. if (Storage->OpenSubKey(L"Values", false))
  47. {
  48. TStrings * Names = new TStringList();
  49. try
  50. {
  51. Storage->GetValueNames(Names);
  52. for (int Index = 0; Index < Names->Count; Index++)
  53. {
  54. UnicodeString Name = Names->Strings[Index];
  55. Set(Name, Storage->ReadString(Name, L""));
  56. }
  57. Storage->CloseSubKey();
  58. }
  59. __finally
  60. {
  61. delete Names;
  62. }
  63. }
  64. Load(Storage, L"PeriodCounters", FPeriodCounters);
  65. Load(Storage, L"LifetimeCounters", FLifetimeCounters);
  66. }
  67. //---------------------------------------------------------------------------
  68. void __fastcall TUsage::Load(THierarchicalStorage * Storage,
  69. const UnicodeString& Name, TCounters & Counters)
  70. {
  71. if (Storage->OpenSubKey(Name, false))
  72. {
  73. TStrings * Names = new TStringList();
  74. try
  75. {
  76. Storage->GetValueNames(Names);
  77. for (int Index = 0; Index < Names->Count; Index++)
  78. {
  79. UnicodeString Name = Names->Strings[Index];
  80. Counters.insert(
  81. std::make_pair(Name, Storage->ReadInteger(Name, 0)));
  82. }
  83. Storage->CloseSubKey();
  84. }
  85. __finally
  86. {
  87. delete Names;
  88. }
  89. }
  90. }
  91. //---------------------------------------------------------------------------
  92. void __fastcall TUsage::Save(THierarchicalStorage * Storage) const
  93. {
  94. TGuard Guard(FCriticalSection);
  95. if (Storage->OpenSubKey(L"Values", true))
  96. {
  97. Storage->ClearValues();
  98. Storage->WriteValues(FValues, true);
  99. Storage->CloseSubKey();
  100. }
  101. Save(Storage, L"PeriodCounters", FPeriodCounters);
  102. Save(Storage, L"LifetimeCounters", FLifetimeCounters);
  103. }
  104. //---------------------------------------------------------------------------
  105. void __fastcall TUsage::Save(THierarchicalStorage * Storage,
  106. const UnicodeString & Name, const TCounters & Counters) const
  107. {
  108. if (Storage->OpenSubKey(Name, true))
  109. {
  110. Storage->ClearValues();
  111. TCounters::const_iterator i = Counters.begin();
  112. while (i != Counters.end())
  113. {
  114. Storage->WriteInteger(i->first, i->second);
  115. i++;
  116. }
  117. Storage->CloseSubKey();
  118. }
  119. }
  120. //---------------------------------------------------------------------------
  121. void __fastcall TUsage::Set(const UnicodeString & Key, const UnicodeString & Value)
  122. {
  123. if (Collect)
  124. {
  125. TGuard Guard(FCriticalSection);
  126. FValues->Values[Key] = Value;
  127. }
  128. }
  129. //---------------------------------------------------------------------------
  130. void __fastcall TUsage::Set(const UnicodeString & Key, int Value)
  131. {
  132. Set(Key, IntToStr(Value));
  133. }
  134. //---------------------------------------------------------------------------
  135. void __fastcall TUsage::Set(const UnicodeString & Key, bool Value)
  136. {
  137. Set(Key, Value ? 1 : 0);
  138. }
  139. //---------------------------------------------------------------------------
  140. UnicodeString __fastcall TUsage::Get(const UnicodeString & Key)
  141. {
  142. TGuard Guard(FCriticalSection);
  143. UnicodeString Result = FValues->Values[Key];
  144. Result.Unique();
  145. return Result;
  146. }
  147. //---------------------------------------------------------------------------
  148. void __fastcall TUsage::UpdateLastReport()
  149. {
  150. Set(L"LastReport", StandardTimestamp());
  151. }
  152. //---------------------------------------------------------------------------
  153. void __fastcall TUsage::Reset()
  154. {
  155. TGuard Guard(FCriticalSection);
  156. UpdateLastReport();
  157. FPeriodCounters.clear();
  158. ResetLastExceptions();
  159. }
  160. //---------------------------------------------------------------------------
  161. void __fastcall TUsage::UpdateCurrentVersion()
  162. {
  163. TGuard Guard(FCriticalSection);
  164. int CompoundVersion = FConfiguration->CompoundVersion;
  165. DebugAssert(ZeroBuildNumber(CompoundVersion) == CompoundVersion);
  166. // ZeroBuildNumber for compatibility with versions that stored build number into the compound version
  167. int PrevVersion = ZeroBuildNumber(StrToIntDef(Get(L"CurrentVersion"), 0));
  168. if (PrevVersion != CompoundVersion)
  169. {
  170. Set(L"Installed", StandardTimestamp());
  171. }
  172. if (PrevVersion != 0)
  173. {
  174. if (PrevVersion < CompoundVersion)
  175. {
  176. Inc(L"Upgrades");
  177. }
  178. else if (PrevVersion > CompoundVersion)
  179. {
  180. Inc(L"Downgrades");
  181. }
  182. if (PrevVersion != CompoundVersion)
  183. {
  184. ResetLastExceptions();
  185. }
  186. }
  187. Set(L"CurrentVersion", CompoundVersion);
  188. }
  189. //---------------------------------------------------------------------------
  190. void __fastcall TUsage::ResetValue(const UnicodeString & Key)
  191. {
  192. int Index = FValues->IndexOfName(Key);
  193. if (Index >= 0)
  194. {
  195. FValues->Delete(Index);
  196. }
  197. }
  198. //---------------------------------------------------------------------------
  199. void __fastcall TUsage::ResetLastExceptions()
  200. {
  201. TGuard Guard(FCriticalSection);
  202. ResetValue(LastInternalExceptionCounter);
  203. ResetValue(LastUpdateExceptionCounter);
  204. }
  205. //---------------------------------------------------------------------------
  206. int __fastcall TUsage::Inc(const UnicodeString & Key, int Increment)
  207. {
  208. int Result;
  209. if (Collect)
  210. {
  211. TGuard Guard(FCriticalSection);
  212. Inc(Key, FPeriodCounters, Increment);
  213. Result = Inc(Key, FLifetimeCounters, Increment);
  214. }
  215. else
  216. {
  217. Result = -1;
  218. }
  219. return Result;
  220. }
  221. //---------------------------------------------------------------------------
  222. int __fastcall TUsage::Inc(const UnicodeString & Key, TCounters & Counters, int Increment)
  223. {
  224. int Result;
  225. TCounters::iterator i = Counters.find(Key);
  226. if (i != Counters.end())
  227. {
  228. i->second += Increment;
  229. Result = i->second;
  230. }
  231. else
  232. {
  233. Counters.insert(std::make_pair(Key, Increment));
  234. Result = Increment;
  235. }
  236. return Result;
  237. }
  238. //---------------------------------------------------------------------------
  239. void __fastcall TUsage::SetMax(const UnicodeString & Key, int Value)
  240. {
  241. if (Collect)
  242. {
  243. TGuard Guard(FCriticalSection);
  244. SetMax(Key, Value, FPeriodCounters);
  245. SetMax(Key, Value, FLifetimeCounters);
  246. }
  247. }
  248. //---------------------------------------------------------------------------
  249. void __fastcall TUsage::IncAndSetMax(const UnicodeString & IncKey, const UnicodeString & MaxKey, int Value)
  250. {
  251. Inc(IncKey, Value);
  252. SetMax(MaxKey, Value);
  253. }
  254. //---------------------------------------------------------------------------
  255. void __fastcall TUsage::SetMax(const UnicodeString & Key, int Value,
  256. TCounters & Counters)
  257. {
  258. TCounters::iterator i = Counters.find(Key);
  259. if (i != Counters.end())
  260. {
  261. if (Value > i->second)
  262. {
  263. i->second = Value;
  264. }
  265. }
  266. else
  267. {
  268. Counters.insert(std::make_pair(Key, Value));
  269. }
  270. }
  271. //---------------------------------------------------------------------------
  272. void __fastcall TUsage::SetCollect(bool value)
  273. {
  274. TGuard Guard(FCriticalSection);
  275. if (Collect != value)
  276. {
  277. FCollect = value;
  278. if (!FCollect)
  279. {
  280. FPeriodCounters.clear();
  281. FLifetimeCounters.clear();
  282. FValues->Clear();
  283. }
  284. else
  285. {
  286. Default();
  287. }
  288. }
  289. }
  290. //---------------------------------------------------------------------------
  291. UnicodeString __fastcall TUsage::Serialize(const UnicodeString & Delimiter, const UnicodeString & Filter) const
  292. {
  293. TGuard Guard(FCriticalSection);
  294. UnicodeString Result;
  295. UnicodeString FilterUpper = Filter.UpperCase();
  296. for (int Index = 0; Index < FValues->Count; Index++)
  297. {
  298. Serialize(Result, FValues->Names[Index], FValues->ValueFromIndex[Index], Delimiter, FilterUpper);
  299. }
  300. Serialize(Result, L"Period", FPeriodCounters, Delimiter, FilterUpper);
  301. Serialize(Result, L"Lifetime", FLifetimeCounters, Delimiter, FilterUpper);
  302. return Result;
  303. }
  304. //---------------------------------------------------------------------------
  305. void __fastcall TUsage::Serialize(
  306. UnicodeString & List, const UnicodeString & Name, const TCounters & Counters,
  307. const UnicodeString & Delimiter, const UnicodeString & FilterUpper) const
  308. {
  309. TCounters::const_iterator i = Counters.begin();
  310. while (i != Counters.end())
  311. {
  312. Serialize(List, Name + i->first, IntToStr(i->second), Delimiter, FilterUpper);
  313. i++;
  314. }
  315. }
  316. //---------------------------------------------------------------------------
  317. void __fastcall TUsage::Serialize(
  318. UnicodeString & List, const UnicodeString & Name, const UnicodeString & Value,
  319. const UnicodeString & Delimiter, const UnicodeString & FilterUpper) const
  320. {
  321. if (FilterUpper.IsEmpty() ||
  322. (Name.UpperCase().Pos(FilterUpper) > 0) ||
  323. (Value.UpperCase().Pos(FilterUpper) > 0))
  324. {
  325. AddToList(List, FORMAT(L"%s=%s", (Name, Value)), Delimiter);
  326. }
  327. }
  328. //---------------------------------------------------------------------------
  329. int __fastcall TUsage::CalculateCounterSize(__int64 Size)
  330. {
  331. const int SizeCounterFactor = 10240;
  332. return (Size <= 0) ? 0 : (Size < SizeCounterFactor ? 1 : static_cast<int>(Size / SizeCounterFactor));
  333. }