ccp 0.2.8 → 0.2.9
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/ccp.gemspec +11 -1
- data/lib/ccp.rb +1 -0
- data/lib/ccp/commands/resolvable.rb +1 -2
- data/lib/ccp/kvs.rb +46 -0
- data/lib/ccp/kvs/core.rb +28 -0
- data/lib/ccp/kvs/hash.rb +16 -0
- data/lib/ccp/kvs/tch.rb +12 -0
- data/lib/ccp/kvs/tokyo.rb +15 -0
- data/lib/ccp/kvs/tokyo/base.rb +49 -0
- data/lib/ccp/kvs/tokyo/cabinet.rb +56 -0
- data/lib/ccp/kvs/tokyo/info.rb +74 -0
- data/lib/ccp/kvs/tokyo/state_machine.rb +106 -0
- data/lib/ccp/serializers.rb +35 -16
- data/lib/ccp/serializers/core.rb +13 -10
- data/lib/ccp/serializers/json.rb +15 -11
- data/lib/ccp/serializers/msgpack.rb +12 -0
- data/lib/ccp/serializers/yaml.rb +8 -11
- data/lib/ccp/version.rb +1 -1
- data/spec/kvs/core_spec.rb +12 -0
- data/spec/kvs/kvs_spec.rb +44 -0
- data/spec/kvs/lookup_spec.rb +55 -0
- data/spec/kvs/tch_spec.rb +19 -0
- data/spec/kvs/tokyo/cabinet_spec.rb +208 -0
- data/spec/kvs/tokyo/info_spec.rb +27 -0
- data/spec/serializers/core_spec.rb +0 -1
- data/spec/serializers/lookup_spec.rb +86 -0
- data/spec/serializers/serializer_spec.rb +34 -0
- data/spec/spec_helper.rb +21 -1
- metadata +108 -18
- data/spec/serializers/json_spec.rb +0 -27
- data/spec/serializers/spec.rb +0 -39
- data/spec/serializers/yaml_spec.rb +0 -27
data/lib/ccp/serializers.rb
CHANGED
@@ -1,19 +1,38 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
name.must.duck(key) { raise NotFound, "%s: %s" % [name.class, name] }
|
15
|
-
end
|
16
|
-
return name
|
1
|
+
require 'ccp/serializers/core'
|
2
|
+
|
3
|
+
module Ccp
|
4
|
+
module Serializers
|
5
|
+
NotFound = Class.new(RuntimeError)
|
6
|
+
|
7
|
+
DICTIONARY = {} # cache for (extname -> Serializer)
|
8
|
+
|
9
|
+
include Enumerable
|
10
|
+
delegate :delete, :to=>"DICTIONARY"
|
11
|
+
|
12
|
+
def each(&block)
|
13
|
+
DICTIONARY.each_value(&block)
|
17
14
|
end
|
15
|
+
|
16
|
+
def [](name)
|
17
|
+
return name.must.coerced(Core, Symbol => :to_s, String => proc{|key| DICTIONARY[key]}) {
|
18
|
+
raise NotFound, "%s(%s) for %s" % [name, name.class, DICTIONARY.keys.inspect]
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def []=(key, val)
|
23
|
+
DICTIONARY[key.to_s] = val.must(Core)
|
24
|
+
end
|
25
|
+
|
26
|
+
alias :lookup :[]
|
27
|
+
extend self
|
18
28
|
end
|
19
29
|
end
|
30
|
+
|
31
|
+
require 'ccp/serializers/json'
|
32
|
+
require 'ccp/serializers/yaml'
|
33
|
+
require 'ccp/serializers/msgpack'
|
34
|
+
|
35
|
+
Ccp::Serializers[:json] = Ccp::Serializers::Json
|
36
|
+
Ccp::Serializers[:yaml] = Ccp::Serializers::Yaml
|
37
|
+
Ccp::Serializers[:msgpack] = Ccp::Serializers::Msgpack
|
38
|
+
|
data/lib/ccp/serializers/core.rb
CHANGED
@@ -1,13 +1,16 @@
|
|
1
|
-
module Ccp
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
raise NotImplementedError, "subclass resposibility"
|
8
|
-
end
|
1
|
+
module Ccp
|
2
|
+
module Serializers
|
3
|
+
module Core
|
4
|
+
def ext ; self.class.name.split(/::/).last.to_s.downcase; end
|
5
|
+
def encode(val) ; raise NotImplementedError, "subclass resposibility"; end
|
6
|
+
def decode(val) ; raise NotImplementedError, "subclass resposibility"; end
|
9
7
|
|
10
|
-
|
11
|
-
|
8
|
+
def self.included(klass)
|
9
|
+
klass.extend klass
|
10
|
+
klass.module_eval do
|
11
|
+
def self.ext; name.split(/::/).last.to_s.downcase; end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
12
15
|
end
|
13
16
|
end
|
data/lib/ccp/serializers/json.rb
CHANGED
@@ -1,15 +1,19 @@
|
|
1
|
-
module Ccp
|
2
|
-
|
1
|
+
module Ccp
|
2
|
+
module Serializers
|
3
|
+
module Json
|
4
|
+
include Core
|
3
5
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
# use Yajl if possible
|
7
|
+
begin
|
8
|
+
require 'yajl'
|
9
|
+
Engine = Yajl
|
10
|
+
rescue LoadError
|
11
|
+
require 'json'
|
12
|
+
Engine = JSON
|
13
|
+
end
|
11
14
|
|
12
|
-
|
13
|
-
|
15
|
+
def encode(val) ; Engine.dump(val) ; end
|
16
|
+
def decode(val) ; Engine.load(val) ; end
|
17
|
+
end
|
14
18
|
end
|
15
19
|
end
|
data/lib/ccp/serializers/yaml.rb
CHANGED
@@ -1,15 +1,12 @@
|
|
1
|
-
|
2
|
-
include Ccp::Serializers::Core
|
1
|
+
require 'yaml'
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
def self.encode(val)
|
9
|
-
val.to_yaml
|
10
|
-
end
|
3
|
+
module Ccp
|
4
|
+
module Serializers
|
5
|
+
module Yaml
|
6
|
+
include Core
|
11
7
|
|
12
|
-
|
13
|
-
|
8
|
+
def encode(val) ; val.to_yaml ; end
|
9
|
+
def decode(val) ; YAML.load(val) ; end
|
10
|
+
end
|
14
11
|
end
|
15
12
|
end
|
data/lib/ccp/version.rb
CHANGED
@@ -0,0 +1,12 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Ccp::Kvs::Core do
|
5
|
+
subject { Object.new.extend Ccp::Kvs::Core }
|
6
|
+
|
7
|
+
it { should respond_to("ext") }
|
8
|
+
it { should respond_to("get") }
|
9
|
+
it { should respond_to("set") }
|
10
|
+
it { should respond_to("del") }
|
11
|
+
it { should respond_to("touch") }
|
12
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
kvss = []
|
5
|
+
kvss << Ccp::Kvs::Hash.new
|
6
|
+
kvss << Ccp::Kvs::Tch.new("#{tmp_path}/kvs/foo.tch")
|
7
|
+
|
8
|
+
kvss.each do |kvs|
|
9
|
+
describe kvs do
|
10
|
+
before { FileUtils.rm_rf(tmp_path) if tmp_path.directory? }
|
11
|
+
|
12
|
+
its(:ext) { should == kvs.class.ext }
|
13
|
+
|
14
|
+
describe "#get, #set, #out" do
|
15
|
+
let(:key) { raise "Sub context responsibility" }
|
16
|
+
let(:val) { raise "Sub context responsibility" }
|
17
|
+
|
18
|
+
subject {
|
19
|
+
k = kvs
|
20
|
+
k.touch
|
21
|
+
k.count.should == 0
|
22
|
+
k.get(key).should == nil
|
23
|
+
k.set(key, val)
|
24
|
+
k.get(key).should == val.to_s
|
25
|
+
k.count.should == 1
|
26
|
+
k.out(key).should == val.to_s
|
27
|
+
k.get(key).should == nil
|
28
|
+
k
|
29
|
+
}
|
30
|
+
|
31
|
+
context "'foo' => '1'" do
|
32
|
+
let(:key) { "foo" }
|
33
|
+
let(:val) { "1" }
|
34
|
+
it { should be }
|
35
|
+
end
|
36
|
+
|
37
|
+
context ":foo => 2" do
|
38
|
+
let(:key) { :foo }
|
39
|
+
let(:val) { 2 }
|
40
|
+
it { should be }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
describe Ccp::Kvs do
|
6
|
+
# API
|
7
|
+
it { should respond_to(:lookup) }
|
8
|
+
|
9
|
+
describe "#reload!" do
|
10
|
+
def add_kvs(const_name)
|
11
|
+
# define a new kvs
|
12
|
+
ext = const_name.downcase
|
13
|
+
kvs = Class.new
|
14
|
+
kvs.class_eval <<-EOF
|
15
|
+
include Ccp::Kvs::Core
|
16
|
+
def ext; '#{ext}'; end
|
17
|
+
EOF
|
18
|
+
Ccp::Kvs[ext] = kvs
|
19
|
+
end
|
20
|
+
|
21
|
+
def del_serialier(const_name)
|
22
|
+
ext = const_name.downcase
|
23
|
+
Ccp::Serializers.delete(ext)
|
24
|
+
end
|
25
|
+
|
26
|
+
specify do
|
27
|
+
# given
|
28
|
+
lambda { subject.lookup(:foo) }.should raise_error(Ccp::Kvs::NotFound)
|
29
|
+
|
30
|
+
begin
|
31
|
+
# main
|
32
|
+
add_kvs("Foo")
|
33
|
+
subject.lookup(:foo).should be_kind_of(Class)
|
34
|
+
ensure
|
35
|
+
del_serialier("Foo")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#lookup" do
|
41
|
+
context ":hash" do
|
42
|
+
it "should return Ccp::Kvs::Hash" do
|
43
|
+
subject.lookup(:hash).should == Ccp::Kvs::Hash
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context ":xxx" do
|
48
|
+
it "should raise NotFound" do
|
49
|
+
lambda {
|
50
|
+
subject.lookup(:xxx)
|
51
|
+
}.should raise_error(Ccp::Kvs::NotFound)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
__END__
|
5
|
+
|
6
|
+
describe Ccp::Kvs::Tch do
|
7
|
+
let(:kvs) { s = Ccp::Kvs::Tch.new; s.open(source); s }
|
8
|
+
let(:tmp) { tmp_path + "kvs/tch" }
|
9
|
+
before { FileUtils.rm_rf(tmp) if tmp.directory? }
|
10
|
+
|
11
|
+
describe "#open" do
|
12
|
+
subject { inform }
|
13
|
+
|
14
|
+
context "foo.tch" do
|
15
|
+
let(:source) { tmp + "foo.tch" }
|
16
|
+
its(:path) { should == "" }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,208 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Ccp::Kvs::Tokyo::Cabinet do
|
5
|
+
let(:tmp) { tmp_path + "kvs/tokyo/cabinet" }
|
6
|
+
let(:tch) { tmp + "foo.tch" }
|
7
|
+
let(:kvs) { subject }
|
8
|
+
|
9
|
+
subject { Ccp::Kvs::Tokyo::Cabinet.new(tch) }
|
10
|
+
before { FileUtils.rm_rf(tmp) if tmp.directory? }
|
11
|
+
after { subject.close }
|
12
|
+
|
13
|
+
def put(key, val)
|
14
|
+
kvs.touch
|
15
|
+
system("tchmgr put #{kvs.path} #{key} #{val}")
|
16
|
+
end
|
17
|
+
|
18
|
+
def del(key)
|
19
|
+
kvs.touch
|
20
|
+
system("tchmgr out #{kvs.path} #{key}")
|
21
|
+
end
|
22
|
+
|
23
|
+
######################################################################
|
24
|
+
### info
|
25
|
+
|
26
|
+
describe "#info" do
|
27
|
+
context "(no files)" do
|
28
|
+
specify do
|
29
|
+
lambda { subject.info }.should raise_error(Ccp::Kvs::NotConnected)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "(file exists)" do
|
34
|
+
specify do
|
35
|
+
subject.touch
|
36
|
+
subject.info.should be_kind_of(Ccp::Kvs::Tokyo::Info)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
######################################################################
|
42
|
+
### count
|
43
|
+
|
44
|
+
describe "#count" do
|
45
|
+
context "(not opened)" do
|
46
|
+
specify { lambda { subject.count }.should raise_error(Ccp::Kvs::NotAllowed) }
|
47
|
+
end
|
48
|
+
|
49
|
+
context "(for read)" do
|
50
|
+
specify {
|
51
|
+
kvs.touch
|
52
|
+
kvs.R!()
|
53
|
+
kvs.count.should == 0
|
54
|
+
}
|
55
|
+
|
56
|
+
specify {
|
57
|
+
kvs.touch
|
58
|
+
kvs.R{ kvs.count.should == 0 }
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
context "(for write)" do
|
63
|
+
specify {
|
64
|
+
kvs.W!()
|
65
|
+
kvs.count.should == 0
|
66
|
+
}
|
67
|
+
|
68
|
+
specify {
|
69
|
+
kvs.W{ kvs.count.should == 0 }
|
70
|
+
}
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
######################################################################
|
75
|
+
### get
|
76
|
+
|
77
|
+
describe "#get" do
|
78
|
+
context "(not opened)" do
|
79
|
+
specify { lambda { kvs.get("foo") }.should raise_error(Ccp::Kvs::NotAllowed) }
|
80
|
+
end
|
81
|
+
|
82
|
+
context "(for read)[no records]" do
|
83
|
+
before { kvs.touch; kvs.R! }
|
84
|
+
specify { kvs.get("foo").should == nil }
|
85
|
+
end
|
86
|
+
|
87
|
+
context "(for read block)[no records]" do
|
88
|
+
before { kvs.touch }
|
89
|
+
specify { kvs.R { kvs.get("foo").should == nil } }
|
90
|
+
end
|
91
|
+
|
92
|
+
context "(for read)[exists]" do
|
93
|
+
before { put(:foo, 1); kvs.R! }
|
94
|
+
specify { kvs.get("foo").should == "1" }
|
95
|
+
end
|
96
|
+
|
97
|
+
context "(for read block)[exists]" do
|
98
|
+
before { put(:foo, 1); kvs.R! }
|
99
|
+
specify { kvs.R { kvs.get("foo").should == "1" } }
|
100
|
+
end
|
101
|
+
|
102
|
+
context "(for write)[no records]" do
|
103
|
+
before { kvs.W! }
|
104
|
+
specify { kvs.get("foo").should == nil }
|
105
|
+
end
|
106
|
+
|
107
|
+
context "(for write block)[no records]" do
|
108
|
+
specify { kvs.W { kvs.get("foo").should == nil } }
|
109
|
+
end
|
110
|
+
|
111
|
+
context "(for write)[exists]" do
|
112
|
+
before { put(:foo, 1); kvs.W! }
|
113
|
+
specify { kvs.get("foo").should == "1" }
|
114
|
+
end
|
115
|
+
|
116
|
+
context "(for write block)[exists]" do
|
117
|
+
before { put(:foo, 1); kvs.W! }
|
118
|
+
specify { kvs.W { kvs.get("foo").should == "1" } }
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
######################################################################
|
123
|
+
### set
|
124
|
+
|
125
|
+
describe "#set" do
|
126
|
+
before { kvs.touch }
|
127
|
+
|
128
|
+
context "(not opened)" do
|
129
|
+
specify { lambda { kvs.set("foo", 2) }.should raise_error(Ccp::Kvs::NotAllowed) }
|
130
|
+
end
|
131
|
+
|
132
|
+
context "(for read)" do
|
133
|
+
before { kvs.R! }
|
134
|
+
specify { lambda { kvs.set("foo", 2) }.should raise_error(Ccp::Kvs::NotAllowed) }
|
135
|
+
end
|
136
|
+
|
137
|
+
context "(for read block)" do
|
138
|
+
specify { lambda { kvs.R{ kvs.set("foo", 2) } }.should raise_error(Ccp::Kvs::NotAllowed) }
|
139
|
+
end
|
140
|
+
|
141
|
+
context "(for write)" do
|
142
|
+
before { kvs.W! }
|
143
|
+
specify { kvs.set("foo", 2).should == "2" }
|
144
|
+
end
|
145
|
+
|
146
|
+
context "(for write block)" do
|
147
|
+
specify { kvs.W{ kvs.set("foo", 2) }.should == "2" }
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
######################################################################
|
152
|
+
### del
|
153
|
+
|
154
|
+
describe "#del" do
|
155
|
+
before { kvs.touch; put(:foo, 3) }
|
156
|
+
|
157
|
+
context "(not opened)" do
|
158
|
+
specify { lambda { kvs.del("foo") }.should raise_error(Ccp::Kvs::NotAllowed) }
|
159
|
+
end
|
160
|
+
|
161
|
+
context "(for read)" do
|
162
|
+
before { kvs.R! }
|
163
|
+
specify { lambda { kvs.del("foo") }.should raise_error(Ccp::Kvs::NotAllowed) }
|
164
|
+
end
|
165
|
+
|
166
|
+
context "(for read block)" do
|
167
|
+
specify { lambda { kvs.R{ kvs.del("foo") } }.should raise_error(Ccp::Kvs::NotAllowed) }
|
168
|
+
end
|
169
|
+
|
170
|
+
context "(for write)" do
|
171
|
+
before { kvs.W! }
|
172
|
+
specify {
|
173
|
+
kvs.get("foo").should == "3"
|
174
|
+
kvs.del("foo").should == "3"
|
175
|
+
kvs.get("foo").should == nil
|
176
|
+
}
|
177
|
+
end
|
178
|
+
|
179
|
+
context "(for write block)" do
|
180
|
+
specify {
|
181
|
+
kvs.W {
|
182
|
+
kvs.get("foo").should == "3"
|
183
|
+
kvs.del("foo").should == "3"
|
184
|
+
kvs.get("foo").should == nil
|
185
|
+
}
|
186
|
+
}
|
187
|
+
end
|
188
|
+
|
189
|
+
context "(for write)[no records]" do
|
190
|
+
before { del(:foo); kvs.W! }
|
191
|
+
specify {
|
192
|
+
kvs.get("foo").should == nil
|
193
|
+
kvs.del("foo").should == nil
|
194
|
+
}
|
195
|
+
end
|
196
|
+
|
197
|
+
context "(for write block)[no records]" do
|
198
|
+
before { del(:foo) }
|
199
|
+
specify {
|
200
|
+
kvs.W {
|
201
|
+
kvs.get("foo").should == nil
|
202
|
+
kvs.del("foo").should == nil
|
203
|
+
}
|
204
|
+
}
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|