Class: LightCloud

Inherits:
Object
  • Object
show all
Defined in:
lib/lightcloud.rb

Overview

LightCloud Library

Background

Usage

require 'rubygems'
require 'lightcloud'

LIGHT_CLOUD = {
  'lookup1_A' => ['127.0.0.1:41401', '127.0.0.1:41402'],
  'storage1_A' => ['192.168.0.2:51401', '192.168.0.2:51402']
}

lookup_nodes, storage_nodes = LightCloud.generate_nodes(LIGHT_CLOUD)
LightCloud.init(lookup_nodes, storage_nodes)

LightCloud.set("hello", "world")
print LightCloud.get("hello") # => world
LightCloud.delete("hello")

print LightCloud.get("hello") # => nil

Constant Summary collapse

VERSION =
'0.6'
DEFAULT_SYSTEM =
'default'
@@systems =
{}

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(lookup_nodes, storage_nodes, system = DEFAULT_SYSTEM) ⇒ LightCloud

Initialize LightCloud as an instance instead of using the class methods. Expects the same arguments as LightCloud.init, except this will return a new instance of LightCloud.

Any nodes initialized through here will not work one class methods.



48
49
50
51
# File 'lib/lightcloud.rb', line 48

def initialize(lookup_nodes, storage_nodes, system=DEFAULT_SYSTEM)
  @systems = {}
  self.class.init(lookup_nodes, storage_nodes, system, @systems)
end

Class Method Details

._clean_up_ring(key, value, system, systems = @@systems) ⇒ Object



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/lightcloud.rb', line 176

def self._clean_up_ring(key, value, system, systems=@@systems)
  nodes = self.get_lookup_ring(system, systems).iterate_nodes(key)

  nodes.each_index do |i|
    break if i > 1

    node = nodes[i]
    if i == 0
      node.set(key, value)
    else
      node.delete(key)
    end
  end

  return self.get_storage_node(value, system, systems)
end

.delete(key, system = DEFAULT_SYSTEM, systems = @@systems) ⇒ Object

Lookup the key and delete it from both the storage ring and lookup ring



118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/lightcloud.rb', line 118

def self.delete(key, system=DEFAULT_SYSTEM, systems=@@systems)
  storage_node = self.locate_node(key, system, systems)
  
  storage_node = get_storage_ring(system, systems).get_node(key) if storage_node.nil?
  lookup_nodes = get_lookup_ring(system, systems).iterate_nodes(key)
  lookup_nodes.each_index do |i|
    break if i > 1
    
    lookup_nodes[i].delete(key)
  end
  
  storage_node.delete(key) unless storage_node.nil?
  true
end

.generate_nodes(config) ⇒ Object

– Helpers ++



214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/lightcloud.rb', line 214

def self.generate_nodes(config)
  lookup_nodes = {}
  storage_nodes = {}

  config.each do |k,v|
    if k.include?("lookup")
      lookup_nodes[k] = v
    elsif k.include?("storage")
      storage_nodes[k] = v
    end
  end

  return lookup_nodes, storage_nodes
end

.generate_ring(nodes) ⇒ Object

Given a set of nodes it creates the the nodes as Tokyo Tyrant objects and returns a hash ring with them



232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/lightcloud.rb', line 232

def self.generate_ring(nodes)
  objects = []
  name_to_obj = {}
  
  nodes.each do |name, nodelist|
    obj = TyrantNode.new(name, nodelist)
    name_to_obj[name] = obj

    objects.push(obj)
  end

  return HashRing.new(objects), name_to_obj
end

.get(key, system = DEFAULT_SYSTEM, systems = @@systems) ⇒ Object

Gets a value based on a key.



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/lightcloud.rb', line 96

def self.get(key, system=DEFAULT_SYSTEM, systems=@@systems)
  result = nil

  # Try to lookup key directly
  storage_node = self.get_storage_ring(system, systems).get_node(key)
  value = storage_node.get(key)

  result = value unless value.nil?
  
  # Else use the lookup ring
  if result.nil?
    storage_node = self.locate_node(key, system, systems)
    
    result = storage_node.get(key) unless storage_node.nil?
  end

  result
end

.get_lookup_ring(system = DEFAULT_SYSTEM, systems = @@systems) ⇒ Object

– Accessors for rings ++



196
197
198
# File 'lib/lightcloud.rb', line 196

def self.get_lookup_ring(system=DEFAULT_SYSTEM, systems=@@systems)
  systems[system][0]
end

.get_storage_node(name, system = DEFAULT_SYSTEM, systems = @@systems) ⇒ Object

– Accessors for nodes ++



207
208
209
# File 'lib/lightcloud.rb', line 207

def self.get_storage_node(name, system=DEFAULT_SYSTEM, systems=@@systems)
  systems[system][3][name]
end

.get_storage_ring(system = DEFAULT_SYSTEM, systems = @@systems) ⇒ Object



200
201
202
# File 'lib/lightcloud.rb', line 200

def self.get_storage_ring(system=DEFAULT_SYSTEM, systems=@@systems)
  systems[system][1]
end

.init(lookup_nodes, storage_nodes, system = DEFAULT_SYSTEM, systems = @@systems) ⇒ Object



53
54
55
56
57
58
# File 'lib/lightcloud.rb', line 53

def self.init(lookup_nodes, storage_nodes, system=DEFAULT_SYSTEM, systems=@@systems)
  lookup_ring, name_to_l_nodes = self.generate_ring(lookup_nodes)
  storage_ring, name_to_s_nodes = self.generate_ring(storage_nodes)

  systems[system] = [lookup_ring, storage_ring, name_to_l_nodes, name_to_s_nodes]
end

.locate_node(key, system = DEFAULT_SYSTEM, systems = @@systems) ⇒ Object

Locates a node in the lookup ring, returning the node if it is found, or nil otherwise.



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/lightcloud.rb', line 152

def self.locate_node(key, system=DEFAULT_SYSTEM, systems=@@systems)
  nodes = self.get_lookup_ring(system, systems).iterate_nodes(key)
  
  lookups = 0
  value = nil
  nodes.each_index do |i|
    lookups = i
    return nil if lookups > 2
    
    node = nodes[lookups]
    value = node.get(key)

    break unless value.nil?
  end

  return nil if value.nil?
  
  if lookups == 0
    return self.get_storage_node(value, system, systems)
  else
    return self._clean_up_ring(key, value, system, systems)
  end
end

.locate_node_or_init(key, system, systems = @@systems) ⇒ Object

– Lookup Cloud ++



136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/lightcloud.rb', line 136

def self.locate_node_or_init(key, system, systems=@@systems)
  storage_node = self.locate_node(key, system, systems)

  if storage_node.nil?
    storage_node = self.get_storage_ring(system, systems).get_node(key)

    lookup_node = self.get_lookup_ring(system, systems).get_node(key)
    lookup_node.set(key, storage_node.to_s)
  end

  storage_node
end

.set(key, value, system = DEFAULT_SYSTEM, systems = @@systems) ⇒ Object

Sets a value to a key in the LightCloud system.

Set first checks to see if the key is already stored. If it is it uses that same node to store the new value. Otherwise, it determines where to store the value based on the hash_ring



89
90
91
92
# File 'lib/lightcloud.rb', line 89

def self.set(key, value, system=DEFAULT_SYSTEM, systems=@@systems)
  storage_node = self.locate_node_or_init(key, system, systems)
  return storage_node.set(key, value)
end

Instance Method Details

#delete(key, system = DEFAULT_SYSTEM) ⇒ Object

Delete a value from a LightCloud instance. See LightCloud.delete for more information.



79
80
81
# File 'lib/lightcloud.rb', line 79

def delete(key, system=DEFAULT_SYSTEM)
  self.class.delete(key, system, @systems)
end

#get(key, system = DEFAULT_SYSTEM) ⇒ Object

Gets a value to a key on a LightCloud instance. See LightCloud.get for more information.



72
73
74
# File 'lib/lightcloud.rb', line 72

def get(key, system=DEFAULT_SYSTEM)
  self.class.get(key, system, @systems)
end

#set(key, value, system = DEFAULT_SYSTEM) ⇒ Object

– Get/Set/Delete ++ Sets a value to a key on a LightCloud instance. See LightCloud.set for more information



65
66
67
# File 'lib/lightcloud.rb', line 65

def set(key, value, system=DEFAULT_SYSTEM)
  self.class.set(key, value, system, @systems)
end