~ubuntu-branches/ubuntu/wily/php-horde-cache/wily

« back to all changes in this revision

Viewing changes to Horde_Cache-2.2.1/lib/Horde/Cache/Storage/Mongo.php

  • Committer: Package Import Robot
  • Author(s): Mathieu Parent
  • Date: 2013-08-10 19:53:57 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20130810195357-empm8uhqxxb7vk5n
Tags: 2.2.1-1
New upstream version 2.2.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * Copyright 2013 Horde LLC (http://www.horde.org/)
 
4
 *
 
5
 * See the enclosed file COPYING for license information (LGPL). If you
 
6
 * did not receive this file, see http://www.horde.org/licenses/lgpl21.
 
7
 *
 
8
 * @category  Horde
 
9
 * @copyright 2013 Horde LLC
 
10
 * @license   http://www.horde.org/licenses/lgpl21 LGPL 2.1
 
11
 * @package   Cache
 
12
 */
 
13
 
 
14
/**
 
15
 * Cache storage in a MongoDB database.
 
16
 *
 
17
 * @author    Michael Slusarz <slusarz@horde.org>
 
18
 * @category  Horde
 
19
 * @copyright 2013 Horde LLC
 
20
 * @license   http://www.horde.org/licenses/lgpl21 LGPL 2.1
 
21
 * @package   Cache
 
22
 */
 
23
class Horde_Cache_Storage_Mongo extends Horde_Cache_Storage_Base
 
24
{
 
25
    /* Field names. */
 
26
    const CID = 'cid';
 
27
    const DATA = 'data';
 
28
    const EXPIRE = 'expire';
 
29
    const TIMESTAMP = 'ts';
 
30
 
 
31
    /**
 
32
     * The MongoDB Collection object for the cache data.
 
33
     *
 
34
     * @var MongoCollection
 
35
     */
 
36
    protected $_db;
 
37
 
 
38
    /**
 
39
     * Constructor.
 
40
     *
 
41
     * @param array $params  Parameters:
 
42
     *   - collection: (string) The collection name.
 
43
     *   - mongo_db: [REQUIRED] (Horde_Mongo_Client) A MongoDB client object.
 
44
     */
 
45
    public function __construct(array $params = array())
 
46
    {
 
47
        if (!isset($params['mongo_db'])) {
 
48
            throw new InvalidArgumentException('Missing mongo_db parameter.');
 
49
        }
 
50
 
 
51
        parent::__construct(array_merge(array(
 
52
            'collection' => 'horde_cache'
 
53
        ), $params));
 
54
    }
 
55
 
 
56
    /**
 
57
     * Destructor.
 
58
     */
 
59
    public function __destruct()
 
60
    {
 
61
        /* Only do garbage collection 0.1% of the time we create an object. */
 
62
        if (rand(0, 999) == 0) {
 
63
            try {
 
64
                $this->_db->remove(array(
 
65
                    self::EXPIRE => array(
 
66
                        '$exists' => true,
 
67
                        '$lt' => time()
 
68
                    )
 
69
                ));
 
70
            } catch (MongoException $e) {
 
71
                $this->_logger->log($e->getMessage(), 'DEBUG');
 
72
            }
 
73
        }
 
74
    }
 
75
 
 
76
    /**
 
77
     */
 
78
    protected function _initOb()
 
79
    {
 
80
        $this->_db = $this->_params['mongo_db']->selectCollection(null, $this->_params['collection']);
 
81
    }
 
82
 
 
83
    /**
 
84
     */
 
85
    public function get($key, $lifetime = 0)
 
86
    {
 
87
        $okey = $key;
 
88
        $key = $this->_getCid($key);
 
89
 
 
90
        /* Build SQL query. */
 
91
        $query = array(
 
92
            self::CID => $key
 
93
        );
 
94
 
 
95
        // 0 lifetime checks for objects which have no expiration
 
96
        if ($lifetime != 0) {
 
97
            $query[self::TIMESTAMP] = array('$gte' => time() - $lifetime);
 
98
        }
 
99
 
 
100
        try {
 
101
            $result = $this->_db->findOne($query, array(self::DATA));
 
102
        } catch (MongoException $e) {
 
103
            $this->_logger->log($e->getMessage(), 'DEBUG');
 
104
            return false;
 
105
        }
 
106
 
 
107
        if (empty($result)) {
 
108
            /* No rows were found - cache miss */
 
109
            if ($this->_logger) {
 
110
                $this->_logger->log(sprintf('Cache miss: %s (cache ID %s)', $okey, $key), 'DEBUG');
 
111
            }
 
112
            return false;
 
113
        }
 
114
 
 
115
        if ($this->_logger) {
 
116
            $this->_logger->log(sprintf('Cache hit: %s (cache ID %s)', $okey, $key), 'DEBUG');
 
117
        }
 
118
 
 
119
        return $result[self::DATA]->bin;
 
120
    }
 
121
 
 
122
    /**
 
123
     */
 
124
    public function set($key, $data, $lifetime = 0)
 
125
    {
 
126
        $okey = $key;
 
127
        $key = $this->_getCid($key);
 
128
        $curr = time();
 
129
 
 
130
        $data = array(
 
131
            self::CID => $key,
 
132
            self::DATA => new MongoBinData($data, MongoBinData::BYTE_ARRAY),
 
133
            self::TIMESTAMP => $curr
 
134
        );
 
135
 
 
136
        // 0 lifetime indicates the object should not be GC'd.
 
137
        if (!empty($lifetime)) {
 
138
            $data[self::EXPIRE] = intval($lifetime) + $curr;
 
139
        }
 
140
 
 
141
        if ($this->_logger) {
 
142
            $this->_logger->log(sprintf(
 
143
                'Cache set: %s (id %s set at %s%s)',
 
144
                $okey,
 
145
                $key,
 
146
                date('r', $curr),
 
147
                (isset($data[self::EXPIRE]) ? ' expires at ' . date('r', $data[self::EXPIRE]) : '')
 
148
            ), 'DEBUG');
 
149
        }
 
150
 
 
151
        // Remove any old cache data and prevent duplicate keys
 
152
        try {
 
153
            $this->_db->update(array(
 
154
                self::CID => $key
 
155
            ), array(
 
156
                '$set' => $data
 
157
            ), array(
 
158
                'upsert' => true,
 
159
                'w' => 0
 
160
            ));
 
161
        } catch (MongoException $e) {
 
162
            $this->_logger->log($e->getMessage(), 'DEBUG');
 
163
            return false;
 
164
        }
 
165
    }
 
166
 
 
167
    /**
 
168
     */
 
169
    public function exists($key, $lifetime = 0)
 
170
    {
 
171
        $okey = $key;
 
172
        $key = $this->_getCid($key);
 
173
 
 
174
        /* Build SQL query. */
 
175
        $query = array(
 
176
            self::CID => $key
 
177
        );
 
178
 
 
179
        // 0 lifetime checks for objects which have no expiration
 
180
        if ($lifetime != 0) {
 
181
            $query[self::TIMESTAMP] = array('$gte' => time() - $lifetime);
 
182
        }
 
183
 
 
184
        try {
 
185
            $result = $this->_db->findOne($query);
 
186
        } catch (MongoException $e) {
 
187
            $this->_logger->log($e->getMessage(), 'DEBUG');
 
188
            return false;
 
189
        }
 
190
 
 
191
        if (is_null($result)) {
 
192
            if ($this->_logger) {
 
193
                $this->_logger->log(sprintf('Cache exists() miss: %s (cache ID %s)', $okey, $key), 'DEBUG');
 
194
            }
 
195
            return false;
 
196
        }
 
197
 
 
198
        if ($this->_logger) {
 
199
            $this->_logger->log(sprintf('Cache exists() hit: %s (cache ID %s)', $okey, $key), 'DEBUG');
 
200
        }
 
201
 
 
202
        return true;
 
203
    }
 
204
 
 
205
    /**
 
206
     */
 
207
    public function expire($key)
 
208
    {
 
209
        try {
 
210
            $this->_db->remove(array(
 
211
                self::CID => $this->_getCid($key)
 
212
            ));
 
213
            return true;
 
214
        } catch (MongoException $e) {
 
215
            return false;
 
216
        }
 
217
    }
 
218
 
 
219
    /**
 
220
     */
 
221
    public function clear()
 
222
    {
 
223
        $this->_db->drop();
 
224
    }
 
225
 
 
226
    /**
 
227
     * Gets the cache ID for a key.
 
228
     *
 
229
     * @param string $key  The key.
 
230
     *
 
231
     * @return string  The cache ID.
 
232
     */
 
233
    protected function _getCid($key)
 
234
    {
 
235
        return hash('md5', $key);
 
236
    }
 
237
 
 
238
}