clindex 1.1.0

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.
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
+