ccp 0.2.9 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/ccp.gemspec CHANGED
@@ -5,6 +5,7 @@ require "ccp/version"
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "ccp"
7
7
  s.version = Ccp::VERSION
8
+ s.license = 'MIT'
8
9
  s.authors = ["maiha"]
9
10
  s.email = ["maiha@wota.jp"]
10
11
  s.homepage = "http://github.com/maiha/ccp"
data/lib/ccp.rb CHANGED
@@ -14,5 +14,6 @@ module Ccp
14
14
  autoload :Receivers, 'ccp/receivers'
15
15
  autoload :Persistent, 'ccp/persistent'
16
16
  autoload :Serializers, 'ccp/serializers'
17
+ autoload :Storage, 'ccp/storage'
17
18
  autoload :Kvs, 'ccp/kvs'
18
19
  end
data/lib/ccp/kvs/core.rb CHANGED
@@ -4,6 +4,8 @@ module Ccp
4
4
  def get(k) ; raise NotImplementedError, "subclass resposibility"; end
5
5
  def set(k,v) ; raise NotImplementedError, "subclass resposibility"; end
6
6
  def del(k) ; raise NotImplementedError, "subclass resposibility"; end
7
+ def keys ; raise NotImplementedError, "subclass resposibility"; end
8
+ def read! ; keys.inject({}){|h,k| h[k] = get(k); h } ; end
7
9
 
8
10
  def open(*) ; end
9
11
  def close ; end
@@ -16,6 +18,10 @@ module Ccp
16
18
  def put(k,v) ; set(k,v) ; end
17
19
  def out(k) ; del(k) ; end
18
20
 
21
+ def codec!(c); @codec = Ccp::Serializers[c] ; self ; end
22
+ def encode(v); @codec ? @codec.encode(v) : v ; end
23
+ def decode(v); (v && @codec) ? @codec.decode(v) : v ; end
24
+
19
25
  def ext; self.class.name.split(/::/).last.to_s.downcase; end
20
26
  def self.included(klass)
21
27
  klass.class_eval do
data/lib/ccp/kvs/hash.rb CHANGED
@@ -3,14 +3,16 @@ module Ccp
3
3
  class Hash
4
4
  include Core
5
5
 
6
+ delegate :keys, :to=>"@db"
7
+
6
8
  def initialize
7
9
  @db = {}
8
10
  end
9
11
 
10
- def get(k) ; @db[k.to_s] ; end
11
- def set(k,v) ; @db[k.to_s] = v.to_s ; end
12
- def del(k) ; @db.delete(k.to_s) ; end
13
- def count ; @db.size ; end
12
+ def get(k) ; decode(@db[k.to_s]) ; end
13
+ def set(k,v) ; @db[k.to_s] = encode(v).to_s; end
14
+ def del(k) ; decode(@db.delete(k.to_s)) ; end
15
+ def count ; @db.size ; end
14
16
  end
15
17
  end
16
18
  end
data/lib/ccp/kvs/tch.rb CHANGED
@@ -7,6 +7,8 @@ module Ccp
7
7
  def set(k,v) ; W{ super }; end
8
8
  def del(k) ; W{ super }; end
9
9
  def count ; R{ super }; end
10
+ def keys ; R{ super }; end
11
+ def read! ; R{ super }; end
10
12
  end
11
13
  end
12
14
  end
@@ -19,10 +19,6 @@ module Ccp
19
19
  ######################################################################
20
20
  ### kvs
21
21
 
22
- def get(k) ; @db[k] ; end
23
- def set(k,v) ; @db[k] = v ; end
24
- def del(k) ; @db.delete(k) ; end
25
-
26
22
  def path
27
23
  file = @source.to_s.sub(/#.*$/, '') # parse "foo.tch#mode=r"
28
24
  Pathname(file)
@@ -30,7 +26,11 @@ module Ccp
30
26
 
31
27
  private
32
28
  def tokyo_error!(label = nil)
33
- raise Ccp::Kvs::Tokyo::Error, "%s%s" % [label, error_message]
29
+ raise Ccp::Kvs::Tokyo::Error, "%s%s (%s)" % [label, error_message, @source]
30
+ end
31
+
32
+ def tokyo_error?
33
+ @db.ecode != HDB::ESUCCESS
34
34
  end
35
35
 
36
36
  def error_message
@@ -16,7 +16,7 @@ module Ccp
16
16
  tryR("get")
17
17
  v = @db[k.to_s]
18
18
  if v
19
- return v
19
+ return decode(v)
20
20
  else
21
21
  if @db.ecode == HDB::ENOREC
22
22
  return nil
@@ -28,15 +28,17 @@ module Ccp
28
28
 
29
29
  def set(k,v)
30
30
  tryW("set")
31
- @db[k.to_s] = v.to_s or tokyo_error!("set(%s): " % k)
31
+ val = encode(v)
32
+ @db[k.to_s] = val or
33
+ tokyo_error!("set(%s): " % k)
32
34
  end
33
35
 
34
36
  def del(k)
35
37
  tryW("del")
36
- v = get(k)
38
+ v = @db[k.to_s]
37
39
  if v
38
- if @db.delete(k.to_s)
39
- return v
40
+ if @db.delete(k.to_s)
41
+ return decode(v)
40
42
  else
41
43
  tokyo_error!("del(%s): " % k)
42
44
  end
@@ -50,6 +52,37 @@ module Ccp
50
52
  return @db.rnum
51
53
  end
52
54
 
55
+ ######################################################################
56
+ ### iterator
57
+
58
+ def each(&block)
59
+ each_keys do |key|
60
+ block.call(get(key))
61
+ end
62
+ end
63
+
64
+ def each_pair(&block)
65
+ each_keys do |key|
66
+ block.call(key, get(key))
67
+ end
68
+ end
69
+
70
+ def each_keys(&block)
71
+ tryR("each_keys")
72
+ @db.iterinit
73
+ while key = @db.iternext
74
+ block.call(key)
75
+ end
76
+ end
77
+
78
+ def keys
79
+ array = []
80
+ each_keys do |key|
81
+ array << key
82
+ end
83
+ return array
84
+ end
85
+
53
86
  end
54
87
  end
55
88
  end
@@ -0,0 +1,62 @@
1
+ module Ccp
2
+ class Storage
3
+ NotFound = Class.new(RuntimeError)
4
+
5
+ def self.load(path)
6
+ array = path.split(".")
7
+ kvs = Ccp::Kvs[array.pop]
8
+ codec = Ccp::Serializers[array.pop]
9
+ return new(path, kvs, codec)
10
+ end
11
+
12
+ attr_reader :source, :kvs, :codec, :path
13
+ delegate :get, :set, :del, :keys, :read!, :to=>"@kvs"
14
+
15
+ def initialize(source, kvs, codec)
16
+ @source = source
17
+ @codec = codec
18
+ @path = Pathname(source)
19
+ @kvs = kvs.new(source).codec!(codec)
20
+ @tables = {}
21
+ end
22
+
23
+ ######################################################################
24
+ ### meta kvs
25
+
26
+ def table_names
27
+ tables # force to update @tables
28
+ @tables.keys
29
+ end
30
+
31
+ def tables
32
+ files = Dir.chdir(@path) { Dir["**/*.#{@kvs.ext}"] }
33
+ files.map{|file|
34
+ name = file.sub(/(\.#{@codec.ext})?(\.#{@kvs.ext})?$/, '')
35
+ table(name, file)
36
+ }
37
+ end
38
+
39
+ def table(name, file = nil)
40
+ @tables[name.to_s] ||= (
41
+ file ||= "%s.%s.%s" % [name, @codec.ext, @kvs.ext]
42
+ Storage.new((@path + file).to_s, @kvs.class, @codec)
43
+ )
44
+ end
45
+
46
+ ######################################################################
47
+ ### kvs
48
+
49
+ def read!
50
+ if @path.directory?
51
+ tables
52
+ hash = {}
53
+ @tables.each_pair do |k, kvs|
54
+ hash[k] = kvs.read!
55
+ end
56
+ return hash
57
+ else
58
+ return @kvs.read!
59
+ end
60
+ end
61
+ end
62
+ end
data/lib/ccp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Ccp
2
- VERSION = "0.2.9"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -8,5 +8,6 @@ describe Ccp::Kvs::Core do
8
8
  it { should respond_to("get") }
9
9
  it { should respond_to("set") }
10
10
  it { should respond_to("del") }
11
+ it { should respond_to("keys") }
11
12
  it { should respond_to("touch") }
12
13
  end
data/spec/kvs/kvs_spec.rb CHANGED
@@ -1,15 +1,14 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  require 'spec_helper'
3
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
4
+ kvs_args = {}
5
+ kvs_args["tch"] = "#{tmp_path}/kvs/foo.tch"
6
+
7
+ Ccp::Kvs.each do |klass|
8
+ describe klass do
10
9
  before { FileUtils.rm_rf(tmp_path) if tmp_path.directory? }
11
10
 
12
- its(:ext) { should == kvs.class.ext }
11
+ let(:kvs) { kvs_args[klass.ext] ? klass.new(*kvs_args[klass.ext]) : klass.new }
13
12
 
14
13
  describe "#get, #set, #out" do
15
14
  let(:key) { raise "Sub context responsibility" }
@@ -34,11 +33,59 @@ kvss.each do |kvs|
34
33
  it { should be }
35
34
  end
36
35
 
37
- context ":foo => 2" do
36
+ context ":foo => '2'" do
38
37
  let(:key) { :foo }
39
- let(:val) { 2 }
38
+ let(:val) { "2" }
40
39
  it { should be }
41
40
  end
42
41
  end
42
+
43
+ describe "#get, #set, #ou (with msgpack)t" do
44
+ let(:key) { raise "Sub context responsibility" }
45
+ let(:val) { raise "Sub context responsibility" }
46
+
47
+ before { kvs.codec! :msgpack }
48
+
49
+ subject {
50
+ k = kvs
51
+ k.touch
52
+ k.count.should == 0
53
+ k.get(key).should == nil
54
+ k.set(key, val)
55
+ k.get(key).should == val
56
+ k.count.should == 1
57
+ k.out(key).should == val
58
+ k.get(key).should == nil
59
+ k
60
+ }
61
+
62
+ context "nil" do
63
+ let(:key) { :foo }
64
+ let(:val) { nil }
65
+ it { should be }
66
+ end
67
+
68
+ context ":foo => [true, nil]" do
69
+ let(:key) { :foo }
70
+ let(:val) { [true, nil] }
71
+ it { should be }
72
+ end
73
+ end
74
+
75
+ describe "#read!" do
76
+ specify do
77
+ kvs.touch
78
+ kvs.codec! :json
79
+ kvs.set(:a, 1)
80
+ kvs.set(:b, ["x", 0])
81
+ kvs.read!.should == {"a"=>1, "b"=>["x", 0]}
82
+ end
83
+ end
84
+
85
+ describe "#codec!" do
86
+ specify "return self" do
87
+ kvs.codec!(:msgpack).should == kvs
88
+ end
89
+ end
43
90
  end
44
91
  end
@@ -140,11 +140,11 @@ describe Ccp::Kvs::Tokyo::Cabinet do
140
140
 
141
141
  context "(for write)" do
142
142
  before { kvs.W! }
143
- specify { kvs.set("foo", 2).should == "2" }
143
+ specify { lambda { kvs.set("foo", 2) }.should_not raise_error }
144
144
  end
145
145
 
146
146
  context "(for write block)" do
147
- specify { kvs.W{ kvs.set("foo", 2) }.should == "2" }
147
+ specify { lambda { kvs.W{ kvs.set("foo", 2) }.should_not raise_error } }
148
148
  end
149
149
  end
150
150
 
@@ -205,4 +205,17 @@ describe Ccp::Kvs::Tokyo::Cabinet do
205
205
  end
206
206
  end
207
207
 
208
+ ######################################################################
209
+ ### keys
210
+
211
+ describe "#keys" do
212
+ specify do
213
+ put(:foo, 1)
214
+ put(:bar, 2)
215
+ put(:baz, 3)
216
+
217
+ kvs.R!
218
+ kvs.keys.sort.should == %w( bar baz foo )
219
+ end
220
+ end
208
221
  end
@@ -0,0 +1,72 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe Ccp::Storage do
5
+ specify ".load" do
6
+ Ccp::Storage.should respond_to(:load)
7
+ end
8
+
9
+ describe ".load" do
10
+ context "('tmp/foo.json.tch')" do
11
+ subject { Ccp::Storage.load('tmp/foo.json.tch') }
12
+ its(:source) { should == 'tmp/foo.json.tch' }
13
+ its(:kvs) { should be_kind_of(Ccp::Kvs::Tch) }
14
+ its(:codec) { should == Ccp::Serializers::Json }
15
+
16
+ describe "table(:foo)" do
17
+ subject { Ccp::Storage.load('tmp/foo.json.tch').table(:bar) }
18
+ its(:source) { should == 'tmp/foo.json.tch/bar.json.tch' }
19
+ its(:kvs) { should be_kind_of(Ccp::Kvs::Tch) }
20
+ its(:codec) { should == Ccp::Serializers::Json }
21
+ end
22
+ end
23
+
24
+ context "('tmp/foo.msgpack.tch')" do
25
+ subject { Ccp::Storage.load('tmp/foo.msgpack.tch') }
26
+ its(:source) { should == 'tmp/foo.msgpack.tch' }
27
+ its(:kvs) { should be_kind_of(Ccp::Kvs::Tch) }
28
+ its(:codec) { should == Ccp::Serializers::Msgpack }
29
+ end
30
+ end
31
+
32
+ describe "#read!" do
33
+ before { FileUtils.rm_rf(tmp_path) if tmp_path.directory? }
34
+
35
+ context "(file)" do
36
+ let(:tch) { tmp_path + "foo.json.tch" }
37
+ subject { Ccp::Storage.new(tch, Ccp::Kvs::Tch, Ccp::Serializers::Json) }
38
+ before {
39
+ tch.parent.mkpath
40
+ system("tchmgr create #{tch}")
41
+ system("tchmgr put #{tch} a '[1,2]'")
42
+ system("tchmgr put #{tch} b 0.1")
43
+ }
44
+ specify do
45
+ subject.read!.should == {"a" => [1, 2], "b" => 0.1}
46
+ end
47
+ end
48
+
49
+ context "(directory)" do
50
+ let(:tch) { tmp_path + "foo.json.tch" }
51
+ subject { Ccp::Storage.new(tch, Ccp::Kvs::Tch, Ccp::Serializers::Json) }
52
+ before {
53
+ tch.mkpath
54
+ system("tchmgr create #{tch}/a.json.tch")
55
+ system("tchmgr put #{tch}/a.json.tch x '[1,2]'")
56
+ system("tchmgr put #{tch}/a.json.tch y []")
57
+ system("tchmgr create #{tch}/b.json.tch")
58
+ system("tchmgr put #{tch}/b.json.tch y 0.1")
59
+ }
60
+ specify do
61
+ subject.read!.should == {
62
+ "a" => {"x" => [1, 2], "y" => []},
63
+ "b" => {"y" => 0.1},
64
+ }
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ # it { should respond_to(:tables) }
71
+ # it { should respond_to(:table) }
72
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ccp
3
3
  version: !ruby/object:Gem::Version
4
- hash: 5
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 2
9
- - 9
10
- version: 0.2.9
8
+ - 3
9
+ - 0
10
+ version: 0.3.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - maiha
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2013-08-22 00:00:00 Z
18
+ date: 2013-08-23 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: activesupport
@@ -220,6 +220,7 @@ files:
220
220
  - lib/ccp/serializers/json.rb
221
221
  - lib/ccp/serializers/msgpack.rb
222
222
  - lib/ccp/serializers/yaml.rb
223
+ - lib/ccp/storage.rb
223
224
  - lib/ccp/utils.rb
224
225
  - lib/ccp/utils/colorize.rb
225
226
  - lib/ccp/utils/fixture_options.rb
@@ -243,7 +244,6 @@ files:
243
244
  - spec/kvs/core_spec.rb
244
245
  - spec/kvs/kvs_spec.rb
245
246
  - spec/kvs/lookup_spec.rb
246
- - spec/kvs/tch_spec.rb
247
247
  - spec/kvs/tokyo/cabinet_spec.rb
248
248
  - spec/kvs/tokyo/info_spec.rb
249
249
  - spec/models.rb
@@ -264,9 +264,10 @@ files:
264
264
  - spec/serializers/lookup_spec.rb
265
265
  - spec/serializers/serializer_spec.rb
266
266
  - spec/spec_helper.rb
267
+ - spec/storage/loadable_spec.rb
267
268
  homepage: http://github.com/maiha/ccp
268
- licenses: []
269
-
269
+ licenses:
270
+ - MIT
270
271
  post_install_message:
271
272
  rdoc_options: []
272
273
 
data/spec/kvs/tch_spec.rb DELETED
@@ -1,19 +0,0 @@
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