Now it is straightforward to fix bug 89, subst: template parameters.
[lhc/web/wiklou.git] / includes / BlockCache.php
1 <?php
2 /**
3 * Contain the blockcache class
4 * @package MediaWiki
5 */
6
7 /**
8 * Object for fast lookup of IP blocks
9 * Represents a memcached value, and in some sense, the entire ipblocks table
10 * @package MediaWiki
11 */
12 class BlockCache
13 {
14 var $mData = false, $mMemcKey;
15
16 function BlockCache( $deferLoad = false, $dbName = '' ) {
17 global $wgDBname;
18
19 if ( $dbName == '' ) {
20 $dbName = $wgDBname;
21 }
22
23 $this->mMemcKey = $dbName.':ipblocks';
24
25 if ( !$deferLoad ) {
26 $this->load();
27 }
28 }
29
30 # Load the blocks from the database and save them to memcached
31 function loadFromDB() {
32 global $wgUseMemCached, $wgMemc;
33 $this->mData = array();
34 # Selecting FOR UPDATE is a convenient way to serialise the memcached and DB operations,
35 # which is necessary even though we don't update the DB
36 if ( $wgUseMemCached ) {
37 Block::enumBlocks( 'wfBlockCacheInsert', '', EB_FOR_UPDATE );
38 $wgMemc->set( $this->mMemcKey, $this->mData, 0 );
39 } else {
40 Block::enumBlocks( 'wfBlockCacheInsert', '' );
41 }
42 }
43
44 # Load the cache from memcached or, if that's not possible, from the DB
45 function load() {
46 global $wgUseMemCached, $wgMemc;
47
48 if ( $this->mData === false) {
49 # Try memcached
50 if ( $wgUseMemCached ) {
51 $this->mData = $wgMemc->get( $this->mMemcKey );
52 }
53
54 if ( !is_array( $this->mData ) ) {
55 $this->loadFromDB();
56 }
57 }
58 }
59
60 # Add a block to the cache
61 function insert( &$block ) {
62 if ( $block->mUser == 0 ) {
63 $nb = $block->getNetworkBits();
64 $ipint = $block->getIntegerAddr();
65 $index = $ipint >> ( 32 - $nb );
66
67 if ( !array_key_exists( $nb, $this->mData ) ) {
68 $this->mData[$nb] = array();
69 }
70
71 $this->mData[$nb][$index] = 1;
72 }
73 }
74
75 # Find out if a given IP address is blocked
76 function get( $ip ) {
77 $this->load();
78 $ipint = ip2long( $ip );
79 $blocked = false;
80
81 foreach ( $this->mData as $networkBits => $blockInts ) {
82 if ( array_key_exists( $ipint >> ( 32 - $networkBits ), $blockInts ) ) {
83 $blocked = true;
84 break;
85 }
86 }
87 if ( $blocked ) {
88 # Clear low order bits
89 if ( $networkBits != 32 ) {
90 $ip .= '/'.$networkBits;
91 $ip = Block::normaliseRange( $ip );
92 }
93 $block = new Block();
94 $block->load( $ip );
95 } else {
96 $block = false;
97 }
98
99 return $block;
100 }
101
102 # Clear the local cache
103 # There was once a clear() to clear memcached too, but I deleted it
104 function clearLocal() {
105 $this->mData = false;
106 }
107 }
108
109 function wfBlockCacheInsert( $block, $tag ) {
110 global $wgBlockCache;
111 $wgBlockCache->insert( $block );
112 }