Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. // GBUdb.inline.hpp
  2. //
  3. // (C) Copyright 2006 - 2009 ARM Research Labs, LLC
  4. // See www.armresearch.com for the copyright terms.
  5. //
  6. // See GBUdb.hpp for details & notes.
  7. // This file contains inline implementations.
  8. //// GBUdbRecord Implementations ///////////////////////////////////////////////
  9. inline GBUdbRecord::GBUdbRecord() : // Initialize a new GBUdbRecord
  10. RawData(0) { // to ZERO.
  11. }
  12. inline GBUdbFlag GBUdbRecord::Flag() { // Return the flags.
  13. return (GBUdbFlag) (RawData & GBUdbFlagsMask); // Isolate the flags from the data & return.
  14. }
  15. inline GBUdbFlag GBUdbRecord::Flag(GBUdbFlag f) { // Set the flags.
  16. RawData = RawData & (~GBUdbFlagsMask); // Strip the current flags from RawData.
  17. RawData = RawData | f; // Put the new flags into RawData.
  18. return (GBUdbFlag) (RawData & GBUdbFlagsMask); // Return the flags now in RawData.
  19. }
  20. inline unsigned int GBUdbRecord::Good() { // Return the Good count.
  21. return ((RawData & GBUdbGoodMask) >> GBUdbGoodShift); // Isolate & shift the good count, return.
  22. }
  23. inline unsigned int GBUdbRecord::Good(unsigned int g) { // Set the good count.
  24. RawData = RawData & (~GBUdbGoodMask); // Strip the current good count.
  25. g = g & GBUdbLimit; // Make g safe (within bitfield limit).
  26. RawData = RawData | (g << GBUdbGoodShift); // Shift & combine g with RawData.
  27. return g; // Return the safe g value.
  28. }
  29. inline unsigned int GBUdbRecord::Bad() { // Get the bad count.
  30. return (RawData & GBUdbBadMask); // Isolate the bad data and return.
  31. }
  32. inline unsigned int GBUdbRecord::Bad(unsigned int b) { // Set the bad count.
  33. RawData = RawData & (~GBUdbBadMask); // Strip out the current bad count.
  34. b = b & GBUdbLimit; // Make b safe (strip any extra bits).
  35. RawData = RawData | b; // Combine RawData with the safe b.
  36. return b; // return the safe b.
  37. }
  38. inline unsigned int GBUdbRecord::addGood(unsigned int g) { // Add to the good count & normalize.
  39. unsigned int G = Good(); // Get the good.
  40. unsigned int B = Bad(); // Get the bad.
  41. G = G + g; // Add the new g to the good.
  42. while(G > GBUdbLimit) { // If normalization is required
  43. G = G >> 1; // then reduce the new good
  44. B = B >> 1; // and bad counts by half
  45. } // until things are normalized.
  46. Good(G); // Then go ahead and set the
  47. Bad(B); // new value(s) into place.
  48. return G; // Return the new good count.
  49. }
  50. inline unsigned int GBUdbRecord::addBad(unsigned int b) { // Add to the bad count & normalize.
  51. unsigned int G = Good(); // Get the good.
  52. unsigned int B = Bad(); // Get the bad.
  53. B = B + b; // Add the new b to the bad.
  54. while(B > GBUdbLimit) { // If normalization is required
  55. G = G >> 1; // then reduce the new good
  56. B = B >> 1; // and bad counts by half
  57. } // until things are normalized.
  58. Good(G); // Then go ahead and set the
  59. Bad(B); // new value(s) into place.
  60. return B; // Return the new good count.
  61. }
  62. inline GBUdbRecord& GBUdbRecord::integrate(GBUdbRecord& A, int LocalWeight, int RemoteWeight) { // Integrate A
  63. unsigned int Gl = Good(); // Get the good and
  64. unsigned int Bl = Bad(); // bad counts from
  65. unsigned int Gr = A.Good(); // the local and
  66. unsigned int Br = A.Bad(); // remote records.
  67. Gl = (Gl * LocalWeight) + (Gr * RemoteWeight); // Combine the Good and
  68. Bl = (Bl * LocalWeight) + (Br * RemoteWeight); // bad counts using the weights.
  69. while(Gl > GBUdbLimit || Bl > GBUdbLimit) { // Normalize the counts by
  70. Gl = Gl >> 1; // dividing both in half until
  71. Bl = Bl >> 1; // they are both within limits.
  72. }
  73. Good(Gl); // Then set the new Good
  74. Bad(Bl); // and bad values and return
  75. return *this; // this object.
  76. }
  77. inline GBUdbIndex GBUdbRecord::Index() { // Read the record as an index.
  78. return (GBUdbIndex) RawData;
  79. }
  80. inline GBUdbIndex GBUdbRecord::Index(GBUdbIndex i) { // Write the index value of the record.
  81. RawData = (unsigned int) i;
  82. return (GBUdbIndex) RawData;
  83. }
  84. // Probability is about the ratio of a given event to the total events.
  85. // In this case, positive probabilities indicate a tendency toward spam and
  86. // negative probabilities indicate a tendency toward ham.
  87. inline double GBUdbRecord::Probability() { // Calculate the probability of spam
  88. unsigned int G = Good(); // Get the good and
  89. unsigned int B = Bad(); // bad counts and
  90. double P = 0.0; // grab a double to hold P.
  91. if(0 == B + G) { // If we have no counts yet
  92. return P; // then return a zero probability.
  93. } // If we have counts lets do the math.
  94. P = ((double) B - (double) G) / ((double) B + (double) G); // Calculate the differential
  95. return P; // probability and return it.
  96. }
  97. // The confidence we have in a probability is related to the number of samples
  98. // that are present. We calculate the confidence on a logarithmic scale between
  99. // one sample and half the maximum number by category (good or bad) because
  100. // during condensation all counts may be reduced by half. That is, a 100%
  101. // confidence is achieved when a record contains a total of half the maximum
  102. // number of counts for a single category.
  103. inline double GBUdbRecord::Confidence() { // Calculate our confidence in prob.
  104. unsigned int Total = Good() + Bad(); // What is our total count of samples.
  105. if(0 == Total) return 0.0; // No samples is no confidence.
  106. double Confidence = (log((double)Total) / log((double)(GBUdbLimit/2))); // Calculate on a log scale.
  107. if(1.0 < Confidence) Confidence = 1.0; // Max confidence is 1.0.
  108. return Confidence; // Return the result.
  109. }
  110. //// GBUdbDataSet Inline Methods ///////////////////////////////////////////////
  111. inline GBUdbIndex GBUdbDataset::ixIPCount() { // Index of the IP count for this db.
  112. return MyArraySize + GBUdbIPCountOffset; // Return the offest from the end.
  113. }
  114. inline GBUdbIndex GBUdbDataset::ixNextFreeNode() { // Index of the Next Free Node.
  115. return MyArraySize + GBUdbNextFreeNodeOffset; // Return the offset from the end.
  116. }
  117. inline GBUdbIndex GBUdbDataset::newNodeRoot() { // Allocates a new node, returns offset.
  118. if(0 >= FreeNodes()) { // Check that we have free nodes to
  119. throw NoFreeNodes(); // allocate. If we don't then throw!
  120. }
  121. GBUdbIndex NewNode = DataArray[ixNextFreeNode()].Index(); // Grab the next new node index.
  122. DataArray[ixNextFreeNode()].Index(NewNode + GBUdbRecordsPerNode); // Move the allocator up a node.
  123. return NewNode; // Return the allocated node.
  124. }
  125. inline int GBUdbDataset::ArraySize() { // Return the current Array Size.
  126. return MyArraySize;
  127. }
  128. inline int GBUdbDataset::FreeNodes() { // Return the number of free nodes.
  129. int FreeRecords = MyArraySize - DataArray[ixNextFreeNode()].RawData; // Find the number of records left.
  130. int FreeNodes = (FreeRecords / GBUdbRecordsPerNode) - 1; // Convert to nodes and subtract the
  131. return FreeNodes; // control node, the return the value.
  132. }
  133. inline int GBUdbDataset::IPCount() { // Return the IP count.
  134. return DataArray[ixIPCount()].RawData;
  135. }
  136. inline int GBUdbDataset::increaseIPCount() { // When we add an IP to the db.
  137. return DataArray[ixIPCount()].RawData++; // Increment and return the IP count.
  138. }
  139. inline int GBUdbDataset::decreaseIPCount() { // When we drop an IP from the db.
  140. return DataArray[ixIPCount()].RawData--; // Decrement and return the IP count.
  141. }
  142. inline const char* GBUdbDataset::FileName() { // get the file name.
  143. return MyFileName.c_str();
  144. }
  145. inline unsigned int GBUdbDataset::EncodedMatch(unsigned int IP) { // Encode an IP as a MatchRecord header.
  146. return GBUdbMatchEntryBit | (IP & GBUdbMatchDataMask); // Use the MatchEntery bit and as much
  147. } // of the remaining IP data as possible.
  148. inline bool GBUdbDataset::isMatch(GBUdbIndex I) { // True if record at I is a match record.
  149. return (0 != (DataArray[I].RawData & GBUdbMatchEntryBit)); // Get the raw data and check for the bit.
  150. }
  151. inline bool GBUdbDataset::isMatch(GBUdbIndex I, unsigned int IP) { // True if record at I is a match for IP.
  152. return (DataArray[I].RawData == EncodedMatch(IP));
  153. }
  154. inline GBUdbRecord& GBUdbDataset::MatchedData(GBUdbIndex I) { // Returns the data for the match at I.
  155. return DataArray[I + 1]; // Since I points to the match record we
  156. } // return the record immedately after it.
  157. inline GBUdbRecord& GBUdbDataset::SafeUnknownRecord() { // Clears and returns the Safe record.
  158. MySafeUnknownRecord.RawData = GBUdbUnknown; // Clear the SafeUnknownRecord and
  159. return MySafeUnknownRecord; // return it as the result.
  160. }
  161. inline GBUdbIndex GBUdbDataset::ixMatchListRoot() { // Index of the Match List Root Index.
  162. return MyArraySize + GBUdbMatchListOffset;
  163. }
  164. inline void GBUdbDataset::increaseIPCountIfNew(GBUdbRecord& R) { // If R is GBUdbUnknown, IncreaseIPCount.
  165. if(GBUdbUnknown == R.RawData) { increaseIPCount(); } // If new, increase the IP count.
  166. }
  167. inline unsigned int GBUdbDataset::remapIP00toFF(unsigned int IP) { // Remaps final octet 00 to FF if needed.
  168. const int LowOctetMask = 0x000000FF; // Mask for seeing the low octet.
  169. if(0 == (IP & LowOctetMask)) { // If the lowest octet is 00 then
  170. return (IP | LowOctetMask); // change it to FF and return.
  171. } // If the lowest octet is something else
  172. return IP; // then return the IP as is.
  173. }
  174. inline void GBUdbDataset::deleteMatchAt(GBUdbIndex I) { // Recalls MatchRecord at I for reuse.
  175. GBUdbIndex Next = DataArray[ixMatchListRoot()].Index(); // Find the current allocation list root.
  176. DataArray[I].RawData = (Next | GBUdbMatchUnusedBit); // Point the current match to that root.
  177. DataArray[I+1].RawData = GBUdbUnknown; // Clean out any data the match had.
  178. DataArray[ixMatchListRoot()].Index(I); // Make this record the list root.
  179. }
  180. //// GBUdb Implementations /////////////////////////////////////////////////////
  181. inline GBUdb::GBUdb() : // Construct the db as new.
  182. PostsCounter(0) { // No posts yet.
  183. MyDataset = new GBUdbDataset(NULL); // Construct with no file name.
  184. }
  185. inline GBUdb::GBUdb(const char* FileName) : // Construct the db from a file.
  186. PostsCounter(0) { // No Posts yet.
  187. MyDataset = new GBUdbDataset(FileName); // Load the data set by name.
  188. }
  189. inline GBUdb::~GBUdb() { // Destroy the db object.
  190. if(NULL != MyDataset) { // Save first if we can.
  191. MyDataset->save();
  192. delete MyDataset;
  193. }
  194. }
  195. inline const char* GBUdb::FileName() { // Return the file name.
  196. return MyDataset->FileName();
  197. }
  198. inline const char* GBUdb::FileName(const char* NewName) { // Set/Change the file name.
  199. return MyDataset->FileName(NewName);
  200. }
  201. inline void GBUdb::save() { // Save the data.
  202. ScopeMutex JustMe(MyMutex); // Lock the mutex during this operation.
  203. MyDataset->save(); // Save the dataset.
  204. PostsCounter = 0; // Reset the posts counter.
  205. }
  206. inline void GBUdb::load() { // Load the data.
  207. ScopeMutex JustMe(MyMutex); // Lock the mutex during this operation.
  208. MyDataset->load(); // Load the dataset.
  209. }
  210. inline GBUdbRecord GBUdb::addGood(unsigned int IP, int i) { // Count an IP as good.
  211. ScopeMutex JustMe(MyMutex); // Lock the mutex during this operation.
  212. ++PostsCounter; // Count this as a post.
  213. GBUdbRecord& X = MyDataset->invokeRecord(IP); // Invoke the record.
  214. unsigned int C = X.addGood(i); // Add a count to the good side.
  215. recordAlertFor(IP, X ,C); // Record an alert if required.
  216. return X; // Return a copy for analysis.
  217. }
  218. inline GBUdbRecord GBUdb::addBad(unsigned int IP, int i) { // Count an IP as bad.
  219. ScopeMutex JustMe(MyMutex); // Lock the mutex during this operation.
  220. ++PostsCounter; // Count this as a post.
  221. GBUdbRecord& X = MyDataset->invokeRecord(IP); // Invoke the reocrd.
  222. unsigned int C = X.addBad(i); // Add a count to the bad side.
  223. recordAlertFor(IP, X, C); // Record an alert if required.
  224. return X; // Return a copy for analysis.
  225. }
  226. inline GBUdbRecord GBUdb::setGood(unsigned int IP) { // Set the flag to Good for this IP.
  227. ScopeMutex JustMe(MyMutex); // Lock the mutex during this operation.
  228. GBUdbRecord& X = MyDataset->invokeRecord(IP); // Invoke the reocrd.
  229. X.Flag(Good); // Set the Good flag.
  230. return X; // Return a copy for analysis.
  231. }
  232. inline GBUdbRecord GBUdb::setBad(unsigned int IP) { // Set the flag to Bad for this IP.
  233. ScopeMutex JustMe(MyMutex); // Lock the mutex during this operation.
  234. GBUdbRecord& X = MyDataset->invokeRecord(IP); // Invoke the reocrd.
  235. X.Flag(Bad); // Set the Bad flag.
  236. return X; // Return a copy for analysis.
  237. }
  238. inline GBUdbRecord GBUdb::setUgly(unsigned int IP) { // Set the flag to Ugly for this IP.
  239. ScopeMutex JustMe(MyMutex); // Lock the mutex during this operation.
  240. GBUdbRecord& X = MyDataset->invokeRecord(IP); // Invoke the reocrd.
  241. X.Flag(Ugly); // Set the Ugly flag.
  242. return X; // Return a copy for analysis.
  243. }
  244. inline GBUdbRecord GBUdb::setIgnore(unsigned int IP) { // Set the flag to Ignore for this IP.
  245. ScopeMutex JustMe(MyMutex); // Lock the mutex during this operation.
  246. GBUdbRecord& X = MyDataset->invokeRecord(IP); // Invoke the reocrd.
  247. X.Flag(Ignore); // Set the Ignore flag.
  248. return X; // Return a copy for analysis.
  249. }
  250. inline GBUdbRecord GBUdb::getRecord(unsigned int IP) { // Retrieve an IP record.
  251. ScopeMutex JustMe(MyMutex); // Lock the mutex during this operation.
  252. GBUdbRecord& X = MyDataset->readRecord(IP); // ReadOnly the reocrd.
  253. return X; // Return a copy for analysis.
  254. }
  255. inline GBUdbRecord GBUdb::setRecord(unsigned int IP, GBUdbRecord& R) { // Store an IP record.
  256. ScopeMutex JustMe(MyMutex); // Lock the mutex during this operation.
  257. GBUdbRecord& X = MyDataset->invokeRecord(IP); // Invoke the reocrd.
  258. X = R; // Overwrite X with R.
  259. return X; // Return a copy for analysis.
  260. }
  261. inline GBUdbRecord GBUdb::adjustCounts(unsigned int IP, GBUdbRecord& R) { // Adds counts from R to record for IP.
  262. ScopeMutex JustMe(MyMutex); // Lock the data for this operation.
  263. GBUdbRecord& X = MyDataset->invokeRecord(IP); // Locate the record in the data.
  264. X.Bad(X.Bad() + R.Bad()); // Add the reflected adjustments
  265. X.Good(X.Good() + R.Good()); // to the good and bad counts.
  266. return X; // Return a copy for analysis.
  267. }
  268. inline bool GBUdb::dropRecord(unsigned int IP) { // Drop an IP record.
  269. ScopeMutex JustMe(MyMutex); // Lock the mutex during this operation.
  270. return MyDataset->dropRecord(IP); // Pass on this call to our dataset.
  271. }
  272. inline int GBUdb::IPCount() { // Number of IPs stored.
  273. ScopeMutex JustMe(MyMutex);
  274. return MyDataset->IPCount();
  275. }
  276. inline int GBUdb::Size() { // Size of GBUdb in bytes.
  277. ScopeMutex JustMe(MyMutex); // Lock the mutex during this operation.
  278. return MyDataset->ArraySize() * sizeof(GBUdbRecord); // Total records converted to bytes.
  279. }
  280. inline double GBUdb::Utilization() { // Utilization (percent).
  281. ScopeMutex JustMe(MyMutex); // Lock the mutex during this operation.
  282. int TotalRecords = MyDataset->ArraySize(); // Calculate the total number of records.
  283. int FreeRecords = MyDataset->FreeNodes() * GBUdbRecordsPerNode; // Calculate the number of unused records.
  284. int UsedRecords = TotalRecords - FreeRecords; // Calcualte the number of used records.
  285. return // Calculate and return as double...
  286. ((double) UsedRecords) * 100.0 / // (Used Records * 100) / (TotalRecords)
  287. ((double) TotalRecords);
  288. }
  289. inline int GBUdb::Posts() { // Number of posts since last snapshot.
  290. int CurrentCount = PostsCounter; // Grab the current posts count.
  291. return CurrentCount; // Return the count we had.
  292. }