metry 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. data/History.txt +6 -0
  2. data/Manifest.txt +14 -69
  3. data/TODO +2 -3
  4. data/cucumber.yml +1 -0
  5. data/example/example.rb +1 -1
  6. data/features/psycho/dashboard.feature +17 -0
  7. data/features/psycho/goals.feature +24 -0
  8. data/features/psycho/visitor_tracking.feature +32 -0
  9. data/features/step_definitions/goals.rb +3 -0
  10. data/features/step_definitions/tracking.rb +1 -1
  11. data/features/step_definitions/web.rb +14 -2
  12. data/features/support/env.rb +4 -0
  13. data/lib/metry.rb +4 -6
  14. data/lib/metry/experiment.rb +6 -8
  15. data/lib/metry/psycho.rb +112 -0
  16. data/lib/metry/psycho/dashboard.erb +14 -0
  17. data/lib/metry/psycho/layout.erb +8 -0
  18. data/lib/metry/psycho/new_goal.erb +9 -0
  19. data/lib/metry/psycho/visitor.erb +7 -0
  20. data/lib/metry/rack/tracking.rb +17 -13
  21. data/lib/metry/storage.rb +116 -0
  22. data/radiant/example/features/metry.feature +8 -8
  23. data/radiant/example/features/psycho.feature +13 -0
  24. data/radiant/example/features/step_definitions/experiments.rb +2 -2
  25. data/radiant/example/features/step_definitions/tracking.rb +1 -1
  26. data/radiant/example/features/support/env.rb +3 -0
  27. data/radiant/extension/lib/metry_authenticator.rb +30 -0
  28. data/radiant/extension/lib/metry_tags.rb +2 -1
  29. data/radiant/extension/metry_extension.rb +1 -1
  30. data/test/{test_tokyo.rb → test_storage.rb} +3 -3
  31. metadata +17 -72
  32. data/lib/metry/memory.rb +0 -27
  33. data/lib/metry/tokyo.rb +0 -181
  34. data/vendor/rufus-tokyo/CHANGELOG.txt +0 -112
  35. data/vendor/rufus-tokyo/CREDITS.txt +0 -27
  36. data/vendor/rufus-tokyo/LICENSE.txt +0 -21
  37. data/vendor/rufus-tokyo/README.txt +0 -310
  38. data/vendor/rufus-tokyo/Rakefile +0 -118
  39. data/vendor/rufus-tokyo/TODO.txt +0 -25
  40. data/vendor/rufus-tokyo/doc/decision_table.numbers +0 -0
  41. data/vendor/rufus-tokyo/doc/rdoc-style.css +0 -320
  42. data/vendor/rufus-tokyo/lib/rufus-edo.rb +0 -3
  43. data/vendor/rufus-tokyo/lib/rufus-tokyo.rb +0 -3
  44. data/vendor/rufus-tokyo/lib/rufus/edo.rb +0 -39
  45. data/vendor/rufus-tokyo/lib/rufus/edo/README.txt +0 -106
  46. data/vendor/rufus-tokyo/lib/rufus/edo/cabcore.rb +0 -333
  47. data/vendor/rufus-tokyo/lib/rufus/edo/cabinet/abstract.rb +0 -219
  48. data/vendor/rufus-tokyo/lib/rufus/edo/cabinet/table.rb +0 -159
  49. data/vendor/rufus-tokyo/lib/rufus/edo/error.rb +0 -36
  50. data/vendor/rufus-tokyo/lib/rufus/edo/ntyrant.rb +0 -4
  51. data/vendor/rufus-tokyo/lib/rufus/edo/ntyrant/abstract.rb +0 -137
  52. data/vendor/rufus-tokyo/lib/rufus/edo/ntyrant/table.rb +0 -141
  53. data/vendor/rufus-tokyo/lib/rufus/edo/tabcore.rb +0 -567
  54. data/vendor/rufus-tokyo/lib/rufus/tokyo.rb +0 -58
  55. data/vendor/rufus-tokyo/lib/rufus/tokyo/cabinet/abstract.rb +0 -568
  56. data/vendor/rufus-tokyo/lib/rufus/tokyo/cabinet/lib.rb +0 -230
  57. data/vendor/rufus-tokyo/lib/rufus/tokyo/cabinet/table.rb +0 -753
  58. data/vendor/rufus-tokyo/lib/rufus/tokyo/cabinet/util.rb +0 -425
  59. data/vendor/rufus-tokyo/lib/rufus/tokyo/config.rb +0 -161
  60. data/vendor/rufus-tokyo/lib/rufus/tokyo/dystopia.rb +0 -43
  61. data/vendor/rufus-tokyo/lib/rufus/tokyo/dystopia/lib.rb +0 -65
  62. data/vendor/rufus-tokyo/lib/rufus/tokyo/dystopia/words.rb +0 -71
  63. data/vendor/rufus-tokyo/lib/rufus/tokyo/hmethods.rb +0 -111
  64. data/vendor/rufus-tokyo/lib/rufus/tokyo/query.rb +0 -102
  65. data/vendor/rufus-tokyo/lib/rufus/tokyo/transactions.rb +0 -74
  66. data/vendor/rufus-tokyo/lib/rufus/tokyo/ttcommons.rb +0 -59
  67. data/vendor/rufus-tokyo/lib/rufus/tokyo/tyrant.rb +0 -35
  68. data/vendor/rufus-tokyo/lib/rufus/tokyo/tyrant/abstract.rb +0 -146
  69. data/vendor/rufus-tokyo/lib/rufus/tokyo/tyrant/lib.rb +0 -153
  70. data/vendor/rufus-tokyo/lib/rufus/tokyo/tyrant/table.rb +0 -162
  71. data/vendor/rufus-tokyo/rufus-tokyo.gemspec +0 -25
  72. data/vendor/rufus-tokyo/spec/cabinet_spec.rb +0 -472
  73. data/vendor/rufus-tokyo/spec/cabinetconfig_spec.rb +0 -82
  74. data/vendor/rufus-tokyo/spec/edo_cabinet_spec.rb +0 -447
  75. data/vendor/rufus-tokyo/spec/edo_ntyrant_spec.rb +0 -299
  76. data/vendor/rufus-tokyo/spec/edo_ntyrant_table_spec.rb +0 -462
  77. data/vendor/rufus-tokyo/spec/edo_table_spec.rb +0 -560
  78. data/vendor/rufus-tokyo/spec/hmethods_spec.rb +0 -44
  79. data/vendor/rufus-tokyo/spec/incr.lua +0 -20
  80. data/vendor/rufus-tokyo/spec/spec.rb +0 -9
  81. data/vendor/rufus-tokyo/spec/spec_base.rb +0 -23
  82. data/vendor/rufus-tokyo/spec/start_tyrants.sh +0 -26
  83. data/vendor/rufus-tokyo/spec/stop_tyrants.sh +0 -9
  84. data/vendor/rufus-tokyo/spec/table_spec.rb +0 -567
  85. data/vendor/rufus-tokyo/spec/tyrant_spec.rb +0 -309
  86. data/vendor/rufus-tokyo/spec/tyrant_table_spec.rb +0 -479
  87. data/vendor/rufus-tokyo/spec/util_list_spec.rb +0 -200
  88. data/vendor/rufus-tokyo/spec/util_map_spec.rb +0 -132
  89. data/vendor/rufus-tokyo/tasks/dev.rb +0 -70
  90. data/vendor/rufus-tokyo/test/bm0.rb +0 -353
  91. data/vendor/rufus-tokyo/test/bm1_compression.rb +0 -54
  92. data/vendor/rufus-tokyo/test/con0.rb +0 -30
  93. data/vendor/rufus-tokyo/test/mem.rb +0 -49
  94. data/vendor/rufus-tokyo/test/mem1.rb +0 -44
  95. data/vendor/rufus-tokyo/test/readme0.rb +0 -17
  96. data/vendor/rufus-tokyo/test/readme1.rb +0 -21
  97. data/vendor/rufus-tokyo/test/readme2.rb +0 -15
  98. data/vendor/rufus-tokyo/test/readme3.rb +0 -24
  99. data/vendor/rufus-tokyo/test/readmes_test.sh +0 -17
@@ -1,230 +0,0 @@
1
- #--
2
- # Copyright (c) 2009, John Mettraux, jmettraux@gmail.com
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining a copy
5
- # of this software and associated documentation files (the "Software"), to deal
6
- # in the Software without restriction, including without limitation the rights
7
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- # copies of the Software, and to permit persons to whom the Software is
9
- # furnished to do so, subject to the following conditions:
10
- #
11
- # The above copyright notice and this permission notice shall be included in
12
- # all copies or substantial portions of the Software.
13
- #
14
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
- # THE SOFTWARE.
21
- #
22
- # Made in Japan.
23
- #++
24
-
25
-
26
- module Rufus::Tokyo
27
-
28
- #
29
- # The libtokyocabinet.so methods get bound to this module
30
- #
31
- module CabinetLib #:nodoc#
32
- extend FFI::Library
33
-
34
- #
35
- # find Tokyo Cabinet lib
36
-
37
- paths = Array(ENV['TOKYO_CABINET_LIB'] || %w{
38
- /usr/lib/libtokyocabinet.so
39
- /opt/local/lib/libtokyocabinet.dylib
40
- /opt/local/lib/libtokyocabinet.so
41
- /usr/local/lib/libtokyocabinet.dylib
42
- /usr/local/lib/libtokyocabinet.so
43
- })
44
-
45
- begin
46
-
47
- ffi_lib(*paths)
48
-
49
- rescue LoadError => le
50
- raise(
51
- "didn't find Tokyo Cabinet libs on your system. " +
52
- "Please install Tokyo Cabinet (http://tokyocabinet.sf.net) " +
53
- "(see also http://openwferu.rubyforge.org/tokyo.html)"
54
- )
55
- end
56
-
57
- class << self
58
- alias :attfunc :attach_function
59
- end
60
-
61
- #
62
- # maybe put that in a standalone c_lib.rb
63
-
64
- # length of a string
65
- #
66
- attfunc :strlen, [ :string ], :int
67
-
68
- # frees a mem zone (TC style)
69
- #
70
- attfunc :tcfree, [ :pointer ], :void
71
-
72
- #
73
- # tcadb functions
74
- #
75
- # http://tokyocabinet.sourceforge.net/spex-en.html#tcadbapi
76
-
77
- attfunc :tcadbnew, [], :pointer
78
-
79
- attfunc :tcadbopen, [ :pointer, :string ], :int
80
- attfunc :abs_close, :tcadbclose, [ :pointer ], :int
81
-
82
- attfunc :abs_del, :tcadbdel, [ :pointer ], :void
83
-
84
- attfunc :abs_rnum, :tcadbrnum, [ :pointer ], :uint64
85
- attfunc :abs_size, :tcadbsize, [ :pointer ], :uint64
86
-
87
- attfunc :abs_put, :tcadbput, [ :pointer, :pointer, :int, :pointer, :int ], :int
88
-
89
- attfunc :abs_get, :tcadbget, [ :pointer, :pointer, :int, :pointer ], :pointer
90
-
91
- attfunc :abs_out, :tcadbout, [ :pointer, :pointer, :int ], :int
92
-
93
- attfunc :abs_putkeep, :tcadbputkeep, [ :pointer, :pointer, :int, :pointer, :int ], :int
94
-
95
- attfunc :abs_iterinit, :tcadbiterinit, [ :pointer ], :int
96
- attfunc :abs_iternext, :tcadbiternext, [ :pointer, :pointer ], :pointer
97
-
98
- attfunc :abs_vanish, :tcadbvanish, [ :pointer ], :int
99
-
100
- attfunc :abs_sync, :tcadbsync, [ :pointer ], :int
101
- attfunc :abs_copy, :tcadbcopy, [ :pointer, :string ], :int
102
-
103
- attfunc :abs_fwmkeys, :tcadbfwmkeys, [ :pointer, :pointer, :int, :int ], :pointer
104
-
105
- attfunc :tcadbmisc, [ :pointer, :string, :pointer ], :pointer
106
-
107
- attfunc :addint, :tcadbaddint, [ :pointer, :string, :int, :int ], :int
108
- attfunc :adddouble, :tcadbadddouble, [ :pointer, :string, :int, :double ], :double
109
-
110
- begin # since TC 1.4.13
111
- attfunc :tcadbtranbegin, [ :pointer ], :int
112
- attfunc :tcadbtrancommit, [ :pointer ], :int
113
- attfunc :tcadbtranabort, [ :pointer ], :int
114
- rescue FFI::NotFoundError => nfe
115
- end
116
-
117
- #
118
- # tctdb functions
119
- #
120
- # http://tokyocabinet.sourceforge.net/spex-en.html#tctdbapi
121
-
122
- attfunc :tctdbnew, [], :pointer
123
- attfunc :tctdbsetmutex, [ :pointer ], :int
124
- attfunc :tctdbtune, [ :pointer, :uint64, :uint8, :uint8, :uint8 ], :int
125
- attfunc :tctdbsetcache, [ :pointer, :uint32, :uint32, :uint32 ], :int
126
- attfunc :tctdbsetxmsiz, [ :pointer, :uint64 ], :int
127
-
128
- begin # since TC 1.4.21
129
- attfunc :tctdbsetdfunit, [ :pointer, :uint32 ], :int
130
- rescue FFI::NotFoundError => nfe
131
- end
132
-
133
- attfunc :tctdbopen, [ :pointer, :string, :int ], :int
134
-
135
- attfunc :tab_close, :tctdbclose, [ :pointer ], :int
136
-
137
- attfunc :tab_genuid, :tctdbgenuid, [ :pointer ], :int64
138
-
139
- attfunc :tab_get, :tctdbget, [ :pointer, :pointer, :int ], :pointer
140
-
141
- attfunc :tab_iterinit, :tctdbiterinit, [ :pointer ], :int
142
- attfunc :tab_iternext, :tctdbiternext, [ :pointer, :pointer ], :pointer
143
-
144
- attfunc :tab_put, :tctdbput, [ :pointer, :pointer, :int, :pointer ], :int
145
-
146
- #attfunc :tctdbput3, [ :pointer, :string, :string ], :int
147
- # not using it anymore, Ruby can turn an array into a hash so easily
148
-
149
- attfunc :tab_out, :tctdbout, [ :pointer, :string, :int ], :int
150
-
151
- attfunc :tab_ecode, :tctdbecode, [ :pointer ], :int
152
- attfunc :tab_errmsg, :tctdberrmsg, [ :int ], :string
153
-
154
- attfunc :tab_del, :tctdbdel, [ :pointer ], :void
155
-
156
- attfunc :tab_rnum, :tctdbrnum, [ :pointer ], :uint64
157
-
158
- attfunc :tab_vanish, :tctdbvanish, [ :pointer ], :int
159
-
160
- attfunc :tab_setindex, :tctdbsetindex, [ :pointer, :string, :int ], :int
161
-
162
- attfunc :tctdbtranbegin, [ :pointer ], :int
163
- attfunc :tctdbtrancommit, [ :pointer ], :int
164
- attfunc :tctdbtranabort, [ :pointer ], :int
165
-
166
- attfunc :tab_fwmkeys, :tctdbfwmkeys, [ :pointer, :pointer, :int, :int ], :pointer
167
-
168
- #
169
- # tctdbqry functions
170
- #
171
- # http://tokyocabinet.sourceforge.net/spex-en.html#tctdbapi
172
-
173
- attfunc :qry_new, :tctdbqrynew, [ :pointer ], :pointer
174
- attfunc :qry_del, :tctdbqrydel, [ :pointer ], :void
175
-
176
- attfunc :qry_addcond, :tctdbqryaddcond, [ :pointer, :string, :int, :string ], :void
177
- attfunc :qry_setorder, :tctdbqrysetorder, [ :pointer, :string, :int ], :void
178
-
179
- callback :TDBQRYPROC, [:pointer, :int, :pointer, :pointer], :int
180
- attfunc :qry_proc, :tctdbqryproc, [ :pointer, :TDBQRYPROC, :pointer], :int
181
-
182
-
183
- begin # since TC 1.4.10
184
- attfunc :qry_setmax, :tctdbqrysetmax, [ :pointer, :int ], :void
185
- rescue FFI::NotFoundError => nfe
186
- attfunc :qry_setlimit, :tctdbqrysetlimit, [ :pointer, :int, :int ], :void
187
- end
188
-
189
- attfunc :qry_search, :tctdbqrysearch, [ :pointer ], :pointer
190
- attfunc :qry_searchout, :tctdbqrysearchout, [ :pointer ], :int
191
-
192
- begin # since TC 1.4.12
193
- attfunc :qry_count, :tctdbqrycount, [ :pointer ], :int
194
- rescue FFI::NotFoundError => nfe
195
- end
196
-
197
- #
198
- # tcmap functions
199
- #
200
- # http://tokyocabinet.sourceforge.net/spex-en.html#tcutilapi
201
-
202
- attfunc :tcmapnew, [], :pointer
203
- attfunc :tcmapput, [ :pointer, :pointer, :int, :pointer, :int ], :void
204
- attfunc :tcmapout, [ :pointer, :pointer, :int ], :int
205
- attfunc :tcmapclear, [ :pointer ], :void
206
- attfunc :tcmapdel, [ :pointer ], :void
207
- attfunc :tcmapget, [ :pointer, :pointer, :int, :pointer ], :pointer
208
- attfunc :tcmapiterinit, [ :pointer ], :void
209
- attfunc :tcmapiternext, [ :pointer, :pointer ], :pointer
210
- attfunc :tcmaprnum, [ :pointer ], :uint64
211
-
212
- #
213
- # tclist functions
214
- #
215
- # http://tokyocabinet.sourceforge.net/spex-en.html#tcutilapi
216
-
217
- attfunc :tclistnew, [], :pointer
218
- attfunc :tclistnum, [ :pointer ], :int
219
- attfunc :tclistval, [ :pointer, :int, :pointer ], :pointer
220
- attfunc :tclistpush, [ :pointer, :pointer, :int ], :void
221
- attfunc :tclistpop, [ :pointer, :pointer ], :pointer
222
- attfunc :tclistshift, [ :pointer, :pointer ], :pointer
223
- attfunc :tclistunshift, [ :pointer, :pointer, :int ], :void
224
- attfunc :tclistover, [ :pointer, :int, :pointer, :int ], :void
225
- attfunc :tclistremove, [ :pointer, :int, :pointer ], :pointer
226
- attfunc :tclistdel, [ :pointer ], :void
227
- end
228
-
229
- end
230
-
@@ -1,753 +0,0 @@
1
- #--
2
- # Copyright (c) 2009, John Mettraux, jmettraux@gmail.com
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining a copy
5
- # of this software and associated documentation files (the "Software"), to deal
6
- # in the Software without restriction, including without limitation the rights
7
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- # copies of the Software, and to permit persons to whom the Software is
9
- # furnished to do so, subject to the following conditions:
10
- #
11
- # The above copyright notice and this permission notice shall be included in
12
- # all copies or substantial portions of the Software.
13
- #
14
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
- # THE SOFTWARE.
21
- #
22
- # Made in Japan.
23
- #++
24
-
25
-
26
- require 'rufus/tokyo/query'
27
- require 'rufus/tokyo/config'
28
- require 'rufus/tokyo/transactions'
29
-
30
-
31
- module Rufus::Tokyo
32
-
33
- #
34
- # A 'table' a table database.
35
- #
36
- # http://alpha.mixi.co.jp/blog/?p=290
37
- # http://tokyocabinet.sourceforge.net/spex-en.html#tctdbapi
38
- #
39
- # A short example :
40
- #
41
- # require 'rubygems'
42
- # require 'rufus/tokyo/cabinet/table'
43
- #
44
- # t = Rufus::Tokyo::Table.new('table.tdb', :create, :write)
45
- # # '.tdb' suffix is a must
46
- #
47
- # t['pk0'] = { 'name' => 'alfred', 'age' => '22' }
48
- # t['pk1'] = { 'name' => 'bob', 'age' => '18' }
49
- # t['pk2'] = { 'name' => 'charly', 'age' => '45' }
50
- # t['pk3'] = { 'name' => 'doug', 'age' => '77' }
51
- # t['pk4'] = { 'name' => 'ephrem', 'age' => '32' }
52
- #
53
- # p t.query { |q|
54
- # q.add_condition 'age', :numge, '32'
55
- # q.order_by 'age'
56
- # q.limit 2
57
- # }
58
- # # => [ {"name"=>"ephrem", :pk=>"pk4", "age"=>"32"},
59
- # # {"name"=>"charly", :pk=>"pk2", "age"=>"45"} ]
60
- #
61
- # t.close
62
- #
63
- class Table
64
-
65
- include HashMethods
66
- include CabinetConfig
67
-
68
- include Transactions
69
- # this class has tranbegin/trancommit/tranabort so let's include the
70
- # transaction mixin
71
-
72
- # Creates a Table instance (creates or opens it depending on the args)
73
- #
74
- # For example,
75
- #
76
- # t = Rufus::Tokyo::Table.new('table.tdb')
77
- # # '.tdb' suffix is a must
78
- #
79
- # will create the table.tdb (or simply open it if already present)
80
- # and make sure we have write access to it.
81
- #
82
- # == parameters
83
- #
84
- # Parameters can be set in the path or via the optional params hash (like
85
- # in Rufus::Tokyo::Cabinet)
86
- #
87
- # * :mode a set of chars ('r'ead, 'w'rite, 'c'reate, 't'runcate,
88
- # 'e' non locking, 'f' non blocking lock), default is 'wc'
89
- # * :opts a set of chars ('l'arge, 'd'eflate, 'b'zip2, 't'cbs)
90
- # (usually empty or something like 'ld' or 'lb')
91
- #
92
- # * :bnum number of elements of the bucket array
93
- # * :apow size of record alignment by power of 2 (defaults to 4)
94
- # * :fpow maximum number of elements of the free block pool by
95
- # power of 2 (defaults to 10)
96
- # * :mutex when set to true, makes sure only 1 thread at a time
97
- # accesses the table (well, Ruby, global thread lock, ...)
98
- #
99
- # * :rcnum specifies the maximum number of records to be cached.
100
- # If it is not more than 0, the record cache is disabled.
101
- # It is disabled by default.
102
- # * :lcnum specifies the maximum number of leaf nodes to be cached.
103
- # If it is not more than 0, the default value is specified.
104
- # The default value is 2048.
105
- # * :ncnum specifies the maximum number of non-leaf nodes to be
106
- # cached. If it is not more than 0, the default value is
107
- # specified. The default value is 512.
108
- #
109
- # * :xmsiz specifies the size of the extra mapped memory. If it is
110
- # not more than 0, the extra mapped memory is disabled.
111
- # The default size is 67108864.
112
- #
113
- # * :dfunit unit step number. If it is not more than 0,
114
- # the auto defragmentation is disabled. (Since TC 1.4.21)
115
- #
116
- # Some examples :
117
- #
118
- # t = Rufus::Tokyo::Table.new('table.tdb')
119
- # t = Rufus::Tokyo::Table.new('table.tdb#mode=r')
120
- # t = Rufus::Tokyo::Table.new('table.tdb', :mode => 'r')
121
- # t = Rufus::Tokyo::Table.new('table.tdb#opts=ld#mode=r')
122
- # t = Rufus::Tokyo::Table.new('table.tdb', :opts => 'ld', :mode => 'r')
123
- #
124
- def initialize (path, params={})
125
-
126
- conf = determine_conf(path, params, :table)
127
-
128
- @db = lib.tctdbnew
129
-
130
- #
131
- # tune table
132
-
133
- libcall(:tctdbsetmutex) if conf[:mutex]
134
-
135
- libcall(:tctdbtune, conf[:bnum], conf[:apow], conf[:fpow], conf[:opts])
136
-
137
- # TODO : set indexes here... well, there is already #set_index
138
- #conf[:indexes]...
139
-
140
- libcall(:tctdbsetcache, conf[:rcnum], conf[:lcnum], conf[:ncnum])
141
-
142
- libcall(:tctdbsetxmsiz, conf[:xmsiz])
143
-
144
- libcall(:tctdbsetdfunit, conf[:dfunit]) \
145
- if lib.respond_to?(:tctdbsetdfunit) # TC >= 1.4.21
146
-
147
- #
148
- # open table
149
-
150
- @path = conf[:path]
151
-
152
- libcall(:tctdbopen, @path, conf[:mode])
153
- end
154
-
155
- # Using the cabinet lib
156
- #
157
- def lib
158
-
159
- CabinetLib
160
- end
161
-
162
- # Returns the path to the table.
163
- #
164
- def path
165
-
166
- @path
167
- end
168
-
169
- # Closes the table (and frees the datastructure allocated for it),
170
- # returns true in case of success.
171
- #
172
- def close
173
-
174
- result = lib.tab_close(@db)
175
- lib.tab_del(@db)
176
-
177
- (result == 1)
178
- end
179
-
180
- # Generates a unique id (in the context of this Table instance)
181
- #
182
- def generate_unique_id
183
-
184
- lib.tab_genuid(@db)
185
- end
186
- alias :genuid :generate_unique_id
187
-
188
- INDEX_TYPES = {
189
- :lexical => 0,
190
- :decimal => 1,
191
- :void => 9999,
192
- :remove => 9999,
193
- :keep => 1 << 24
194
- }
195
-
196
- # Sets an index on a column of the table.
197
- #
198
- # Types maybe be :lexical or :decimal, use :keep to "add" and
199
- # :remove (or :void) to "remove" an index.
200
- #
201
- # If column_name is :pk or "", the index will be set on the primary key.
202
- #
203
- # Returns true in case of success.
204
- #
205
- def set_index (column_name, *types)
206
-
207
- column_name = '' if column_name == :pk
208
-
209
- i = types.inject(0) { |i, t| i = i | INDEX_TYPES[t]; i }
210
-
211
- (lib.tab_setindex(@db, column_name, i) == 1)
212
- end
213
-
214
- # Inserts a record in the table db
215
- #
216
- # table['pk0'] = [ 'name', 'fred', 'age', '45' ]
217
- # table['pk1'] = { 'name' => 'jeff', 'age' => '46' }
218
- #
219
- # Accepts both a hash or an array (expects the array to be of the
220
- # form [ key, value, key, value, ... ] else it will raise
221
- # an ArgumentError)
222
- #
223
- # Raises an error in case of failure.
224
- #
225
- def []= (pk, h_or_a)
226
-
227
- m = Rufus::Tokyo::Map[h_or_a]
228
-
229
- r = lib.tab_put(@db, pk, Rufus::Tokyo.blen(pk), m.pointer)
230
-
231
- m.free
232
-
233
- (r == 1) || raise_error # raising potential error after freeing map
234
-
235
- h_or_a
236
- end
237
-
238
- # Removes an entry in the table
239
- #
240
- # (might raise an error if the delete itself failed, but returns nil
241
- # if there was no entry for the given key)
242
- #
243
- def delete (k)
244
-
245
- v = self[k]
246
- return nil unless v
247
- libcall(:tab_out, k, Rufus::Tokyo.blen(k))
248
-
249
- v
250
- end
251
-
252
- # Removes all records in this table database
253
- #
254
- def clear
255
-
256
- libcall(:tab_vanish)
257
- end
258
-
259
- # Returns an array of all the primary keys in the table
260
- #
261
- # With no options given, this method will return all the keys (strings)
262
- # in a Ruby array.
263
- #
264
- # :prefix --> returns only the keys who match a given string prefix
265
- #
266
- # :limit --> returns a limited number of keys
267
- #
268
- # :native --> returns an instance of Rufus::Tokyo::List instead of
269
- # a Ruby Hash, you have to call #free on that List when done with it !
270
- # Else you're exposing yourself to a memory leak.
271
- #
272
- def keys (options={})
273
-
274
- outlen = nil
275
-
276
- if pre = options[:prefix]
277
-
278
- l = lib.tab_fwmkeys(
279
- @db, pre, Rufus::Tokyo.blen(pre), options[:limit] || -1)
280
-
281
- l = Rufus::Tokyo::List.new(l)
282
-
283
- options[:native] ? l : l.release
284
-
285
- else
286
-
287
- limit = options[:limit] || -1
288
- limit = nil if limit < 1
289
-
290
- l = options[:native] ? Rufus::Tokyo::List.new : []
291
-
292
- lib.tab_iterinit(@db)
293
-
294
- outlen = FFI::MemoryPointer.new(:int)
295
-
296
- loop do
297
- break if limit and l.size >= limit
298
- out = lib.tab_iternext(@db, outlen)
299
- break if out.address == 0
300
- l << out.get_bytes(0, outlen.get_int(0))
301
- end
302
-
303
- l
304
- end
305
-
306
- ensure
307
-
308
- outlen.free if outlen
309
- end
310
-
311
- # Deletes all the entries whose key begin with the given prefix.
312
- #
313
- def delete_keys_with_prefix (prefix)
314
-
315
- # TODO : use ...searchout
316
-
317
- ks = lib.tab_fwmkeys(@db, prefix, Rufus::Tokyo.blen(prefix), -1)
318
- # -1 for no limit
319
-
320
- begin
321
- ks = Rufus::Tokyo::List.new(ks)
322
- ks.each { |k| self.delete(k) }
323
- ensure
324
- ks.free
325
- end
326
- end
327
-
328
- # No 'misc' methods for the table library, so this lget is equivalent
329
- # to calling get for each key. Hoping later versions of TC will provide
330
- # a mget method.
331
- #
332
- def lget (keys)
333
-
334
- keys.inject({}) { |h, k| v = self[k]; h[k] = v if v; h }
335
- end
336
-
337
- # Returns the number of records in this table db
338
- #
339
- def size
340
-
341
- lib.tab_rnum(@db)
342
- end
343
-
344
- # Prepares a query instance (block is optional)
345
- #
346
- def prepare_query (&block)
347
-
348
- q = TableQuery.new(self)
349
- block.call(q) if block
350
-
351
- q
352
- end
353
-
354
- # Prepares and runs a query, returns a ResultSet instance
355
- # (takes care of freeing the query structure)
356
- #
357
- def do_query (&block)
358
-
359
- q = prepare_query(&block)
360
- rs = q.run
361
-
362
- return rs
363
-
364
- ensure
365
- q.free
366
- end
367
-
368
- # Prepares and runs a query, returns an array of hashes (all Ruby)
369
- # (takes care of freeing the query and the result set structures)
370
- #
371
- def query (&block)
372
-
373
- rs = do_query(&block)
374
- a = rs.to_a
375
-
376
- return a
377
-
378
- ensure
379
- rs.free
380
- end
381
-
382
- # Prepares a query and then runs it and deletes all the results.
383
- #
384
- def query_delete (&block)
385
-
386
- q = prepare_query(&block)
387
- rs = q.delete
388
-
389
- return rs
390
-
391
- ensure
392
- q.free
393
- end
394
-
395
- # Warning : this method is low-level, you probably only need
396
- # to use #transaction and a block.
397
- #
398
- # Direct call for 'transaction begin'.
399
- #
400
- def tranbegin
401
-
402
- libcall(:tctdbtranbegin)
403
- end
404
-
405
- # Warning : this method is low-level, you probably only need
406
- # to use #transaction and a block.
407
- #
408
- # Direct call for 'transaction commit'.
409
- #
410
- def trancommit
411
- libcall(:tctdbtrancommit)
412
- end
413
-
414
- # Warning : this method is low-level, you probably only need
415
- # to use #transaction and a block.
416
- #
417
- # Direct call for 'transaction abort'.
418
- #
419
- def tranabort
420
- libcall(:tctdbtranabort)
421
- end
422
-
423
- # Returns the actual pointer to the Tokyo Cabinet table
424
- #
425
- def pointer
426
- @db
427
- end
428
-
429
- protected
430
-
431
- # Returns the value (as a Ruby Hash) else nil
432
- #
433
- # (the actual #[] method is provided by HashMethods)
434
- #
435
- def get (k)
436
-
437
- m = lib.tab_get(@db, k, Rufus::Tokyo.blen(k))
438
-
439
- return nil if m.address == 0
440
-
441
- Map.to_h(m) # which frees the map
442
- end
443
-
444
- def libcall (lib_method, *args)
445
-
446
- #(lib.send(lib_method, @db, *args) == 1) or raise_error
447
- # stack level too deep with JRuby 1.1.6 :(
448
-
449
- (eval(%{ lib.#{lib_method}(@db, *args) }) == 1) or raise_error
450
- # works with JRuby 1.1.6
451
- end
452
-
453
- # Obviously something got wrong, let's ask the db about it and raise
454
- # a TokyoError
455
- #
456
- def raise_error
457
-
458
- err_code = lib.tab_ecode(@db)
459
- err_msg = lib.tab_errmsg(err_code)
460
-
461
- raise TokyoError.new("(err #{err_code}) #{err_msg}")
462
- end
463
- end
464
-
465
- #
466
- # A query on a Tokyo Cabinet table db
467
- #
468
- class TableQuery
469
-
470
- include QueryConstants
471
-
472
- # Creates a query for a given Rufus::Tokyo::Table
473
- #
474
- # Queries are usually created via the #query (#prepare_query #do_query)
475
- # of the Table instance.
476
- #
477
- # Methods of interest here are :
478
- #
479
- # * #add (or #add_condition)
480
- # * #order_by
481
- # * #limit
482
- #
483
- # also
484
- #
485
- # * #pk_only
486
- # * #no_pk
487
- #
488
- def initialize (table)
489
- @table = table
490
- @query = @table.lib.qry_new(@table.pointer)
491
- @opts = {}
492
- end
493
-
494
- def lib
495
- @table.lib
496
- end
497
-
498
- # Adds a condition
499
- #
500
- # table.query { |q|
501
- # q.add 'name', :equals, 'Oppenheimer'
502
- # q.add 'age', :numgt, 35
503
- # }
504
- #
505
- # Understood 'operators' :
506
- #
507
- # :streq # string equality
508
- # :eq
509
- # :eql
510
- # :equals
511
- #
512
- # :strinc # string include
513
- # :inc # string include
514
- # :includes # string include
515
- #
516
- # :strbw # string begins with
517
- # :bw
518
- # :starts_with
519
- # :strew # string ends with
520
- # :ew
521
- # :ends_with
522
- #
523
- # :strand # string which include all the tokens in the given exp
524
- # :and
525
- #
526
- # :stror # string which include at least one of the tokens
527
- # :or
528
- #
529
- # :stroreq # string which is equal to at least one token
530
- #
531
- # :strorrx # string which matches the given regex
532
- # :regex
533
- # :matches
534
- #
535
- # # numbers...
536
- #
537
- # :numeq # equal
538
- # :numequals
539
- # :numgt # greater than
540
- # :gt
541
- # :numge # greater or equal
542
- # :ge
543
- # :gte
544
- # :numlt # greater or equal
545
- # :lt
546
- # :numle # greater or equal
547
- # :le
548
- # :lte
549
- # :numbt # a number between two tokens in the given exp
550
- # :bt
551
- # :between
552
- #
553
- # :numoreq # number which is equal to at least one token
554
- #
555
- def add (colname, operator, val, affirmative=true, no_index=false)
556
-
557
- op = operator.is_a?(Fixnum) ? operator : OPERATORS[operator]
558
- op = op | TDBQCNEGATE unless affirmative
559
- op = op | TDBQCNOIDX if no_index
560
- lib.qry_addcond(@query, colname, op, val)
561
- end
562
- alias :add_condition :add
563
-
564
- # Sets the max number of records to return for this query.
565
- #
566
- # (If you're using TC >= 1.4.10 the optional 'offset' (skip) parameter
567
- # is accepted)
568
- #
569
- def limit (i, offset=-1)
570
-
571
- lib.respond_to?(:qry_setlimit) ?
572
- lib.qry_setlimit(@query, i, offset) :
573
- lib.qry_setmax(@query, i)
574
- end
575
-
576
- # Sets the sort order for the result of the query
577
- #
578
- # The 'direction' may be :
579
- #
580
- # :strasc # string ascending
581
- # :strdesc
582
- # :asc # string ascending
583
- # :desc
584
- # :numasc # number ascending
585
- # :numdesc
586
- #
587
- def order_by (colname, direction=:strasc)
588
- lib.qry_setorder(@query, colname, DIRECTIONS[direction])
589
- end
590
-
591
- # When set to true, only the primary keys of the matching records will
592
- # be returned.
593
- #
594
- def pk_only (on=true)
595
- @opts[:pk_only] = on
596
- end
597
-
598
- # When set to true, the :pk (primary key) is not inserted in the record
599
- # (hashes) returned
600
- #
601
- def no_pk (on=true)
602
-
603
- @opts[:no_pk] = on
604
- end
605
-
606
- # Process each record using the supplied block, which will be passed
607
- # two parameters, the primary key and the value hash.
608
- #
609
- # The block passed to this method accepts two parameters : the [String]
610
- # primary key and a Hash of the values for the record.
611
- #
612
- # The return value of the passed block does matter. Three different
613
- # values are expected :stop, :delete or a Hash instance.
614
- #
615
- # :stop will make the iteration stop, further matching records will not
616
- # be passed to the block
617
- #
618
- # :delete will let Tokyo Cabinet delete the record just seen.
619
- #
620
- # a Hash is passed to let TC update the values for the record just seen.
621
- #
622
- # Passing an array is possible : [ :stop, { 'name' => 'Toto' } ] will
623
- # update the record just seen to a unique column 'name' and will stop the
624
- # iteration. Likewise, returning [ :stop, :delete ] will work as well.
625
- #
626
- # (by Matthew King)
627
- #
628
- def process (&block)
629
-
630
- callback = lambda do |pk, pklen, map, opt_param|
631
-
632
- key = pk.read_string(pklen)
633
- val = Rufus::Tokyo::Map.new(map).to_h
634
-
635
- r = block.call(key, val)
636
- r = [ r ] unless r.is_a?(Array)
637
-
638
- if updated_value = r.find { |e| e.is_a?(Hash) }
639
- Rufus::Tokyo::Map.new(map).merge!(updated_value)
640
- end
641
-
642
- r.inject(0) { |i, v|
643
- case v
644
- when :stop then i = i | 1 << 24
645
- when :delete then i = i | 2
646
- when Hash then i = i | 1
647
- end
648
- i
649
- }
650
- end
651
-
652
- lib.qry_proc(@query, callback, nil)
653
-
654
- self
655
- end
656
-
657
- # Runs this query (returns a TableResultSet instance)
658
- #
659
- def run
660
-
661
- @last_resultset =
662
- TableResultSet.new(@table, lib.qry_search(@query), @opts)
663
- end
664
-
665
- # Runs this query AND let all the matching records get deleted.
666
- #
667
- def delete
668
-
669
- lib.qry_searchout(@query) || raise_error
670
- end
671
-
672
- # Gets the count of records returned by this query.
673
- #
674
- # Note : the 'real' impl is only available since TokyoCabinet 1.4.12.
675
- #
676
- def count
677
-
678
- if lib.respond_to?(:qry_count)
679
- lib.qry_count(@query)
680
- else
681
- @last_resultset ? @last_resultset.size : 0
682
- end
683
- end
684
-
685
- # Frees this data structure
686
- #
687
- def free
688
- lib.qry_del(@query)
689
- @query = nil
690
- end
691
-
692
- alias :close :free
693
- alias :destroy :free
694
- end
695
-
696
- #
697
- # The thing queries return
698
- #
699
- class TableResultSet
700
-
701
- include Enumerable
702
-
703
- def initialize (table, list_pointer, query_opts)
704
-
705
- @table = table
706
- @list = Rufus::Tokyo::List.new(list_pointer)
707
- @opts = query_opts
708
- end
709
-
710
- # Returns the count of element in this result set
711
- #
712
- def size
713
-
714
- @list.size
715
- end
716
-
717
- alias :length :size
718
-
719
- # The classical each
720
- #
721
- def each
722
- (0..size-1).each do |i|
723
- pk = @list[i]
724
- if @opts[:pk_only]
725
- yield(pk)
726
- else
727
- val = @table[pk]
728
- val[:pk] = pk unless @opts[:no_pk]
729
- yield(val)
730
- end
731
- end
732
- end
733
-
734
- # Returns an array of hashes
735
- #
736
- def to_a
737
-
738
- collect { |m| m }
739
- end
740
-
741
- # Frees this query (the underlying Tokyo Cabinet list structure)
742
- #
743
- def free
744
-
745
- @list.free
746
- @list = nil
747
- end
748
-
749
- alias :close :free
750
- alias :destroy :free
751
- end
752
- end
753
-