knjrbfw 0.0.110 → 0.0.111
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.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +2 -2
- data/VERSION +1 -1
- data/knjrbfw.gemspec +8 -36
- data/lib/knj/autoload.rb +1 -2
- data/lib/knj/gtk2_window.rb +7 -7
- data/lib/knj/unix_proc.rb +35 -35
- metadata +33 -62
- data/lib/knj/db.rb +0 -1
- data/lib/knj/knjdb/dbtime.rb +0 -35
- data/lib/knj/knjdb/drivers/mysql/knjdb_mysql.rb +0 -604
- data/lib/knj/knjdb/drivers/mysql/knjdb_mysql_columns.rb +0 -155
- data/lib/knj/knjdb/drivers/mysql/knjdb_mysql_indexes.rb +0 -69
- data/lib/knj/knjdb/drivers/mysql/knjdb_mysql_sqlspecs.rb +0 -5
- data/lib/knj/knjdb/drivers/mysql/knjdb_mysql_tables.rb +0 -443
- data/lib/knj/knjdb/drivers/sqlite3/knjdb_sqlite3.rb +0 -184
- data/lib/knj/knjdb/drivers/sqlite3/knjdb_sqlite3_columns.rb +0 -177
- data/lib/knj/knjdb/drivers/sqlite3/knjdb_sqlite3_indexes.rb +0 -29
- data/lib/knj/knjdb/drivers/sqlite3/knjdb_sqlite3_sqlspecs.rb +0 -5
- data/lib/knj/knjdb/drivers/sqlite3/knjdb_sqlite3_tables.rb +0 -449
- data/lib/knj/knjdb/dump.rb +0 -122
- data/lib/knj/knjdb/idquery.rb +0 -109
- data/lib/knj/knjdb/libknjdb.rb +0 -797
- data/lib/knj/knjdb/libknjdb_java_sqlite3.rb +0 -83
- data/lib/knj/knjdb/libknjdb_row.rb +0 -153
- data/lib/knj/knjdb/libknjdb_sqlite3_ironruby.rb +0 -69
- data/lib/knj/knjdb/query_buffer.rb +0 -87
- data/lib/knj/knjdb/revision.rb +0 -342
- data/lib/knj/knjdb/sqlspecs.rb +0 -5
- data/lib/knj/objects.rb +0 -957
- data/lib/knj/process.rb +0 -480
- data/lib/knj/process_meta.rb +0 -569
- data/spec/db_spec.rb +0 -282
- data/spec/db_spec_encoding_test_file.txt +0 -1
- data/spec/objects_spec.rb +0 -394
- data/spec/process_meta_spec.rb +0 -172
- data/spec/process_spec.rb +0 -115
data/lib/knj/process.rb
DELETED
@@ -1,480 +0,0 @@
|
|
1
|
-
require "#{$knjpath}errors"
|
2
|
-
require "#{$knjpath}thread"
|
3
|
-
require "tsafe"
|
4
|
-
|
5
|
-
#This class is able to control communicate with another Ruby-process also running Knj::Process.
|
6
|
-
class Knj::Process
|
7
|
-
attr_reader :blocks, :blocks_send
|
8
|
-
|
9
|
-
#Constructor. Sets in, out and various other needed variables.
|
10
|
-
def initialize(args = {})
|
11
|
-
@args = args
|
12
|
-
@in = @args[:in]
|
13
|
-
@out = @args[:out]
|
14
|
-
@on_rec = @args[:on_rec]
|
15
|
-
@in_count = 0
|
16
|
-
@out_count = 0
|
17
|
-
@out_answers = {}
|
18
|
-
@out_mutex = Mutex.new
|
19
|
-
@debug = @args[:debug]
|
20
|
-
@args[:sleep_answer] = 0.001 if !@args.key?(:sleep_answer)
|
21
|
-
@thread_error = nil
|
22
|
-
|
23
|
-
#Used when this process is trying to receive block-results from the subprocess.
|
24
|
-
@blocks = {}
|
25
|
-
|
26
|
-
#Used when the other process is trying to receive block-results from this object.
|
27
|
-
@blocks_send = {}
|
28
|
-
|
29
|
-
#Else the sockets might hang when waiting for results and stuff like that... - knj.
|
30
|
-
@in.sync = true
|
31
|
-
@out.sync = true
|
32
|
-
|
33
|
-
if @args[:err]
|
34
|
-
@err_thread = Knj::Thread.new do
|
35
|
-
@args[:err].each_line do |str|
|
36
|
-
if @args[:on_err]
|
37
|
-
@args[:on_err].call(str)
|
38
|
-
else
|
39
|
-
$stderr.print "Process error: #{str}"
|
40
|
-
end
|
41
|
-
|
42
|
-
#Try to break out of loop - the process has been destroyed.
|
43
|
-
break if (!@out_mutex and str.to_s.strip.length <= 0) or (@args and @args[:err] and @args[:err].closed?)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
if @args[:listen]
|
49
|
-
require "#{$knjpath}/thread"
|
50
|
-
@listen_thread = Knj::Thread.new do
|
51
|
-
begin
|
52
|
-
self.listen
|
53
|
-
rescue => e
|
54
|
-
$stderr.print "#{Knj::Errors.error_str(e)}\n\n" if @debug
|
55
|
-
@thread_error = e
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
#Kills the listen-thread.
|
62
|
-
def kill_listen
|
63
|
-
@listen_thread.kill if @listen_thread
|
64
|
-
end
|
65
|
-
|
66
|
-
#Joins the listen-thread and the error-thread.
|
67
|
-
def join
|
68
|
-
@listen_thread.join if @listen_thread
|
69
|
-
sleep 0.5
|
70
|
-
raise @thread_error if @thread_error
|
71
|
-
end
|
72
|
-
|
73
|
-
#Listens for a new incoming object.
|
74
|
-
def listen
|
75
|
-
loop do
|
76
|
-
self.listen_loop
|
77
|
-
|
78
|
-
#Break out if something is wrong.
|
79
|
-
break if !@out_mutex or (@in and @in.closed?) or (@out and @out.closed?)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
#This method is called by listen on every loop.
|
84
|
-
def listen_loop
|
85
|
-
$stderr.print "listen-loop called.\n" if @debug
|
86
|
-
|
87
|
-
str = @in.gets("\n")
|
88
|
-
if str == nil
|
89
|
-
raise "Socket closed." if @in.closed?
|
90
|
-
sleep 0.1
|
91
|
-
return nil
|
92
|
-
end
|
93
|
-
|
94
|
-
|
95
|
-
data = str.strip.split(":")
|
96
|
-
raise "Expected length of 2 or 3 but got: '#{data.length}'.\n#{data}" if data.length != 2 and data.length != 3
|
97
|
-
|
98
|
-
raise "Invalid ID: '#{data[1]}'." if data[1].to_s.strip.length <= 0
|
99
|
-
id = data[1].to_i
|
100
|
-
|
101
|
-
raise "Invalid length: '#{data[2]}' (#{str.to_s.strip})." if data[2].to_s.strip.length <= 0
|
102
|
-
length = data[2].to_i
|
103
|
-
|
104
|
-
$stderr.print "Received ID #{id}.\n" if @debug
|
105
|
-
res = @in.read(length)
|
106
|
-
|
107
|
-
begin
|
108
|
-
obj = Marshal.load(res)
|
109
|
-
$stderr.print "Got content for '#{id}' (#{data[0]}).\n" if @debug
|
110
|
-
|
111
|
-
case data[0]
|
112
|
-
when "answer"
|
113
|
-
#raise "Already have answer for '#{id}'." if @out_answers.key?(id)
|
114
|
-
@out_answers[id] = obj
|
115
|
-
when "answer_block"
|
116
|
-
@blocks[id][:mutex].synchronize do
|
117
|
-
@blocks[id][:results] += obj
|
118
|
-
end
|
119
|
-
when "answer_block_end"
|
120
|
-
$stderr.print "Answer-block-end received!\n" if @debug
|
121
|
-
@blocks[id][:block_result] = obj
|
122
|
-
@blocks[id][:finished] = true
|
123
|
-
when "send"
|
124
|
-
Knj::Thread.new do
|
125
|
-
result_obj = Knj::Process::Resultobject.new(:process => self, :id => id, :obj => obj)
|
126
|
-
|
127
|
-
begin
|
128
|
-
@on_rec.call(result_obj)
|
129
|
-
rescue SystemExit, Interrupt => e
|
130
|
-
raise e
|
131
|
-
rescue Exception => e
|
132
|
-
#Error was raised - try to forward it to the server.
|
133
|
-
result_obj.answer("type" => "process_error", "class" => e.class.name, "msg" => e.message, "backtrace" => e.backtrace)
|
134
|
-
end
|
135
|
-
end
|
136
|
-
when "send_block"
|
137
|
-
result_obj = Knj::Process::Resultobject.new(:process => self, :id => id, :obj => obj)
|
138
|
-
@blocks_send[id] = {:result_obj => result_obj, :waiting_for_result => false}
|
139
|
-
|
140
|
-
@blocks_send[id][:enum] = Enumerator.new do |y|
|
141
|
-
@on_rec.call(result_obj) do |answer_block|
|
142
|
-
$stderr.print "Running enum-block for #{answer_block}\n" if @debug
|
143
|
-
|
144
|
-
#Block has ended on hosts side - break out of block-loop.
|
145
|
-
break if !@blocks_send.key?(id)
|
146
|
-
|
147
|
-
#Throw the result at the block running.
|
148
|
-
y << answer_block
|
149
|
-
|
150
|
-
#This is to prevent the block-loop from running again, until host has confirmed it wants another result.
|
151
|
-
dobreak = false
|
152
|
-
|
153
|
-
loop do
|
154
|
-
#Block has ended on hosts-side - break of out block-loop.
|
155
|
-
if !@blocks_send.key?(id)
|
156
|
-
dobreak = true
|
157
|
-
break
|
158
|
-
end
|
159
|
-
|
160
|
-
#If waiting for result then release the loop and return another result.
|
161
|
-
if @blocks_send[id][:waiting_for_result]
|
162
|
-
@blocks_send[id][:waiting_for_result] = false
|
163
|
-
break
|
164
|
-
end
|
165
|
-
|
166
|
-
#Wait a little with checking for another result to not use 100% CPU.
|
167
|
-
sleep 0.01
|
168
|
-
end
|
169
|
-
|
170
|
-
#The block-loop should not run again - it has been prematurely interrupted on the host-side.
|
171
|
-
break if dobreak
|
172
|
-
end
|
173
|
-
end
|
174
|
-
when "send_block_res"
|
175
|
-
begin
|
176
|
-
#The host wants another result. Set the 'waiting-for-result' and wait for the enumerator to run. Then return result from enumerator (code is right above here).
|
177
|
-
@blocks_send[obj][:waiting_for_result] = true
|
178
|
-
res = @blocks_send[obj][:enum].next
|
179
|
-
self.answer(id, {"result" => res})
|
180
|
-
rescue StopIteration
|
181
|
-
self.answer(id, "StopIteration")
|
182
|
-
end
|
183
|
-
when "send_block_end"
|
184
|
-
if @blocks_send.key?(obj)
|
185
|
-
enum = @blocks_send[obj][:enum]
|
186
|
-
@blocks_send.delete(obj)
|
187
|
-
|
188
|
-
begin
|
189
|
-
enum.next if enum #this has to be called to stop Enumerator from blocking...
|
190
|
-
rescue StopIteration
|
191
|
-
#do nothing.
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
self.answer(id, "ok")
|
196
|
-
when "send_block_buffer"
|
197
|
-
Knj::Thread.new do
|
198
|
-
result_obj = Knj::Process::Resultobject.new(:process => self, :id => id, :obj => obj)
|
199
|
-
block_res = nil
|
200
|
-
buffer_done = false
|
201
|
-
|
202
|
-
begin
|
203
|
-
buffer_answers = Tsafe.std_array #JRuby needs the threadsafety.
|
204
|
-
buffer_thread = Knj::Thread.new do
|
205
|
-
loop do
|
206
|
-
arr = buffer_answers.shift(200)
|
207
|
-
|
208
|
-
if !arr.empty?
|
209
|
-
$stderr.print "Sending: #{arr.length} results.\n" if @debug
|
210
|
-
self.answer(id, arr, "answer_block")
|
211
|
-
else
|
212
|
-
$stderr.print "Waiting for buffer-stuff (#{arr.length}, #{buffer_done}).\n" if @debug
|
213
|
-
sleep 0.05
|
214
|
-
end
|
215
|
-
|
216
|
-
break if buffer_done and buffer_answers.empty?
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
begin
|
221
|
-
begin
|
222
|
-
count = 0
|
223
|
-
block_res = @on_rec.call(result_obj) do |answer_block|
|
224
|
-
loop do
|
225
|
-
if buffer_answers.length > 1000
|
226
|
-
$stderr.print "Buffer is more than 1000 - sleeping and tries again in 0.05 sec.\n" if @debug
|
227
|
-
sleep 0.05
|
228
|
-
else
|
229
|
-
break
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
count += 1
|
234
|
-
buffer_answers << answer_block
|
235
|
-
|
236
|
-
if count >= 100
|
237
|
-
count = 0
|
238
|
-
|
239
|
-
loop do
|
240
|
-
answer = self.send("obj" => id, "type" => "send_block_count")
|
241
|
-
$stderr.print "Answer was: #{answer}\n" if @debug
|
242
|
-
|
243
|
-
if answer >= 100
|
244
|
-
$stderr.print "More than 100 results are buffered on the other side - wait for them to be handeled before sending more.\n" if @debug
|
245
|
-
sleep 0.05
|
246
|
-
else
|
247
|
-
$stderr.print "Less than 100 results in buffer - send more.\n" if @debug
|
248
|
-
break
|
249
|
-
end
|
250
|
-
end
|
251
|
-
end
|
252
|
-
end
|
253
|
-
ensure
|
254
|
-
buffer_done = true
|
255
|
-
end
|
256
|
-
ensure
|
257
|
-
buffer_thread.join
|
258
|
-
end
|
259
|
-
rescue => e
|
260
|
-
$stderr.print Knj::Errors.error_str(e) if @debug
|
261
|
-
#Error was raised - try to forward it to the server.
|
262
|
-
result_obj.answer("type" => "process_error", "class" => e.class.name, "msg" => e.message, "backtrace" => e.backtrace)
|
263
|
-
ensure
|
264
|
-
$stderr.print "Answering with block-end.\n" if @debug
|
265
|
-
self.answer(id, block_res, "answer_block_end")
|
266
|
-
end
|
267
|
-
end
|
268
|
-
when "send_block_count"
|
269
|
-
if @blocks.key?(obj)
|
270
|
-
count = @blocks[obj][:results].length
|
271
|
-
else
|
272
|
-
count = 0
|
273
|
-
end
|
274
|
-
|
275
|
-
self.answer(id, count)
|
276
|
-
else
|
277
|
-
$stderr.print "Unknown command: '#{data[0]}'."
|
278
|
-
raise "Unknown command: '#{data[0]}'."
|
279
|
-
end
|
280
|
-
rescue => e
|
281
|
-
$stderr.print Knj::Errors.error_str(e) if @debug
|
282
|
-
#Error was raised - try to forward it to the server.
|
283
|
-
result_obj = Knj::Process::Resultobject.new(:process => self, :id => id, :obj => obj)
|
284
|
-
result_obj.answer("type" => "process_error", "class" => e.class.name, "msg" => e.message, "backtrace" => e.backtrace)
|
285
|
-
end
|
286
|
-
end
|
287
|
-
|
288
|
-
#Answers a send.
|
289
|
-
def answer(id, obj, type = "answer")
|
290
|
-
$stderr.print "Answering #{id} (#{obj}).\n" if @debug
|
291
|
-
str = Marshal.dump(obj)
|
292
|
-
|
293
|
-
@out_mutex.synchronize do
|
294
|
-
@out.write("#{type}:#{id}:#{str.length}\n#{str}")
|
295
|
-
end
|
296
|
-
end
|
297
|
-
|
298
|
-
#Sends a command to the client.
|
299
|
-
def send(args, &block)
|
300
|
-
args = {"obj" => args} if !args.is_a?(Hash)
|
301
|
-
|
302
|
-
my_id = nil
|
303
|
-
raise "No 'obj' was given." if !args["obj"]
|
304
|
-
str = Marshal.dump(args["obj"])
|
305
|
-
|
306
|
-
if args.key?("type")
|
307
|
-
type = args["type"]
|
308
|
-
else
|
309
|
-
type = "send"
|
310
|
-
end
|
311
|
-
|
312
|
-
raise "Invalid type: '#{type}'." if type.to_s.strip.length <= 0
|
313
|
-
args["wait_for_answer"] = true if !args.key?("wait_for_answer")
|
314
|
-
|
315
|
-
@out_mutex.synchronize do
|
316
|
-
my_id = @out_count
|
317
|
-
@out_count += 1
|
318
|
-
|
319
|
-
if block
|
320
|
-
if type == "send"
|
321
|
-
if args["buffer_use"]
|
322
|
-
type = "send_block_buffer"
|
323
|
-
@blocks[my_id] = {:block => block, :results => [], :finished => false, :buffer => args["buffer_use"], :mutex => Mutex.new}
|
324
|
-
else
|
325
|
-
type = "send_block"
|
326
|
-
end
|
327
|
-
end
|
328
|
-
end
|
329
|
-
|
330
|
-
$stderr.print "Writing #{type}:#{my_id}:#{args["obj"]} to socket.\n" if @debug
|
331
|
-
@out.write("#{type}:#{my_id}:#{str.length}\n#{str}")
|
332
|
-
end
|
333
|
-
|
334
|
-
#If block is broken it might never give us control to return anything - thats why we use ensure.
|
335
|
-
begin
|
336
|
-
if type == "send_block"
|
337
|
-
loop do
|
338
|
-
res = self.send("obj" => my_id, "type" => "send_block_res")
|
339
|
-
|
340
|
-
if res == "StopIteration"
|
341
|
-
break
|
342
|
-
elsif res.is_a?(Hash) and res.key?("result")
|
343
|
-
#do nothing.
|
344
|
-
else
|
345
|
-
raise "Unknown result: '#{res}'."
|
346
|
-
end
|
347
|
-
|
348
|
-
block.call(res["result"])
|
349
|
-
end
|
350
|
-
end
|
351
|
-
ensure
|
352
|
-
#Tell the subprocess we are done with the block (if break, exceptions or anything else like that was used).
|
353
|
-
if type == "send_block"
|
354
|
-
res = self.send("obj" => my_id, "type" => "send_block_end")
|
355
|
-
raise "Unknown result: '#{res}'." if res != "ok"
|
356
|
-
end
|
357
|
-
|
358
|
-
if args["wait_for_answer"]
|
359
|
-
#Make very, very short sleep, if the result is almost instant this will heavily optimize the speed, because :sleep_answer-argument wont be used.
|
360
|
-
sleep 0.00001
|
361
|
-
return self.read_answer(my_id)
|
362
|
-
end
|
363
|
-
|
364
|
-
return {:id => my_id}
|
365
|
-
end
|
366
|
-
end
|
367
|
-
|
368
|
-
#Returns true if an answer with a certain ID has arrived.
|
369
|
-
def has_answer?(id)
|
370
|
-
return @out_answers.key?(id)
|
371
|
-
end
|
372
|
-
|
373
|
-
#This is used to call the block with results and remove the results from the array.
|
374
|
-
def exec_block_results(id)
|
375
|
-
return nil if @blocks[id][:results].empty?
|
376
|
-
|
377
|
-
removes = []
|
378
|
-
@blocks[id][:mutex].synchronize do
|
379
|
-
results = @blocks[id][:results]
|
380
|
-
@blocks[id][:results] = []
|
381
|
-
|
382
|
-
results.each do |res|
|
383
|
-
removes << res
|
384
|
-
@blocks[id][:block].call(res)
|
385
|
-
end
|
386
|
-
end
|
387
|
-
end
|
388
|
-
|
389
|
-
#Waits for data with a certain ID and returns it when it exists.
|
390
|
-
def read_answer(id)
|
391
|
-
$stderr.print "Reading answer (#{id}).\n" if @debug
|
392
|
-
block_res = @blocks[id]
|
393
|
-
$stderr.print "Answer is block for #{id} #{block_res}\n" if @debug and block_res
|
394
|
-
|
395
|
-
loop do
|
396
|
-
raise "Process destroyed." if !@out_answers
|
397
|
-
|
398
|
-
if block_res
|
399
|
-
self.exec_block_results(id)
|
400
|
-
break if block_res and block_res[:finished]
|
401
|
-
else
|
402
|
-
break if @out_answers.key?(id)
|
403
|
-
end
|
404
|
-
|
405
|
-
sleep @args[:sleep_answer]
|
406
|
-
end
|
407
|
-
|
408
|
-
if block_res
|
409
|
-
self.exec_block_results(id)
|
410
|
-
@blocks.delete(id)
|
411
|
-
end
|
412
|
-
|
413
|
-
ret = @out_answers[id]
|
414
|
-
@out_answers.delete(id)
|
415
|
-
|
416
|
-
if ret.is_a?(Hash) and ret["type"] == "process_error"
|
417
|
-
$stderr.print "Process-error - begin generating error...\n" if @debug
|
418
|
-
err = RuntimeError.new(ret["msg"])
|
419
|
-
bt = []
|
420
|
-
ret["backtrace"].each do |subproc_bt|
|
421
|
-
bt << "Subprocess: #{subproc_bt}"
|
422
|
-
end
|
423
|
-
|
424
|
-
caller.each do |proc_bt|
|
425
|
-
bt << proc_bt
|
426
|
-
end
|
427
|
-
|
428
|
-
err.set_backtrace(bt)
|
429
|
-
|
430
|
-
$stderr.print Knj::Errors.error_str(err) if @debug
|
431
|
-
raise err
|
432
|
-
end
|
433
|
-
|
434
|
-
$stderr.print "Returning answer (#{id}).\n" if @debug
|
435
|
-
return ret
|
436
|
-
end
|
437
|
-
|
438
|
-
#Closes everything down...
|
439
|
-
def destroy
|
440
|
-
self.kill_listen
|
441
|
-
@err_thread.kill if @err_thread
|
442
|
-
@out_answers = nil
|
443
|
-
@out_mutex = nil
|
444
|
-
end
|
445
|
-
end
|
446
|
-
|
447
|
-
class Knj::Process::Resultobject
|
448
|
-
attr_reader :args
|
449
|
-
|
450
|
-
def initialize(args)
|
451
|
-
@args = args
|
452
|
-
@answered = false
|
453
|
-
end
|
454
|
-
|
455
|
-
#The object that was passed to the current process/socket.
|
456
|
-
def obj
|
457
|
-
return @args[:obj]
|
458
|
-
end
|
459
|
-
|
460
|
-
#Returns the process that spawned this resultobject.
|
461
|
-
def process
|
462
|
-
return @args[:process]
|
463
|
-
end
|
464
|
-
|
465
|
-
#Returns the ID this result-object should answer to.
|
466
|
-
def id
|
467
|
-
return @args[:id]
|
468
|
-
end
|
469
|
-
|
470
|
-
#Answers the call with the given object.
|
471
|
-
def answer(obj)
|
472
|
-
@answered = true
|
473
|
-
@args[:process].answer(@args[:id], obj)
|
474
|
-
end
|
475
|
-
|
476
|
-
#Returns true if this result has been answered.
|
477
|
-
def answered?
|
478
|
-
return @answered
|
479
|
-
end
|
480
|
-
end
|