Class: VCAP::Services::Base::SnapshotV2::SnapshotClient
- Includes:
- Error
- Defined in:
- lib/base/snapshot_v2/snapshot_client.rb
Constant Summary collapse
- SNAPSHOT_KEY_PREFIX =
"vcap:snapshotv2".freeze
- SNAPSHOT_ID =
"maxid".freeze
- FILTER_KEYS =
%w(snapshot_id date size name).freeze
- MAX_NAME_LENGTH =
512
Class Method Summary collapse
-
.filter_keys(snapshot) ⇒ Object
filter internal keys of a given snapshot object, return a new snapshot object in canonical format.
- .fmt_time ⇒ Object
- .redis_key(key) ⇒ Object
-
.snapshot_filepath(base_dir, service_name, service_id, snapshot_id) ⇒ Object
Get the snapshot file path that service should save the dump file to.
Instance Method Summary collapse
- #create_empty_snapshot(service_id, name) ⇒ Object
- #delete_snapshot(service_id, snapshot_id) ⇒ Object
-
#initialize(redis_config) ⇒ SnapshotClient
constructor
A new instance of SnapshotClient.
-
#new_snapshot_id ⇒ Object
Generate a new unique id for a snapshot.
- #save_snapshot(service_id, snapshot) ⇒ Object
-
#service_snapshots(service_id) ⇒ Object
Get all snapshots related to a service instance.
-
#service_snapshots_count(service_id) ⇒ Object
Return total snapshots count.
-
#snapshot_details(service_id, snapshot_id) ⇒ Object
Get detail information for a single snapshot.
-
#update_name(service_id, snapshot_id, name) ⇒ Object
Update the name of given snapshot.
Methods included from Error
#failure, #internal_fail, #parse_msg, #success, #timeout_fail
Constructor Details
#initialize(redis_config) ⇒ SnapshotClient
Returns a new instance of SnapshotClient.
14 15 16 17 18 |
# File 'lib/base/snapshot_v2/snapshot_client.rb', line 14 def initialize(redis_config) @redis = ::Redis.new(redis_config) # FIXME: use UUID? redis_init end |
Class Method Details
.filter_keys(snapshot) ⇒ Object
filter internal keys of a given snapshot object, return a new snapshot object in canonical format
57 58 59 60 |
# File 'lib/base/snapshot_v2/snapshot_client.rb', line 57 def self.filter_keys(snapshot) return unless snapshot.is_a? Hash snapshot.select {|k,v| FILTER_KEYS.include? k.to_s} end |
.fmt_time ⇒ Object
116 117 118 119 |
# File 'lib/base/snapshot_v2/snapshot_client.rb', line 116 def self.fmt_time() # UTC time in ISO 8601 format. Time.now.utc.strftime("%FT%TZ") end |
.redis_key(key) ⇒ Object
121 122 123 |
# File 'lib/base/snapshot_v2/snapshot_client.rb', line 121 def self.redis_key(key) "#{SNAPSHOT_KEY_PREFIX}:#{key}" end |
.snapshot_filepath(base_dir, service_name, service_id, snapshot_id) ⇒ Object
Get the snapshot file path that service should save the dump file to. the snapshot path structure looks like <base_dir>snapshots<service-name><aa><bb><cc><aabbcc-rest-of-instance-guid>snapshot_id<service specific data>
69 70 71 |
# File 'lib/base/snapshot_v2/snapshot_client.rb', line 69 def self.snapshot_filepath(base_dir, service_name, service_id, snapshot_id) File.join(base_dir, "snapshots", service_name, service_id[0,2], service_id[2,2], service_id[4,2], service_id, snapshot_id.to_s) end |
Instance Method Details
#create_empty_snapshot(service_id, name) ⇒ Object
20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/base/snapshot_v2/snapshot_client.rb', line 20 def create_empty_snapshot(service_id, name) snapshot = { 'state' => 'empty', 'size' => 0, 'name' => name, 'snapshot_id' => new_snapshot_id, } msg = Yajl::Encoder.encode(snapshot) client.hset(redis_key(service_id), snapshot['snapshot_id'], msg) snapshot end |
#delete_snapshot(service_id, snapshot_id) ⇒ Object
110 111 112 113 |
# File 'lib/base/snapshot_v2/snapshot_client.rb', line 110 def delete_snapshot(service_id , snapshot_id) return unless service_id && snapshot_id client.hdel(redis_key(service_id), snapshot_id) end |
#new_snapshot_id ⇒ Object
Generate a new unique id for a snapshot
63 64 65 |
# File 'lib/base/snapshot_v2/snapshot_client.rb', line 63 def new_snapshot_id client.incr(redis_key(SNAPSHOT_ID)).to_s end |
#save_snapshot(service_id, snapshot) ⇒ Object
101 102 103 104 105 106 107 108 |
# File 'lib/base/snapshot_v2/snapshot_client.rb', line 101 def save_snapshot(service_id , snapshot) return unless service_id && snapshot # FIXME: srsly? where are we using symbols? sid = snapshot[:snapshot_id] || snapshot["snapshot_id"] return unless sid msg = Yajl::Encoder.encode(snapshot) client.hset(redis_key(service_id), sid, msg) end |
#service_snapshots(service_id) ⇒ Object
Get all snapshots related to a service instance
34 35 36 37 38 |
# File 'lib/base/snapshot_v2/snapshot_client.rb', line 34 def service_snapshots(service_id) return unless service_id res = client.hgetall(redis_key(service_id)) res.values.map{|v| Yajl::Parser.parse(v)} end |
#service_snapshots_count(service_id) ⇒ Object
Return total snapshots count
42 43 44 45 |
# File 'lib/base/snapshot_v2/snapshot_client.rb', line 42 def service_snapshots_count(service_id) return unless service_id client.hlen(redis_key(service_id)) end |
#snapshot_details(service_id, snapshot_id) ⇒ Object
Get detail information for a single snapshot
49 50 51 52 53 54 |
# File 'lib/base/snapshot_v2/snapshot_client.rb', line 49 def snapshot_details(service_id, snapshot_id) return unless service_id && snapshot_id res = client.hget(redis_key(service_id), snapshot_id) raise ServiceError.new(ServiceError::NOT_FOUND, "snapshot #{snapshot_id}") unless res Yajl::Parser.parse(res) end |
#update_name(service_id, snapshot_id, name) ⇒ Object
Update the name of given snapshot. This function is not protected by redis lock so a optimistic lock is applied to prevent concurrent update.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/base/snapshot_v2/snapshot_client.rb', line 77 def update_name(service_id, snapshot_id, name) return unless service_id && snapshot_id && name verify_input_name(name) key = self.class.redis_key(service_id) # NOTE: idealy should watch on combination of (service_id, snapshot_id) # but current design doesn't support such fine-grained watching. client.watch(key) snapshot = client.hget(redis_key(service_id), snapshot_id) return nil unless snapshot snapshot = Yajl::Parser.parse(snapshot) snapshot["name"] = name res = client.multi do save_snapshot(service_id, snapshot) end unless res raise ServiceError.new(ServiceError::REDIS_CONCURRENT_UPDATE) end true end |