Merge "Title: Title::getSubpage should not lose the interwiki prefix"
[lhc/web/wiklou.git] / includes / libs / objectcache / MemcachedBagOStuff.php
1 <?php
2 /**
3 * Base class for memcached clients.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 * @file
21 * @ingroup Cache
22 */
23
24 /**
25 * Base class for memcached clients.
26 *
27 * @ingroup Cache
28 */
29 abstract class MemcachedBagOStuff extends BagOStuff {
30 function __construct( array $params ) {
31 parent::__construct( $params );
32
33 $this->attrMap[self::ATTR_SYNCWRITES] = self::QOS_SYNCWRITES_BE; // unreliable
34 $this->segmentationSize = $params['maxPreferedKeySize'] ?? 917504; // < 1MiB
35 }
36
37 /**
38 * Construct a cache key.
39 *
40 * @since 1.27
41 * @param string $keyspace
42 * @param array $args
43 * @return string
44 */
45 public function makeKeyInternal( $keyspace, $args ) {
46 // Memcached keys have a maximum length of 255 characters. From that,
47 // subtract the number of characters we need for the keyspace and for
48 // the separator character needed for each argument. To handle some
49 // custom prefixes used by thing like WANObjectCache, limit to 205.
50 $charsLeft = 205 - strlen( $keyspace ) - count( $args );
51
52 $args = array_map(
53 function ( $arg ) use ( &$charsLeft ) {
54 $arg = strtr( $arg, ' ', '_' );
55
56 // Make sure %, #, and non-ASCII chars are escaped
57 $arg = preg_replace_callback(
58 '/[^\x21-\x22\x24\x26-\x39\x3b-\x7e]+/',
59 function ( $m ) {
60 return rawurlencode( $m[0] );
61 },
62 $arg
63 );
64
65 // 33 = 32 characters for the MD5 + 1 for the '#' prefix.
66 if ( $charsLeft > 33 && strlen( $arg ) > $charsLeft ) {
67 $arg = '#' . md5( $arg );
68 }
69
70 $charsLeft -= strlen( $arg );
71 return $arg;
72 },
73 $args
74 );
75
76 if ( $charsLeft < 0 ) {
77 return $keyspace . ':BagOStuff-long-key:##' . md5( implode( ':', $args ) );
78 }
79
80 return $keyspace . ':' . implode( ':', $args );
81 }
82
83 /**
84 * Ensure that a key is safe to use (contains no control characters and no
85 * characters above the ASCII range.)
86 *
87 * @param string $key
88 * @return string
89 * @throws Exception
90 */
91 public function validateKeyEncoding( $key ) {
92 if ( preg_match( '/[^\x21-\x7e]+/', $key ) ) {
93 throw new Exception( "Key contains invalid characters: $key" );
94 }
95 return $key;
96 }
97
98 /**
99 * TTLs higher than 30 days will be detected as absolute TTLs
100 * (UNIX timestamps), and will result in the cache entry being
101 * discarded immediately because the expiry is in the past.
102 * Clamp expires >30d at 30d, unless they're >=1e9 in which
103 * case they are likely to really be absolute (1e9 = 2011-09-09)
104 * @param int $expiry
105 * @return int
106 */
107 function fixExpiry( $expiry ) {
108 if ( $expiry > 2592000 && $expiry < 1000000000 ) {
109 $expiry = 2592000;
110 }
111 return (int)$expiry;
112 }
113 }