filecluster 0.3.7 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +15 -1
- data/bin/fc-manage +10 -0
- data/lib/daemon/global_daemon_thread.rb +17 -2
- data/lib/fc/copy_rule.rb +79 -0
- data/lib/fc/db.rb +9 -0
- data/lib/fc/policy.rb +8 -3
- data/lib/fc/version.rb +1 -1
- data/lib/filecluster.rb +1 -0
- data/lib/manage.rb +1 -0
- data/lib/manage/copy_rules.rb +107 -0
- data/test/copy_rule_test.rb +80 -0
- data/test/daemon_test.rb +4 -0
- metadata +8 -4
data/README.md
CHANGED
@@ -5,6 +5,7 @@ A set of scripts to manage files on multiple dc/host/drive.
|
|
5
5
|
Item (storage unit)- file or folder.
|
6
6
|
Storage - folder, usually separate drive.
|
7
7
|
Policy - rule for selecting storage to store the item and сreate copies.
|
8
|
+
Copy rule - additional rule for copies сreate.
|
8
9
|
|
9
10
|
Daemon monitors the availability of each storage and copy files between them.
|
10
11
|
|
@@ -31,7 +32,20 @@ Selecting available storage to store item by policy.create_storages (from left t
|
|
31
32
|
|
32
33
|
## Copy policy
|
33
34
|
|
34
|
-
|
35
|
+
Used first available storage.
|
36
|
+
First try copy rules (copy_storages field, from left to right).
|
37
|
+
After that storage.copy_storages (from left to right).
|
38
|
+
|
39
|
+
Copy rule is ruby expression.
|
40
|
+
Can be used the following variables:
|
41
|
+
|
42
|
+
* item_id
|
43
|
+
* size
|
44
|
+
* item_copies
|
45
|
+
* name
|
46
|
+
* tag
|
47
|
+
* dir
|
48
|
+
* src_storage (FC::Storage instance)
|
35
49
|
|
36
50
|
## Variables
|
37
51
|
|
data/bin/fc-manage
CHANGED
@@ -46,6 +46,16 @@ Command:
|
|
46
46
|
errors [<count>] show last count (default 10) errors
|
47
47
|
host_info [<host>] show info for host (default current host)
|
48
48
|
items_info show items statistics
|
49
|
+
}],
|
50
|
+
'copy_rules' => [
|
51
|
+
'show and manage copy rules',
|
52
|
+
%q{Usage: fc-manage [options] copy_rules <command>
|
53
|
+
Command:
|
54
|
+
list show all copy rules
|
55
|
+
show <id> show full info for copy rule
|
56
|
+
add add new copy rule
|
57
|
+
rm <id> delete copy rule
|
58
|
+
change <id> change copy rules attributes
|
49
59
|
}],
|
50
60
|
'var' => [
|
51
61
|
'show and change FC::Var',
|
@@ -33,7 +33,7 @@ class GlobalDaemonThread < BaseThread
|
|
33
33
|
all_policies.each do |policy|
|
34
34
|
next if policy.copies.to_i < 2
|
35
35
|
copies = (1..policy.copies.to_i-1).to_a.join(',')
|
36
|
-
sql = "SELECT i.id as item_id, i.size, i.copies as item_copies, GROUP_CONCAT(ist.storage_name ORDER BY ist.id) as storages "+
|
36
|
+
sql = "SELECT i.id as item_id, i.size, i.copies as item_copies, i.name, i.tag, i.dir, GROUP_CONCAT(ist.storage_name ORDER BY ist.id) as storages "+
|
37
37
|
"FROM #{FC::Item.table_name} as i, #{FC::ItemStorage.table_name} as ist WHERE i.policy_id = #{policy.id} AND "+
|
38
38
|
"ist.item_id = i.id AND i.copies IN (#{copies}) AND i.status = 'ready' AND ist.status <> 'delete' GROUP BY i.id LIMIT #{limit}"
|
39
39
|
r = FC::DB.query(sql)
|
@@ -46,8 +46,23 @@ class GlobalDaemonThread < BaseThread
|
|
46
46
|
$log.warn("GlobalDaemonThread: ItemStorage count >= policy.copies for item #{row['item_id']}")
|
47
47
|
else
|
48
48
|
src_storage = all_storages.detect{|s| item_storages.first == s.name}
|
49
|
-
|
49
|
+
if src_storage
|
50
|
+
storage = FC::CopyRule.get_proper_storage_for_copy(
|
51
|
+
:item_id => row['item_id'],
|
52
|
+
:size => row['size'],
|
53
|
+
:item_copies => row['item_copies'],
|
54
|
+
:name => row['name'],
|
55
|
+
:tag => row['tag'],
|
56
|
+
:dir => row['dir'].to_i == 1,
|
57
|
+
:src_storage => src_storage,
|
58
|
+
:exclude => item_storages
|
59
|
+
)
|
60
|
+
storage = src_storage.get_proper_storage_for_copy(row['size'], item_storages) unless storage
|
61
|
+
end
|
50
62
|
if storage
|
63
|
+
puts row
|
64
|
+
puts src_storage.name+'>'
|
65
|
+
puts storage.name
|
51
66
|
FC::Item.new(:id => row['item_id']).make_item_storage(storage, 'copy')
|
52
67
|
else
|
53
68
|
error 'No available storage', :item_id => row['item_id']
|
data/lib/fc/copy_rule.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module FC
|
4
|
+
class CopyRule < DbBase
|
5
|
+
set_table :copy_rules, 'rule, copy_storages'
|
6
|
+
|
7
|
+
class << self
|
8
|
+
attr_accessor :rules_cache_time, :get_rules_mutex, :copy_storages_cache_time, :get_copy_storages_mutex
|
9
|
+
end
|
10
|
+
@rules_cache_time = 20 # ttl for rules cache
|
11
|
+
@copy_storages_cache_time = 20 # ttl for rule copy_storages
|
12
|
+
@get_rules_mutex = Mutex.new
|
13
|
+
@get_copy_storages_mutex = Mutex.new
|
14
|
+
|
15
|
+
def self.all
|
16
|
+
get_rules_mutex.synchronize do
|
17
|
+
unless @all_rules_cache && Time.new.to_i - @get_all_rules_time.to_i < rules_cache_time
|
18
|
+
@get_all_rules_time = Time.new.to_i
|
19
|
+
@all_rules_cache = where("1")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
@all_rules_cache
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.check_all(item_id, size, item_copies, name, tag, dir, src_storage)
|
26
|
+
all.select do |r|
|
27
|
+
r.check(item_id, size, item_copies, name, tag, dir, src_storage)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# get available storage for copy
|
32
|
+
def self.get_proper_storage_for_copy(options)
|
33
|
+
exclude = options[:exclude] || []
|
34
|
+
rules = check_all(options[:item_id].to_i, options[:size].to_i, options[:item_copies].to_i, options[:name].to_s, options[:tag].to_s, options[:dir] ? true : false, options[:src_storage])
|
35
|
+
result = nil
|
36
|
+
rules.each do |rule|
|
37
|
+
result = rule.get_copy_storages.select do |storage|
|
38
|
+
!exclude.include?(storage.name) && storage.up? && storage.size + options[:size].to_i < storage.size_limit
|
39
|
+
end.first
|
40
|
+
break if result
|
41
|
+
end
|
42
|
+
result
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_copy_storages
|
46
|
+
self.class.get_copy_storages_mutex.synchronize do
|
47
|
+
unless @copy_storages_cache && Time.new.to_i - @get_copy_storages_time.to_i < self.class.copy_storages_cache_time
|
48
|
+
@get_copy_storages_time = Time.new.to_i
|
49
|
+
names = copy_storages.to_s.split(',').map{|s| "'#{s}'"}.join(',')
|
50
|
+
@copy_storages_cache = names.empty? ? [] : FC::Storage.where("name IN (#{names}) ORDER BY FIELD(name, #{names})")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
@copy_storages_cache
|
54
|
+
end
|
55
|
+
|
56
|
+
def check(item_id, size, item_copies, name, tag, dir, src_storage)
|
57
|
+
return false unless rule
|
58
|
+
$SELF = 4
|
59
|
+
r = eval(rule)
|
60
|
+
$SELF = 0
|
61
|
+
r ? true : false
|
62
|
+
end
|
63
|
+
|
64
|
+
def test
|
65
|
+
storage = FC::Storage.new(
|
66
|
+
:id => 1,
|
67
|
+
:name => 'test_storage',
|
68
|
+
:host => 'test_host',
|
69
|
+
:path => '/bla/bla',
|
70
|
+
:url => 'http://bla',
|
71
|
+
:size => 1000,
|
72
|
+
:size_limit => 9999,
|
73
|
+
:check_time => Time.new.to_i,
|
74
|
+
:copy_storages => 'a,b,c'
|
75
|
+
)
|
76
|
+
check(3, 1, 1, 'test/item', 'tag', false, storage)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/fc/db.rb
CHANGED
@@ -179,6 +179,15 @@ module FC
|
|
179
179
|
})
|
180
180
|
FC::DB.connect.query("CREATE TRIGGER fc_errors_before_insert BEFORE INSERT on #{@prefix}errors FOR EACH ROW BEGIN #{proc_time} END")
|
181
181
|
|
182
|
+
FC::DB.connect.query(%{
|
183
|
+
CREATE TABLE #{@prefix}copy_rules (
|
184
|
+
id int NOT NULL AUTO_INCREMENT,
|
185
|
+
copy_storages text NOT NULL DEFAULT '',
|
186
|
+
rule text DEFAULT NULL,
|
187
|
+
PRIMARY KEY (id)
|
188
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
|
189
|
+
})
|
190
|
+
|
182
191
|
FC::DB.connect.query(%{
|
183
192
|
CREATE TABLE #{@prefix}vars (
|
184
193
|
name varchar(255) DEFAULT NULL,
|
data/lib/fc/policy.rb
CHANGED
@@ -28,11 +28,16 @@ module FC
|
|
28
28
|
@create_storages_cache
|
29
29
|
end
|
30
30
|
|
31
|
-
# get available
|
32
|
-
def
|
33
|
-
get_create_storages.
|
31
|
+
# get available storages for create by size
|
32
|
+
def get_proper_storages_for_create(size, exclude = [])
|
33
|
+
get_create_storages.select do |storage|
|
34
34
|
!exclude.include?(storage.name) && storage.up? && storage.size + size < storage.size_limit
|
35
35
|
end
|
36
36
|
end
|
37
|
+
|
38
|
+
# get available storage for create by size
|
39
|
+
def get_proper_storage_for_create(size, exclude = [])
|
40
|
+
get_proper_storages_for_create(size, exclude).first
|
41
|
+
end
|
37
42
|
end
|
38
43
|
end
|
data/lib/fc/version.rb
CHANGED
data/lib/filecluster.rb
CHANGED
data/lib/manage.rb
CHANGED
@@ -0,0 +1,107 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'shellwords'
|
3
|
+
|
4
|
+
def copy_rules_list
|
5
|
+
rules = FC::CopyRule.where("1 ORDER BY id")
|
6
|
+
if rules.size == 0
|
7
|
+
puts "No rules."
|
8
|
+
else
|
9
|
+
rules.each do |rule|
|
10
|
+
puts "##{rule.id}, copy storages: #{rule.copy_storages}, rule: #{rule.rule}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def copy_rules_show
|
16
|
+
if rule = find_rule
|
17
|
+
#count = FC::DB.query("SELECT count(*) as cnt FROM #{FC::ItemStorage.table_name} WHERE storage_name='#{Mysql2::Client.escape(storage.name)}'").first['cnt']
|
18
|
+
puts %Q{Rule
|
19
|
+
Id: #{rule.id}
|
20
|
+
Copy storages: #{rule.copy_storages}
|
21
|
+
Rule: #{rule.rule}}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def copy_rules_add
|
26
|
+
puts "Add copy rule"
|
27
|
+
copy_storages = stdin_read_val('Copy storages')
|
28
|
+
storages = FC::Storage.where.map(&:name)
|
29
|
+
copy_storages = copy_storages.split(',').select{|s| storages.member?(s.strip)}.join(',').strip
|
30
|
+
rule_str = stdin_read_val('Rule')
|
31
|
+
|
32
|
+
begin
|
33
|
+
rule = FC::CopyRule.new(:rule => rule_str, :copy_storages => copy_storages)
|
34
|
+
rule.test
|
35
|
+
rescue Exception => e
|
36
|
+
puts "Error: #{e.message}"
|
37
|
+
exit
|
38
|
+
end
|
39
|
+
puts %Q{\nRule
|
40
|
+
Copy storages: #{rule.copy_storages}
|
41
|
+
Rule: #{rule.rule}}
|
42
|
+
s = Readline.readline("Continue? (y/n) ", false).strip.downcase
|
43
|
+
puts ""
|
44
|
+
if s == "y" || s == "yes"
|
45
|
+
begin
|
46
|
+
rule.save
|
47
|
+
rescue Exception => e
|
48
|
+
puts "Error: #{e.message}"
|
49
|
+
exit
|
50
|
+
end
|
51
|
+
puts "ok"
|
52
|
+
else
|
53
|
+
puts "Canceled."
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def copy_rules_rm
|
58
|
+
if rule = find_rule
|
59
|
+
s = Readline.readline("Continue? (y/n) ", false).strip.downcase
|
60
|
+
puts ""
|
61
|
+
if s == "y" || s == "yes"
|
62
|
+
rule.delete
|
63
|
+
puts "ok"
|
64
|
+
else
|
65
|
+
puts "Canceled."
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def copy_rules_change
|
71
|
+
if rule = find_rule
|
72
|
+
puts "Change rule #{rule.id}"
|
73
|
+
copy_storages = stdin_read_val("Copy storages (now #{rule.copy_storages})", true)
|
74
|
+
storages = FC::Storage.where.map(&:name)
|
75
|
+
rule.copy_storages = copy_storages.split(',').select{|s| storages.member?(s.strip)}.join(',').strip unless copy_storages.empty?
|
76
|
+
rule_str = stdin_read_val("Rule (now #{rule.rule})", true)
|
77
|
+
rule.rule = rule_str unless rule_str.empty?
|
78
|
+
|
79
|
+
puts %Q{\nRule
|
80
|
+
Id: #{rule.id}
|
81
|
+
Copy storages: #{rule.copy_storages}
|
82
|
+
Rule: #{rule.rule}}
|
83
|
+
s = Readline.readline("Continue? (y/n) ", false).strip.downcase
|
84
|
+
puts ""
|
85
|
+
if s == "y" || s == "yes"
|
86
|
+
begin
|
87
|
+
rule.test
|
88
|
+
rule.save
|
89
|
+
rescue Exception => e
|
90
|
+
puts "Error: #{e.message}"
|
91
|
+
exit
|
92
|
+
end
|
93
|
+
puts "ok"
|
94
|
+
else
|
95
|
+
puts "Canceled."
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def find_rule
|
103
|
+
id = ARGV[2]
|
104
|
+
rule = FC::CopyRule.where('id = ?', id).first
|
105
|
+
puts "Rule #{id} not found." unless rule
|
106
|
+
rule
|
107
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class CopyRuleTest < Test::Unit::TestCase
|
4
|
+
class << self
|
5
|
+
def startup
|
6
|
+
@@rules = []
|
7
|
+
@@rules << FC::CopyRule.new(:copy_storages => 'rec2-sda,rec3-sda', :rule => 'size < 100')
|
8
|
+
@@rules << FC::CopyRule.new(:copy_storages => 'rec1-sda,rec3-sda', :rule => 'name.match(/^test1/)')
|
9
|
+
@@rules.each {|rule| rule.save}
|
10
|
+
|
11
|
+
@@storages = []
|
12
|
+
@@storages << FC::Storage.new(:name => 'rec1-sda', :host => 'rec1', :size => 0, :size_limit => 100)
|
13
|
+
@@storages << FC::Storage.new(:name => 'rec2-sda', :host => 'rec2', :size => 0, :size_limit => 10)
|
14
|
+
@@storages << FC::Storage.new(:name => 'rec3-sda', :host => 'rec3', :size => 0, :size_limit => 100)
|
15
|
+
@@storages.each {|storage| storage.save}
|
16
|
+
end
|
17
|
+
def shutdown
|
18
|
+
FC::DB.query("DELETE FROM copy_rules")
|
19
|
+
FC::DB.query("DELETE FROM storages")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
should "rule check" do
|
24
|
+
assert_equal true, @@rules[0].test
|
25
|
+
assert_equal true, @@rules[0].check(1, 1, 1, '', '', false, nil)
|
26
|
+
assert_equal false, @@rules[0].check(1, 100, 1, '', '', false, nil)
|
27
|
+
assert_equal false, @@rules[1].test
|
28
|
+
assert_equal false, @@rules[1].check(1, 1, 1, '', '', false, nil)
|
29
|
+
assert_equal true, @@rules[1].check(1, 1, 1, 'test1/test', '', false, nil)
|
30
|
+
end
|
31
|
+
|
32
|
+
should "get_copy_storages" do
|
33
|
+
FC::CopyRule.copy_storages_cache_time = 10
|
34
|
+
assert_equal 'rec2-sda,rec3-sda', @@rules[0].get_copy_storages.map(&:name).join(',')
|
35
|
+
@@rules[0].copy_storages = 'rec3-sda,rec2-sda'
|
36
|
+
@@rules[0].save
|
37
|
+
assert_equal 'rec2-sda,rec3-sda', @@rules[0].get_copy_storages.map(&:name).join(',')
|
38
|
+
FC::CopyRule.copy_storages_cache_time = 0
|
39
|
+
assert_equal 'rec3-sda,rec2-sda', @@rules[0].get_copy_storages.map(&:name).join(',')
|
40
|
+
end
|
41
|
+
|
42
|
+
should "all rules" do
|
43
|
+
FC::CopyRule.rules_cache_time = 10
|
44
|
+
assert_equal @@rules.map(&:id), FC::CopyRule.all.map(&:id)
|
45
|
+
assert_equal 'rec1-sda,rec3-sda', FC::CopyRule.all[1].copy_storages
|
46
|
+
@@rules[1].copy_storages = 'rec1-sda,rec2-sda'
|
47
|
+
@@rules[1].save
|
48
|
+
assert_equal 'rec1-sda,rec3-sda', FC::CopyRule.all[1].copy_storages
|
49
|
+
FC::CopyRule.rules_cache_time = 0
|
50
|
+
assert_equal 'rec1-sda,rec2-sda', FC::CopyRule.all[1].copy_storages
|
51
|
+
end
|
52
|
+
|
53
|
+
should "check_all" do
|
54
|
+
assert_equal [], FC::CopyRule.check_all(1, 100, 1, '', '', false, nil)
|
55
|
+
assert_same_elements [@@rules[0].id], FC::CopyRule.check_all(1, 1, 1, '', '', false, nil).map(&:id)
|
56
|
+
assert_same_elements [@@rules[0].id, @@rules[1].id], FC::CopyRule.check_all(1, 1, 1, 'test1/test', '', false, nil).map(&:id)
|
57
|
+
end
|
58
|
+
|
59
|
+
should "get_proper_storage_for_copy" do
|
60
|
+
@@rules[0].copy_storages = 'rec2-sda,rec3-sda'
|
61
|
+
@@rules[1].copy_storages = 'rec1-sda,rec3-sda'
|
62
|
+
@@rules[0].save
|
63
|
+
@@rules[1].save
|
64
|
+
FC::CopyRule.rules_cache_time = 0
|
65
|
+
FC::CopyRule.copy_storages_cache_time = 0
|
66
|
+
|
67
|
+
@@storages.each {|storage| storage.check_time = 0; storage.save}
|
68
|
+
assert_nil FC::CopyRule.get_proper_storage_for_copy(:size => 1), 'all storages down'
|
69
|
+
|
70
|
+
@@storages[0].update_check_time
|
71
|
+
assert_nil FC::CopyRule.get_proper_storage_for_copy(:size => 1), 'first storage up, but no rules with storage'
|
72
|
+
assert_equal 'rec1-sda', FC::CopyRule.get_proper_storage_for_copy(:name => 'test1/test').name, 'first storage up'
|
73
|
+
assert_nil FC::CopyRule.get_proper_storage_for_copy(:name => 'test1/test', :size => 200), 'first storage full'
|
74
|
+
assert_nil FC::CopyRule.get_proper_storage_for_copy(:name => 'test1/test', :exclude => ['rec1-sda']), 'exclude'
|
75
|
+
@@storages[1].update_check_time
|
76
|
+
assert_equal 'rec2-sda', FC::CopyRule.get_proper_storage_for_copy(:name => 'test1/test', :size => 5).name, 'second storages up, small file'
|
77
|
+
assert_equal 'rec1-sda', FC::CopyRule.get_proper_storage_for_copy(:name => 'test1/test', :size => 20).name, 'second storages up, big file'
|
78
|
+
assert_nil FC::CopyRule.get_proper_storage_for_copy(:name => 'test1/test', :size => 1000), 'second storages up, big file'
|
79
|
+
end
|
80
|
+
end
|
data/test/daemon_test.rb
CHANGED
@@ -53,6 +53,9 @@ class DaemonTest < Test::Unit::TestCase
|
|
53
53
|
@@policy = FC::Policy.new(:create_storages => 'host1-sda,host1-sdb,host1-sdc', :copies => 2, :name => 'policy 1')
|
54
54
|
@@policy.save
|
55
55
|
|
56
|
+
@@rule = FC::CopyRule.new(:copy_storages => 'host1-sdc', :rule => 'name == "bla/bla/test3"')
|
57
|
+
@@rule.save
|
58
|
+
|
56
59
|
# wait for running fc-daemon
|
57
60
|
Timeout::timeout(5) do
|
58
61
|
while @stotage_checks < @@storages.size
|
@@ -77,6 +80,7 @@ class DaemonTest < Test::Unit::TestCase
|
|
77
80
|
@@storages.each {|storage| storage.reload}
|
78
81
|
assert @@storages[0].up?, "Storage #{@@storages[0].name} down"
|
79
82
|
assert @@storages[1].up?, "Storage #{@@storages[1].name} down"
|
83
|
+
assert @@storages[2].up?, "Storage #{@@storages[2].name} down"
|
80
84
|
|
81
85
|
FC::Storage.any_instance.stubs(:host).returns('host1')
|
82
86
|
FC::Storage.stubs(:curr_host).returns('host1')
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: filecluster
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-07-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rb-readline
|
@@ -152,6 +152,7 @@ files:
|
|
152
152
|
- lib/daemon/run_tasks_thread.rb
|
153
153
|
- lib/daemon/update_tasks_thread.rb
|
154
154
|
- lib/fc/base.rb
|
155
|
+
- lib/fc/copy_rule.rb
|
155
156
|
- lib/fc/db.rb
|
156
157
|
- lib/fc/error.rb
|
157
158
|
- lib/fc/item.rb
|
@@ -162,12 +163,14 @@ files:
|
|
162
163
|
- lib/fc/version.rb
|
163
164
|
- lib/filecluster.rb
|
164
165
|
- lib/manage.rb
|
166
|
+
- lib/manage/copy_rules.rb
|
165
167
|
- lib/manage/policies.rb
|
166
168
|
- lib/manage/show.rb
|
167
169
|
- lib/manage/storages.rb
|
168
170
|
- lib/manage/var.rb
|
169
171
|
- lib/utils.rb
|
170
172
|
- test/base_test.rb
|
173
|
+
- test/copy_rule_test.rb
|
171
174
|
- test/daemon_test.rb
|
172
175
|
- test/db_test.rb
|
173
176
|
- test/error_test.rb
|
@@ -193,7 +196,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
193
196
|
version: '0'
|
194
197
|
segments:
|
195
198
|
- 0
|
196
|
-
hash: -
|
199
|
+
hash: -1801267482625081315
|
197
200
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
198
201
|
none: false
|
199
202
|
requirements:
|
@@ -202,7 +205,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
202
205
|
version: '0'
|
203
206
|
segments:
|
204
207
|
- 0
|
205
|
-
hash: -
|
208
|
+
hash: -1801267482625081315
|
206
209
|
requirements: []
|
207
210
|
rubyforge_project:
|
208
211
|
rubygems_version: 1.8.24
|
@@ -211,6 +214,7 @@ specification_version: 3
|
|
211
214
|
summary: Distributed storage
|
212
215
|
test_files:
|
213
216
|
- test/base_test.rb
|
217
|
+
- test/copy_rule_test.rb
|
214
218
|
- test/daemon_test.rb
|
215
219
|
- test/db_test.rb
|
216
220
|
- test/error_test.rb
|