~jstys-z/helioviewer.org/client5

« back to all changes in this revision

Viewing changes to api/lib/Redisent/RedisentCluster.php

  • Committer: Keith Hughitt
  • Date: 2012-07-26 21:26:16 UTC
  • Revision ID: keith.hughitt@nasa.gov-20120726212616-hos4e9yyun3ebvlq
Added conky script to display Helioviewer.org status information

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * Redisent, a Redis interface for the modest
 
4
 * @author Justin Poliey <jdp34@njit.edu>
 
5
 * @copyright 2009 Justin Poliey <jdp34@njit.edu>
 
6
 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
 
7
 * @package Redisent
 
8
 */
 
9
 
 
10
require_once dirname(__FILE__) . '/Redisent.php';
 
11
 
 
12
/**
 
13
 * A generalized Redisent interface for a cluster of Redis servers
 
14
 */
 
15
class RedisentCluster {
 
16
 
 
17
        /**
 
18
         * Collection of Redisent objects attached to Redis servers
 
19
         * @var array
 
20
         * @access private
 
21
         */
 
22
        private $redisents;
 
23
 
 
24
        /**
 
25
         * Aliases of Redisent objects attached to Redis servers, used to route commands to specific servers
 
26
         * @see RedisentCluster::to
 
27
         * @var array
 
28
         * @access private
 
29
         */
 
30
        private $aliases;
 
31
 
 
32
        /**
 
33
         * Hash ring of Redis server nodes
 
34
         * @var array
 
35
         * @access private
 
36
         */
 
37
        private $ring;
 
38
 
 
39
        /**
 
40
         * Individual nodes of pointers to Redis servers on the hash ring
 
41
         * @var array
 
42
         * @access private
 
43
         */
 
44
        private $nodes;
 
45
 
 
46
        /**
 
47
         * Number of replicas of each node to make around the hash ring
 
48
         * @var integer
 
49
         * @access private
 
50
         */
 
51
        private $replicas = 128;
 
52
 
 
53
        /**
 
54
         * The commands that are not subject to hashing
 
55
         * @var array
 
56
         * @access private
 
57
         */
 
58
        private $dont_hash = array(
 
59
                'RANDOMKEY', 'DBSIZE',
 
60
                'SELECT',    'MOVE',    'FLUSHDB',  'FLUSHALL',
 
61
                'SAVE',      'BGSAVE',  'LASTSAVE', 'SHUTDOWN',
 
62
                'INFO',      'MONITOR', 'SLAVEOF'
 
63
        );
 
64
 
 
65
        /**
 
66
         * Creates a Redisent interface to a cluster of Redis servers
 
67
         * @param array $servers The Redis servers in the cluster. Each server should be in the format array('host' => hostname, 'port' => port)
 
68
         */
 
69
        function __construct($servers) {
 
70
                $this->ring = array();
 
71
                $this->aliases = array();
 
72
                foreach ($servers as $alias => $server) {
 
73
                        $this->redisents[] = new Redisent($server['host'], $server['port']);
 
74
                        if (is_string($alias)) {
 
75
                                $this->aliases[$alias] = $this->redisents[count($this->redisents)-1];
 
76
                        }
 
77
                        for ($replica = 1; $replica <= $this->replicas; $replica++) {
 
78
                                $this->ring[crc32($server['host'].':'.$server['port'].'-'.$replica)] = $this->redisents[count($this->redisents)-1];
 
79
                        }
 
80
                }
 
81
                ksort($this->ring, SORT_NUMERIC);
 
82
                $this->nodes = array_keys($this->ring);
 
83
        }
 
84
 
 
85
        /**
 
86
         * Routes a command to a specific Redis server aliased by {$alias}.
 
87
         * @param string $alias The alias of the Redis server
 
88
         * @return Redisent The Redisent object attached to the Redis server
 
89
         */
 
90
        function to($alias) {
 
91
                if (isset($this->aliases[$alias])) {
 
92
                        return $this->aliases[$alias];
 
93
                }
 
94
                else {
 
95
                        throw new Exception("That Redisent alias does not exist");
 
96
                }
 
97
        }
 
98
 
 
99
        /* Execute a Redis command on the cluster */
 
100
        function __call($name, $args) {
 
101
 
 
102
                /* Pick a server node to send the command to */
 
103
                $name = strtoupper($name);
 
104
                if (!in_array($name, $this->dont_hash)) {
 
105
                        $node = $this->nextNode(crc32($args[0]));
 
106
                        $redisent = $this->ring[$node];
 
107
        }
 
108
        else {
 
109
                        $redisent = $this->redisents[0];
 
110
        }
 
111
 
 
112
                /* Execute the command on the server */
 
113
        return call_user_func_array(array($redisent, $name), $args);
 
114
        }
 
115
 
 
116
        /**
 
117
         * Routes to the proper server node
 
118
         * @param integer $needle The hash value of the Redis command
 
119
         * @return Redisent The Redisent object associated with the hash
 
120
         */
 
121
        private function nextNode($needle) {
 
122
                $haystack = $this->nodes;
 
123
                while (count($haystack) > 2) {
 
124
                        $try = floor(count($haystack) / 2);
 
125
                        if ($haystack[$try] == $needle) {
 
126
                                return $needle;
 
127
                        }
 
128
                        if ($needle < $haystack[$try]) {
 
129
                                $haystack = array_slice($haystack, 0, $try + 1);
 
130
                        }
 
131
                        if ($needle > $haystack[$try]) {
 
132
                                $haystack = array_slice($haystack, $try + 1);
 
133
                        }
 
134
                }
 
135
                return $haystack[count($haystack)-1];
 
136
        }
 
137
 
 
138
}
 
 
b'\\ No newline at end of file'