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.7'
DEFAULT_SYSTEM =
'default'
@@instance =
nil

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

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

– INSTANCE METHODS ++ 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.



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

def initialize(lookup_nodes=nil, storage_nodes=nil, system=DEFAULT_SYSTEM)
  add_system(lookup_nodes, storage_nodes, system) if !lookup_nodes.nil? && !storage_nodes.nil?
end

Class Method Details

.delete(key, system = DEFAULT_SYSTEM) ⇒ Object

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



239
240
241
# File 'lib/lightcloud.rb', line 239

def self.delete(key, system=DEFAULT_SYSTEM)
  instance.delete(key, system)
end

.generate_nodes(config) ⇒ Object

– Helpers ++



254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'lib/lightcloud.rb', line 254

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

.get(key, system = DEFAULT_SYSTEM) ⇒ Object

Gets a value based on a key.



232
233
234
# File 'lib/lightcloud.rb', line 232

def self.get(key, system=DEFAULT_SYSTEM)
  instance.get(key, system)
end

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

– CLASS METHODS ++

Initializes LightCloud library with lookup and storage nodes. This only needs to be called with servers with which you intend to use the class methods (set/get/delete)



216
217
218
# File 'lib/lightcloud.rb', line 216

def self.init(lookup_nodes, storage_nodes, system=DEFAULT_SYSTEM)
  instance.add_system(lookup_nodes, storage_nodes, system)
end

.instanceObject

– Instance accessor ++



246
247
248
249
# File 'lib/lightcloud.rb', line 246

def self.instance
  @@instance ||= self.new
  @@instance
end

.set(key, value, system = DEFAULT_SYSTEM) ⇒ 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



226
227
228
# File 'lib/lightcloud.rb', line 226

def self.set(key, value, system=DEFAULT_SYSTEM)
  instance.set(key, value, system)
end

Instance Method Details

#_clean_up_ring(key, value, system) ⇒ Object



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/lightcloud.rb', line 157

def _clean_up_ring(key, value, system)
  nodes = get_lookup_ring(system).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 get_storage_node(value, system)
end

#add_system(lookup_nodes, storage_nodes, system = DEFAULT_SYSTEM) ⇒ Object

Create a new LightCloud system within a pre-existing instance.



56
57
58
59
60
61
62
# File 'lib/lightcloud.rb', line 56

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

  @systems ||= {}
  @systems[system] = [lookup_ring, storage_ring, name_to_l_nodes, name_to_s_nodes]    
end

#delete(key, system = DEFAULT_SYSTEM) ⇒ Object

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



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

def delete(key, system=DEFAULT_SYSTEM)
  storage_node = locate_node(key, system)
  
  storage_node = get_storage_ring(system).get_node(key) if storage_node.nil?
  lookup_nodes = get_lookup_ring(system).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_ring(nodes) ⇒ Object

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



195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/lightcloud.rb', line 195

def 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) ⇒ Object

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



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/lightcloud.rb', line 77

def get(key, system=DEFAULT_SYSTEM)
  result = nil

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

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

  result    
end

#get_lookup_ring(system = DEFAULT_SYSTEM) ⇒ Object

– Accessors for rings ++



177
178
179
# File 'lib/lightcloud.rb', line 177

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

#get_storage_node(name, system = DEFAULT_SYSTEM) ⇒ Object

– Accessors for nodes ++



188
189
190
# File 'lib/lightcloud.rb', line 188

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

#get_storage_ring(system = DEFAULT_SYSTEM) ⇒ Object



181
182
183
# File 'lib/lightcloud.rb', line 181

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

#locate_node(key, system = DEFAULT_SYSTEM) ⇒ Object

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



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/lightcloud.rb', line 133

def locate_node(key, system=DEFAULT_SYSTEM)
  nodes = get_lookup_ring(system).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 get_storage_node(value, system)
  else
    return _clean_up_ring(key, value, system)
  end
end

#locate_node_or_init(key, system) ⇒ Object

– Lookup Cloud ++



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

def locate_node_or_init(key, system)
  storage_node = locate_node(key, system)

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

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

  storage_node
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



69
70
71
72
# File 'lib/lightcloud.rb', line 69

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