PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 4.3.0
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v4.3.0
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 5 years ago ArchiveInvalidator.php 5 years ago ArchivePurger.php 5 years ago ArchiveQuery.php 5 years ago ArchiveQueryFactory.php 5 years ago Chunk.php 5 years ago DataCollection.php 5 years ago DataTableFactory.php 5 years ago Parameters.php 5 years ago
Chunk.php
143 lines
1 <?php
2 /**
3 * Matomo - free/libre analytics platform
4 *
5 * @link https://matomo.org
6 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
7 *
8 */
9
10 namespace Piwik\Archive;
11
12 /**
13 * This class is used to split blobs of DataTables into chunks. Each blob used to be stored under one blob in the
14 * archive table. For better efficiency we do now combine multiple DataTable into one blob entry.
15 *
16 * Chunks are identified by having the recordName $recordName_chunk_0_99, $recordName_chunk_100_199 (this chunk stores
17 * the subtable 100-199).
18 */
19 class Chunk
20 {
21 const ARCHIVE_APPENDIX_SUBTABLES = 'chunk';
22 const NUM_TABLES_IN_CHUNK = 100;
23
24 /**
25 * Gets the record name to use for a given tableId/subtableId.
26 *
27 * @param string $recordName eg 'Actions_ActionsUrl'
28 * @param int $tableId eg '5' for tableId '5'
29 * @return string eg 'Actions_ActionsUrl_chunk_0_99' as the table should be stored under this blob id.
30 */
31 public function getRecordNameForTableId($recordName, $tableId)
32 {
33 $chunk = (floor($tableId / self::NUM_TABLES_IN_CHUNK));
34 $start = $chunk * self::NUM_TABLES_IN_CHUNK;
35 $end = $start + self::NUM_TABLES_IN_CHUNK - 1;
36
37 return $recordName . $this->getAppendix() . $start . '_' . $end;
38 }
39
40 /**
41 * Moves the given blobs into chunks and assigns a proper record name containing the chunk number.
42 *
43 * @param string $recordName The original archive record name, eg 'Actions_ActionsUrl'
44 * @param array $blobs An array containing a mapping of tableIds to blobs. Eg array(0 => 'blob', 1 => 'subtableBlob', ...)
45 * @return array An array where each blob is moved into a chunk, indexed by recordNames.
46 * eg array('Actions_ActionsUrl_chunk_0_99' => array(0 => 'blob', 1 => 'subtableBlob', ...),
47 * 'Actions_ActionsUrl_chunk_100_199' => array(...))
48 */
49 public function moveArchiveBlobsIntoChunks($recordName, $blobs)
50 {
51 $chunks = array();
52
53 foreach ($blobs as $tableId => $blob) {
54 $name = $this->getRecordNameForTableId($recordName, $tableId);
55
56 if (!array_key_exists($name, $chunks)) {
57 $chunks[$name] = array();
58 }
59
60 $chunks[$name][$tableId] = $blob;
61 }
62
63 return $chunks;
64 }
65
66 /**
67 * Detects whether a recordName like 'Actions_ActionUrls_chunk_0_99' or 'Actions_ActionUrls' belongs to a
68 * chunk or not.
69 *
70 * To be a valid recordName that belongs to a chunk it must end with '_chunk_NUMERIC_NUMERIC'.
71 *
72 * @param string $recordName
73 * @return bool
74 */
75 public function isRecordNameAChunk($recordName)
76 {
77 $posAppendix = $this->getEndPosOfChunkAppendix($recordName);
78
79 if (false === $posAppendix) {
80 return false;
81 }
82
83 // will contain "0_99" of "chunk_0_99"
84 $blobId = substr($recordName, $posAppendix);
85
86 return $this->isChunkRange($blobId);
87 }
88
89 private function isChunkRange($blobId)
90 {
91 $blobId = explode('_', $blobId);
92
93 return 2 === count($blobId) && is_numeric($blobId[0]) && is_numeric($blobId[1]);
94 }
95
96 /**
97 * When having a record like 'Actions_ActionUrls_chunk_0_99" it will return the raw recordName 'Actions_ActionUrls'.
98 *
99 * @param string $recordName
100 * @return string
101 */
102 public function getRecordNameWithoutChunkAppendix($recordName)
103 {
104 if (!$this->isRecordNameAChunk($recordName)) {
105 return $recordName;
106 }
107
108 $posAppendix = $this->getStartPosOfChunkAppendix($recordName);
109
110 if (false === $posAppendix) {
111 return $recordName;
112 }
113
114 return substr($recordName, 0, $posAppendix);
115 }
116
117 /**
118 * Returns the string that is appended to the original record name. This appendix identifes a record name is a
119 * chunk.
120 * @return string
121 */
122 public function getAppendix()
123 {
124 return '_' . self::ARCHIVE_APPENDIX_SUBTABLES . '_';
125 }
126
127 private function getStartPosOfChunkAppendix($recordName)
128 {
129 return strpos($recordName, $this->getAppendix());
130 }
131
132 private function getEndPosOfChunkAppendix($recordName)
133 {
134 $pos = strpos($recordName, $this->getAppendix());
135
136 if ($pos === false) {
137 return false;
138 }
139
140 return $pos + strlen($this->getAppendix());
141 }
142 }
143