Class: ShardRangeDB
Instance Attribute Summary collapse
-
#local_shard_db ⇒ Object
Returns the value of attribute local_shard_db.
-
#nodes ⇒ Object
Returns the value of attribute nodes.
-
#our_node ⇒ Object
Returns the value of attribute our_node.
Instance Method Summary collapse
- #build_shards(number) ⇒ Object
- #get_content_shards ⇒ Object
- #get_doc_directly(internal_id) ⇒ Object
- #get_shard(internal_id) ⇒ Object
-
#initialize(nodesv) ⇒ ShardRangeDB
constructor
A new instance of ShardRangeDB.
- #sync ⇒ Object
- #write_doc_directly(content_doc) ⇒ Object
Constructor Details
#initialize(nodesv) ⇒ ShardRangeDB
Returns a new instance of ShardRangeDB.
5 6 7 8 9 10 11 12 13 14 |
# File 'lib/adhd/models/shard_range.rb', line 5 def initialize(nodesv) @nodes = nodesv # Automatically get our shard_db address from our own node name @our_node = nodesv.our_node @local_shard_db = nodesv.our_node.get_shard_db puts "Assign default database for shard ranges (#{@local_shard_db})" ShardRange.use_database @local_shard_db end |
Instance Attribute Details
#local_shard_db ⇒ Object
Returns the value of attribute local_shard_db.
3 4 5 |
# File 'lib/adhd/models/shard_range.rb', line 3 def local_shard_db @local_shard_db end |
#nodes ⇒ Object
Returns the value of attribute nodes.
3 4 5 |
# File 'lib/adhd/models/shard_range.rb', line 3 def nodes @nodes end |
#our_node ⇒ Object
Returns the value of attribute our_node.
3 4 5 |
# File 'lib/adhd/models/shard_range.rb', line 3 def our_node @our_node end |
Instance Method Details
#build_shards(number) ⇒ Object
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/adhd/models/shard_range.rb', line 34 def build_shards(number) # Make a large list of possible id boundaries characters = [] ("0".."9").each do |c| characters << c end ("a".."f").each do |c| characters << c end # Generate 36 x 36 keys to choose boundaries from all_keys = [] characters.each do |c1| characters.each do |c2| characters.each do |c3| all_keys << (c1+c2+c3) end end end # Now chose our boundaries num_range_keys = all_keys.length approx_shard_size = (num_range_keys * 1.0) / number shard_starts = [] (0...number).each do |n| shard_starts << (all_keys[(n * approx_shard_size).floor]) end shard_ends = shard_starts.clone shard_ends << ("z" * 3) shard_ends.delete_at(0) # Finally build them! puts "Build Shards" (0...number).each do |n| puts "Shard #{n}: from #{shard_starts[n]} to #{shard_ends[n]}" shard_name = "sh_#{shard_starts[n]}_to_#{shard_ends[n]}" sr = ShardRange.new sr.range_start = shard_starts[n] sr.range_end = shard_ends[n] sr.shard_db_name = shard_name sr.save end end |
#get_content_shards ⇒ Object
92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/adhd/models/shard_range.rb', line 92 def get_content_shards # Return the content_shards of our node content_shards = {} ShardRange.by_node(:key => our_node.name).each do |s| # Build a content shard object content_shards[s.shard_db_name] = ContentShard.new(nodes, s) end puts "Content shards #{content_shards.length}" content_shards end |
#get_doc_directly(internal_id) ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/adhd/models/shard_range.rb', line 132 def get_doc_directly(internal_id) # Write a document directly to a nodes content repository doc_shard = get_shard(internal_id).first # TODO: Randomize the order of nodes for load balancing in retrieval! docx = [] doc_shard.get_nodes.each do |node| # Try to write the doc to this node begin remote_node = Node.by_name(:key => node).first remote_ndb = NodeDB.new(remote_node) remote_content_shard = ContentShard.new(remote_ndb, doc_shard) docx = ContentDoc.by_internal_id(:key => internal_id, :database => remote_content_shard.this_shard_db) if docx.length > 0 return {:ok => true, :doc => docx.first, :db => remote_content_shard.this_shard_db } end rescue puts "Could not put doc in node #{node.name}" # TODO: change status or chose another management server remote_node.status = "UNAVAILABLE" remote_node.save end end return {:ok => false } end |
#get_shard(internal_id) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/adhd/models/shard_range.rb', line 80 def get_shard(internal_id) # Finds the list of shards within which this ID lives all_shards = ShardRange.by_range_start selected_shards = [] all_shards.each do |a_shard| # TODO: linear search is inefficient -- create a view if a_shard.range_start <= internal_id && a_shard.range_end > internal_id selected_shards << a_shard end end selected_shards end |
#sync ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/adhd/models/shard_range.rb', line 16 def sync # We replicate our state from the management node(s) # We never push content if we are only storage management_nodes = Node.by_is_management.reverse # NOTE: randomize the order for load balancing here management_nodes.each do |mng_node| remote_db = mng_node.get_shard_db bool_from = @our_node.replicate_from(local_shard_db, mng_node, remote_db) if our_node.is_management # Push any changes to other management nodes bool_to = @our_node.replicate_to(local_shard_db, mng_node, remote_db) end break if bool_from && !our_node.is_management end end |
#write_doc_directly(content_doc) ⇒ Object
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/adhd/models/shard_range.rb', line 104 def write_doc_directly(content_doc) # Write a document directly to a nodes content repository success = {:ok => false , :reason => "No available node found"} doc_shard = get_shard(content_doc.internal_id).first doc_shard.get_nodes.each do |node| # Try to write the doc to this node begin remote_node = Node.by_name(:key => node).first remote_ndb = NodeDB.new(remote_node) remote_content_shard = ContentShard.new(remote_ndb, doc_shard) remote_content_shard.this_shard_db.save_doc(content_doc) success = {:ok => true, :doc => content_doc, :db => remote_content_shard.this_shard_db} break rescue RestClient::RequestFailed => rf if rf.http_code == 409 puts "Document already there" return {:ok => false , :reason => "Document already in database"} end rescue Exception =>e puts "Could not put doc in node #{node} because of #{rf}" # TODO: change status or chose another management server remote_node.status = "UNAVAILABLE" remote_node.save end end return success end |