PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / trunk
Matomo Analytics – Powerful, Privacy-First Insights for WordPress vtrunk
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / core / Archive / Chunk.php
matomo / app / core / Archive Last commit date
ArchiveInvalidator 1 year ago ArchiveInvalidator.php 1 month ago ArchivePurger.php 1 month ago ArchiveQuery.php 1 year ago ArchiveQueryFactory.php 1 year ago ArchiveState.php 1 year ago Chunk.php 1 year ago DataCollection.php 1 month ago DataTableFactory.php 1 month ago Parameters.php 2 years ago
Chunk.php
120 lines
1 <?php
2
3 /**
4 * Matomo - free/libre analytics platform
5 *
6 * @link https://matomo.org
7 * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
8 */
9 namespace Piwik\Archive;
10
11 /**
12 * This class is used to split blobs of DataTables into chunks. Each blob used to be stored under one blob in the
13 * archive table. For better efficiency we do now combine multiple DataTable into one blob entry.
14 *
15 * Chunks are identified by having the recordName $recordName_chunk_0_99, $recordName_chunk_100_199 (this chunk stores
16 * the subtable 100-199).
17 */
18 class Chunk
19 {
20 public const ARCHIVE_APPENDIX_SUBTABLES = 'chunk';
21 public const NUM_TABLES_IN_CHUNK = 100;
22 /**
23 * Gets the record name to use for a given tableId/subtableId.
24 *
25 * @param string $recordName eg 'Actions_ActionsUrl'
26 * @param int $tableId eg '5' for tableId '5'
27 * @return string eg 'Actions_ActionsUrl_chunk_0_99' as the table should be stored under this blob id.
28 */
29 public function getRecordNameForTableId($recordName, $tableId)
30 {
31 $chunk = floor($tableId / self::NUM_TABLES_IN_CHUNK);
32 $start = $chunk * self::NUM_TABLES_IN_CHUNK;
33 $end = $start + self::NUM_TABLES_IN_CHUNK - 1;
34 return $recordName . $this->getAppendix() . $start . '_' . $end;
35 }
36 /**
37 * Moves the given blobs into chunks and assigns a proper record name containing the chunk number.
38 *
39 * @param string $recordName The original archive record name, eg 'Actions_ActionsUrl'
40 * @param array $blobs An array containing a mapping of tableIds to blobs. Eg array(0 => 'blob', 1 => 'subtableBlob', ...)
41 * @return array An array where each blob is moved into a chunk, indexed by recordNames.
42 * eg array('Actions_ActionsUrl_chunk_0_99' => array(0 => 'blob', 1 => 'subtableBlob', ...),
43 * 'Actions_ActionsUrl_chunk_100_199' => array(...))
44 */
45 public function moveArchiveBlobsIntoChunks($recordName, $blobs)
46 {
47 $chunks = array();
48 foreach ($blobs as $tableId => $blob) {
49 $name = $this->getRecordNameForTableId($recordName, $tableId);
50 if (!array_key_exists($name, $chunks)) {
51 $chunks[$name] = array();
52 }
53 $chunks[$name][$tableId] = $blob;
54 }
55 return $chunks;
56 }
57 /**
58 * Detects whether a recordName like 'Actions_ActionUrls_chunk_0_99' or 'Actions_ActionUrls' belongs to a
59 * chunk or not.
60 *
61 * To be a valid recordName that belongs to a chunk it must end with '_chunk_NUMERIC_NUMERIC'.
62 *
63 * @param string $recordName
64 * @return bool
65 */
66 public function isRecordNameAChunk($recordName)
67 {
68 $posAppendix = $this->getEndPosOfChunkAppendix($recordName);
69 if (\false === $posAppendix) {
70 return \false;
71 }
72 // will contain "0_99" of "chunk_0_99"
73 $blobId = substr($recordName, $posAppendix);
74 return $this->isChunkRange($blobId);
75 }
76 private function isChunkRange($blobId)
77 {
78 $blobId = explode('_', $blobId);
79 return 2 === count($blobId) && is_numeric($blobId[0]) && is_numeric($blobId[1]);
80 }
81 /**
82 * When having a record like 'Actions_ActionUrls_chunk_0_99" it will return the raw recordName 'Actions_ActionUrls'.
83 *
84 * @param string $recordName
85 * @return string
86 */
87 public function getRecordNameWithoutChunkAppendix($recordName)
88 {
89 if (!$this->isRecordNameAChunk($recordName)) {
90 return $recordName;
91 }
92 $posAppendix = $this->getStartPosOfChunkAppendix($recordName);
93 if (\false === $posAppendix) {
94 return $recordName;
95 }
96 return substr($recordName, 0, $posAppendix);
97 }
98 /**
99 * Returns the string that is appended to the original record name. This appendix identifes a record name is a
100 * chunk.
101 * @return string
102 */
103 public function getAppendix()
104 {
105 return '_' . self::ARCHIVE_APPENDIX_SUBTABLES . '_';
106 }
107 private function getStartPosOfChunkAppendix($recordName)
108 {
109 return strpos($recordName, $this->getAppendix());
110 }
111 private function getEndPosOfChunkAppendix($recordName)
112 {
113 $pos = strpos($recordName, $this->getAppendix());
114 if ($pos === \false) {
115 return \false;
116 }
117 return $pos + strlen($this->getAppendix());
118 }
119 }
120