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.1'
DEFAULT_SYSTEM =
'default'
@@systems =
{}

Class Method Summary collapse

Class Method Details

._clean_up_ring(key, value, system) ⇒ Object



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/lightcloud.rb', line 146

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

.delete(key, system = DEFAULT_SYSTEM) ⇒ Object

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



88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/lightcloud.rb', line 88

def self.delete(key, system=DEFAULT_SYSTEM)
  storage_node = self.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_nodes(config) ⇒ Object

– Helpers ++



184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/lightcloud.rb', line 184

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



202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/lightcloud.rb', line 202

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

Gets a value based on a key.



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/lightcloud.rb', line 66

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

  # Try to lookup key directly
  storage_node = self.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 = self.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 ++



166
167
168
# File 'lib/lightcloud.rb', line 166

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

.get_storage_node(name, system = DEFAULT_SYSTEM) ⇒ Object

– Accessors for nodes ++



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

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

.get_storage_ring(system = DEFAULT_SYSTEM) ⇒ Object



170
171
172
# File 'lib/lightcloud.rb', line 170

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

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



43
44
45
46
47
48
# File 'lib/lightcloud.rb', line 43

def self.init(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[system] = [lookup_ring, storage_ring, name_to_l_nodes, name_to_s_nodes]
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.



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/lightcloud.rb', line 122

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

.locate_node_or_init(key, system) ⇒ Object

– Lookup Cloud ++



106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/lightcloud.rb', line 106

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

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

    lookup_node = self.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 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



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

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