clindex 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/src/index.rb +274 -0
  2. metadata +86 -0
@@ -0,0 +1,274 @@
1
+ # $Id: index.rb,v 1.14 2003/05/28 22:57:28 chrismo Exp $
2
+ =begin
3
+ ----------------------------------------------------------------------------
4
+ Copyright (c) 2002, Chris Morris
5
+ All rights reserved.
6
+
7
+ Redistribution and use in source and binary forms, with or without
8
+ modification, are permitted provided that the following conditions are met:
9
+
10
+ 1. Redistributions of source code must retain the above copyright notice,
11
+ this list of conditions and the following disclaimer.
12
+
13
+ 2. Redistributions in binary form must reproduce the above copyright notice,
14
+ this list of conditions and the following disclaimer in the documentation
15
+ and/or other materials provided with the distribution.
16
+
17
+ 3. Neither the names Chris Morris, cLabs nor the names of contributors to
18
+ this software may be used to endorse or promote products derived from this
19
+ software without specific prior written permission.
20
+
21
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
22
+ IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
25
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28
+ OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
+ ----------------------------------------------------------------------------
33
+ (based on BSD Open Source License)
34
+ =end
35
+
36
+ require 'thread'
37
+ require 'drb'
38
+ require 'cl/util/console'
39
+
40
+ # create a batch_add method? This would allow a whole
41
+ # page full of terms to be queued and the index
42
+ # locked for the duration to prevent a concurrent
43
+ # query from getting a partial result
44
+ class ClIndex
45
+ attr_accessor :index
46
+
47
+ WAIT = true
48
+ NO_WAIT = false
49
+
50
+ def initialize(verboseServer=false)
51
+ @index = {}
52
+ @lockMgr = ClIndexLockMgr.new
53
+ @verboseServer = verboseServer
54
+ end
55
+
56
+ def assign(src)
57
+ @index = src.index
58
+ end
59
+
60
+ # refactor with do_read?
61
+ def do_edit(wait)
62
+ locked = lock(ClIndexLockMgr::EDIT, wait)
63
+ if locked
64
+ begin
65
+ yield if block_given?
66
+ ensure
67
+ unlock(ClIndexLockMgr::EDIT)
68
+ end
69
+ end
70
+ end
71
+
72
+ def add(term, reference, wait=NO_WAIT)
73
+ success = false
74
+ do_edit(wait) {
75
+ @index[term] = [] if @index[term].nil?
76
+ @index[term] << reference
77
+ @index[term].uniq!
78
+ success = true
79
+ }
80
+ success
81
+ end
82
+
83
+ def remove(reference, wait=NO_WAIT)
84
+ success = false
85
+ do_edit(wait) {
86
+ @index.each_pair do |term, refArray|
87
+ @index[term].delete(reference) if refArray.include?(reference)
88
+ @index.delete(term) if @index[term].empty?
89
+ end
90
+ success = true
91
+ }
92
+ success
93
+ end
94
+
95
+ # two optional parameters, filename (defaults to index.dat in pwd) and
96
+ # wait (defaults to false). If wait is false and a blocking action
97
+ # is preventing saving, the call returns immediately. If wait is true,
98
+ # save waits for the blocking action to complete before continuing.
99
+ def save(filename='index.dat', wait=NO_WAIT)
100
+ locked = lock(ClIndexLockMgr::SAVE, wait)
101
+ if locked
102
+ begin
103
+ File.open(filename, File::CREAT|File::TRUNC|File::RDWR) do |f|
104
+ Marshal.dump(self, f)
105
+ end
106
+ ensure
107
+ unlock(ClIndexLockMgr::SAVE)
108
+ end
109
+ end
110
+ locked
111
+ end
112
+
113
+ def load(filename='index.dat', wait=NO_WAIT)
114
+ locked = lock(ClIndexLockMgr::LOAD, wait)
115
+ if locked
116
+ begin
117
+ src = nil
118
+ File.open(filename) do |f|
119
+ src = Marshal.load(f)
120
+ end
121
+ assign(src)
122
+ ensure
123
+ unlock(ClIndexLockMgr::LOAD)
124
+ end
125
+ end
126
+ locked
127
+ end
128
+
129
+ def search(term, hits, wait=NO_WAIT)
130
+ puts 'searching...' if @verboseServer
131
+ success = false
132
+ do_read(wait) {
133
+ success = true
134
+ terms = @index.keys.grep(/#{term}/i)
135
+ terms.each do |thisTerm|
136
+ hits << @index[thisTerm]
137
+ end
138
+ hits = hits.flatten.uniq.sort
139
+ }
140
+ success
141
+ end
142
+
143
+ def do_read(wait)
144
+ locked = lock(ClIndexLockMgr::READ, wait)
145
+ if locked
146
+ begin
147
+ yield if block_given?
148
+ ensure
149
+ unlock(ClIndexLockMgr::READ)
150
+ end
151
+ end
152
+ end
153
+
154
+ def all_terms(reference, wait=NO_WAIT)
155
+ all = []
156
+ do_read(wait) {
157
+ @index.each do |term, refArray|
158
+ all << term if refArray.include?(reference)
159
+ end
160
+ }
161
+ all
162
+ end
163
+
164
+ def reference_exists?(reference, wait=NO_WAIT)
165
+ exists = false
166
+ do_read(wait) {
167
+ @index.each do |term, refArray|
168
+ if refArray.include? reference
169
+ exists = true
170
+ break
171
+ end
172
+ end
173
+ }
174
+ exists
175
+ end
176
+
177
+ def term_exists?(term, wait=NO_WAIT)
178
+ exists = false
179
+ do_read(wait) {
180
+ exists = @index.keys.include?(term)
181
+ }
182
+ exists
183
+ end
184
+
185
+ def lock(lockType, wait=NO_WAIT)
186
+ @lockMgr.lock(lockType, wait)
187
+ end
188
+
189
+ def unlock(lockType)
190
+ @lockMgr.unlock(lockType)
191
+ end
192
+ end
193
+
194
+ class ThreadSafeArray
195
+ def initialize
196
+ @mutex = Mutex.new
197
+ @internalArray = []
198
+ end
199
+
200
+ def to_ary
201
+ @internalArray
202
+ end
203
+
204
+ def method_missing(method, *args, &block)
205
+ @mutex.synchronize do
206
+ @internalArray.send(method, *args, &block)
207
+ end
208
+ end
209
+ end
210
+
211
+ class ClIndexLockMgr
212
+ LOAD = 'load'
213
+ SAVE = 'save'
214
+ EDIT = 'edit'
215
+ READ = 'read'
216
+ WAIT = true
217
+
218
+ def initialize
219
+ @allowable = {
220
+ LOAD => [],
221
+ SAVE => [READ],
222
+ EDIT => [],
223
+ READ => [READ, SAVE]
224
+ }
225
+
226
+ @current = ThreadSafeArray.new
227
+ @mutex = Mutex.new
228
+ end
229
+
230
+ def lock_approved(lockType)
231
+ result = true
232
+ @allowable.each_pair do |locked, allowable|
233
+ if @current.include?(locked) && !allowable.include?(lockType)
234
+ result = false
235
+ end
236
+ break if !result
237
+ end
238
+ result
239
+ end
240
+
241
+ def lock(lockType, wait=false)
242
+ if wait
243
+ begin
244
+ approved = lock_approved(lockType)
245
+ end until approved
246
+ else
247
+ approved = lock_approved(lockType)
248
+ end
249
+ @current << lockType if approved
250
+ approved
251
+ end
252
+
253
+ def unlock(lockType)
254
+ @current.delete(lockType)
255
+ end
256
+ end
257
+
258
+ def launch_server(port='9110')
259
+ idxServer = ClIndex.new(true)
260
+ puts "ClIndex launching on localhost:#{port}..."
261
+ DRb.start_service("druby://localhost:#{port}", idxServer)
262
+ DRb.thread.join
263
+ end
264
+
265
+ if __FILE__ == $0
266
+ if if_switch('-s')
267
+ port = get_switch('-p')
268
+ if port
269
+ launch_server(port)
270
+ else
271
+ launch_server
272
+ end
273
+ end
274
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: clindex
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 1
9
+ - 0
10
+ version: 1.1.0
11
+ platform: ruby
12
+ authors:
13
+ - chrismo
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-05-22 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: clutil
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 15599
29
+ segments:
30
+ - 2011
31
+ - 138
32
+ - 0
33
+ version: 2011.138.0
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ description: A generic index DRb server. The core index is a hash, each key is an individual term, each value is an array of references for that term. Searches the index with a simple regexp grep against the hash keys to return a single array of all references on matching terms. Multi-user ready via a simple locking mechanism that probably doesn't scale too well. BSD License.
37
+ email:
38
+ - chrismo@clabs.org
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ files:
46
+ - src/index.rb
47
+ homepage: http://clabs.org/ruby.htm
48
+ licenses: []
49
+
50
+ post_install_message:
51
+ rdoc_options: []
52
+
53
+ require_paths:
54
+ - lib
55
+ - src
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 59
62
+ segments:
63
+ - 1
64
+ - 8
65
+ - 6
66
+ version: 1.8.6
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ hash: 23
73
+ segments:
74
+ - 1
75
+ - 3
76
+ - 6
77
+ version: 1.3.6
78
+ requirements: []
79
+
80
+ rubyforge_project:
81
+ rubygems_version: 1.8.2
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: cLabs Index
85
+ test_files: []
86
+