Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
/*
3
 * Copyright 2008 Google Inc.
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 *     http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
 
18
if (!class_exists('Google_Client')) {
19
  require_once dirname(__FILE__) . '/../autoload.php';
20
}
21
 
22
/**
23
 * A persistent storage class based on the memcache, which is not
24
 * really very persistent, as soon as you restart your memcache daemon
25
 * the storage will be wiped.
26
 *
27
 * Will use either the memcache or memcached extensions, preferring
28
 * memcached.
29
 *
30
 * @author Chris Chabot <chabotc@google.com>
31
 */
32
#[AllowDynamicProperties]
33
class Google_Cache_Memcache extends Google_Cache_Abstract
34
{
35
  private $connection = false;
36
  private $mc = false;
37
  private $host;
38
  private $port;
39
 
40
  /**
41
   * @var Google_Client the current client
42
   */
43
  private $client;
44
 
45
  public function __construct(Google_Client $client)
46
  {
47
    if (!function_exists('memcache_connect') && !class_exists("Memcached")) {
48
      $error = "Memcache functions not available";
49
 
50
      $client->getLogger()->error($error);
51
      throw new Google_Cache_Exception($error);
52
    }
53
 
54
    $this->client = $client;
55
 
56
    if ($client->isAppEngine()) {
57
      // No credentials needed for GAE.
58
      $this->mc = new Memcached();
59
      $this->connection = true;
60
    } else {
61
      $this->host = $client->getClassConfig($this, 'host');
62
      $this->port = $client->getClassConfig($this, 'port');
63
      if (empty($this->host) || (empty($this->port) && (string) $this->port != "0")) {
64
        $error = "You need to supply a valid memcache host and port";
65
 
66
        $client->getLogger()->error($error);
67
        throw new Google_Cache_Exception($error);
68
      }
69
    }
70
  }
71
 
72
  /**
73
   * @inheritDoc
74
   */
75
  public function get($key, $expiration = false)
76
  {
77
    $this->connect();
78
    $ret = false;
79
    if ($this->mc) {
80
      $ret = $this->mc->get($key);
81
    } else {
82
      $ret = memcache_get($this->connection, $key);
83
    }
84
    if ($ret === false) {
85
      $this->client->getLogger()->debug(
86
          'Memcache cache miss',
87
          array('key' => $key)
88
      );
89
      return false;
90
    }
91
    if (is_numeric($expiration) && (time() - $ret['time'] > $expiration)) {
92
      $this->client->getLogger()->debug(
93
          'Memcache cache miss (expired)',
94
          array('key' => $key, 'var' => $ret)
95
      );
96
      $this->delete($key);
97
      return false;
98
    }
99
 
100
    $this->client->getLogger()->debug(
101
        'Memcache cache hit',
102
        array('key' => $key, 'var' => $ret)
103
    );
104
 
105
    return $ret['data'];
106
  }
107
 
108
  /**
109
   * @inheritDoc
110
   * @param string $key
111
   * @param string $value
112
   * @throws Google_Cache_Exception
113
   */
114
  public function set($key, $value)
115
  {
116
    $this->connect();
117
    // we store it with the cache_time default expiration so objects will at
118
    // least get cleaned eventually.
119
    $data = array('time' => time(), 'data' => $value);
120
    $rc = false;
121
    if ($this->mc) {
122
      $rc = $this->mc->set($key, $data);
123
    } else {
124
      $rc = memcache_set($this->connection, $key, $data, false);
125
    }
126
    if ($rc == false) {
127
      $this->client->getLogger()->error(
128
          'Memcache cache set failed',
129
          array('key' => $key, 'var' => $data)
130
      );
131
 
132
      throw new Google_Cache_Exception("Couldn't store data in cache");
133
    }
134
 
135
    $this->client->getLogger()->debug(
136
        'Memcache cache set',
137
        array('key' => $key, 'var' => $data)
138
    );
139
  }
140
 
141
  /**
142
   * @inheritDoc
143
   * @param String $key
144
   */
145
  public function delete($key)
146
  {
147
    $this->connect();
148
    if ($this->mc) {
149
      $this->mc->delete($key, 0);
150
    } else {
151
      memcache_delete($this->connection, $key, 0);
152
    }
153
 
154
    $this->client->getLogger()->debug(
155
        'Memcache cache delete',
156
        array('key' => $key)
157
    );
158
  }
159
 
160
  /**
161
   * Lazy initialiser for memcache connection. Uses pconnect for to take
162
   * advantage of the persistence pool where possible.
163
   */
164
  private function connect()
165
  {
166
    if ($this->connection) {
167
      return;
168
    }
169
 
170
    if (class_exists("Memcached")) {
171
      $this->mc = new Memcached();
172
      $this->mc->addServer($this->host, $this->port);
173
       $this->connection = true;
174
    } else {
175
      $this->connection = memcache_pconnect($this->host, $this->port);
176
    }
177
 
178
    if (! $this->connection) {
179
      $error = "Couldn't connect to memcache server";
180
 
181
      $this->client->getLogger()->error($error);
182
      throw new Google_Cache_Exception($error);
183
    }
184
  }
185
}