knjrbfw 0.0.39 → 0.0.40
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.
- data/VERSION +1 -1
- data/knjrbfw.gemspec +5 -2
- data/lib/knj/datarow.rb +18 -15
- data/lib/knj/errors.rb +3 -0
- data/lib/knj/http2.rb +104 -38
- data/lib/knj/knjdb/drivers/mysql/knjdb_mysql.rb +62 -11
- data/lib/knj/knjdb/drivers/mysql/knjdb_mysql_columns.rb +29 -11
- data/lib/knj/knjdb/drivers/mysql/knjdb_mysql_tables.rb +10 -3
- data/lib/knj/knjdb/drivers/sqlite3/knjdb_sqlite3.rb +24 -0
- data/lib/knj/knjdb/drivers/sqlite3/knjdb_sqlite3_columns.rb +30 -16
- data/lib/knj/knjdb/drivers/sqlite3/knjdb_sqlite3_tables.rb +51 -8
- data/lib/knj/knjdb/dump.rb +121 -0
- data/lib/knj/knjdb/idquery.rb +109 -0
- data/lib/knj/knjdb/libknjdb.rb +97 -36
- data/lib/knj/knjdb/query_buffer.rb +43 -0
- data/lib/knj/locales.rb +4 -8
- data/lib/knj/objects/objects_sqlhelper.rb +2 -2
- data/lib/knj/process.rb +6 -0
- data/lib/knj/process_meta.rb +4 -2
- data/lib/knj/threadpool.rb +84 -40
- data/lib/knj/web.rb +1 -1
- data/spec/db_spec.rb +72 -10
- data/spec/http2_spec.rb +51 -14
- data/spec/process_meta_spec.rb +17 -1
- metadata +6 -3
data/lib/knj/knjdb/libknjdb.rb
CHANGED
@@ -38,10 +38,6 @@ class Knj::Db
|
|
38
38
|
@debug = @opts[:debug]
|
39
39
|
end
|
40
40
|
|
41
|
-
def col_table
|
42
|
-
return "`"
|
43
|
-
end
|
44
|
-
|
45
41
|
def args
|
46
42
|
return @opts
|
47
43
|
end
|
@@ -118,6 +114,15 @@ class Knj::Db
|
|
118
114
|
end
|
119
115
|
|
120
116
|
thread_cur[:knjdb][tid] = @conns.get_and_lock if !thread_cur[:knjdb][tid]
|
117
|
+
|
118
|
+
#If block given then be ensure to free thread after yielding.
|
119
|
+
if block_given?
|
120
|
+
begin
|
121
|
+
yield
|
122
|
+
ensure
|
123
|
+
self.free_thread
|
124
|
+
end
|
125
|
+
end
|
121
126
|
end
|
122
127
|
|
123
128
|
#Frees the current driver from the current thread.
|
@@ -154,7 +159,19 @@ class Knj::Db
|
|
154
159
|
|
155
160
|
#Clones the current database-connection with possible extra arguments.
|
156
161
|
def clone_conn(args = {})
|
157
|
-
|
162
|
+
conn = Knj::Db.new(@opts.clone.merge(args))
|
163
|
+
|
164
|
+
if block_given?
|
165
|
+
begin
|
166
|
+
yield(conn)
|
167
|
+
ensure
|
168
|
+
conn.close
|
169
|
+
end
|
170
|
+
|
171
|
+
return nil
|
172
|
+
else
|
173
|
+
return conn
|
174
|
+
end
|
158
175
|
end
|
159
176
|
|
160
177
|
#Copies the content of the current database to another instance of Knj::Db.
|
@@ -213,6 +230,7 @@ class Knj::Db
|
|
213
230
|
#===Examples
|
214
231
|
# db.insert(:users, {:name => "John", :lastname => "Doe"})
|
215
232
|
# id = db.insert(:users, {:name => "John", :lastname => "Doe"}, :return_id => true)
|
233
|
+
# sql = db.insert(:users, {:name => "John", :lastname => "Doe"}, :return_sql => true) #=> "INSERT INTO `users` (`name`, `lastname`) VALUES ('John', 'Doe')"
|
216
234
|
def insert(tablename, arr_insert, args = nil)
|
217
235
|
self.conn_exec do |driver|
|
218
236
|
sql = "INSERT INTO #{driver.escape_table}#{tablename.to_s}#{driver.escape_table} ("
|
@@ -243,8 +261,10 @@ class Knj::Db
|
|
243
261
|
|
244
262
|
sql << ")"
|
245
263
|
|
264
|
+
return sql if args and args[:return_sql]
|
246
265
|
driver.query(sql)
|
247
266
|
return driver.lastID if args and args[:return_id]
|
267
|
+
return nil
|
248
268
|
end
|
249
269
|
end
|
250
270
|
|
@@ -260,19 +280,19 @@ class Knj::Db
|
|
260
280
|
|
261
281
|
self.conn_exec do |driver|
|
262
282
|
if driver.respond_to?(:insert_multi)
|
263
|
-
return driver.insert_multi(tablename, arr_hashes, args)
|
283
|
+
return [driver.insert_multi(tablename, arr_hashes, args)]
|
264
284
|
else
|
265
|
-
|
285
|
+
ret = [] if args and (args[:return_id] or args[:return_sql])
|
266
286
|
arr_hashes.each do |hash|
|
267
|
-
if
|
268
|
-
|
287
|
+
if ret
|
288
|
+
ret << self.insert(tablename, hash, args)
|
269
289
|
else
|
270
|
-
self.insert(tablename, hash)
|
290
|
+
self.insert(tablename, hash, args)
|
271
291
|
end
|
272
292
|
end
|
273
293
|
|
274
|
-
if
|
275
|
-
return
|
294
|
+
if ret
|
295
|
+
return ret
|
276
296
|
else
|
277
297
|
return nil
|
278
298
|
end
|
@@ -316,10 +336,30 @@ class Knj::Db
|
|
316
336
|
|
317
337
|
#Makes a select from the given arguments: table-name, where-terms and other arguments as limits and orders. Also takes a block to avoid raping of memory.
|
318
338
|
def select(tablename, arr_terms = nil, args = nil, &block)
|
339
|
+
#Set up vars.
|
319
340
|
sql = ""
|
341
|
+
args_q = nil
|
342
|
+
select_sql = "*"
|
343
|
+
|
344
|
+
#Give 'cloned_ubuf' argument to 'q'-method.
|
345
|
+
if args and args[:cloned_ubuf]
|
346
|
+
args_q = {:cloned_ubuf => true}
|
347
|
+
end
|
348
|
+
|
349
|
+
#Set up IDQuery-stuff if that is given in arguments.
|
350
|
+
if args and args[:idquery]
|
351
|
+
if args[:idquery] == true
|
352
|
+
select_sql = "`id`"
|
353
|
+
col = :id
|
354
|
+
else
|
355
|
+
select_sql = "`#{self.esc_col(args[:idquery])}`"
|
356
|
+
col = args[:idquery]
|
357
|
+
end
|
358
|
+
end
|
320
359
|
|
360
|
+
#Get the driver and generate SQL.
|
321
361
|
self.conn_exec do |driver|
|
322
|
-
sql = "SELECT
|
362
|
+
sql = "SELECT #{select_sql} FROM #{driver.escape_table}#{tablename.to_s}#{driver.escape_table}"
|
323
363
|
|
324
364
|
if arr_terms != nil and !arr_terms.empty?
|
325
365
|
sql << " WHERE #{self.makeWhere(arr_terms, driver)}"
|
@@ -327,24 +367,34 @@ class Knj::Db
|
|
327
367
|
|
328
368
|
if args != nil
|
329
369
|
if args["orderby"]
|
330
|
-
sql << " ORDER BY "
|
331
|
-
sql << args["orderby"]
|
370
|
+
sql << " ORDER BY #{args["orderby"]}"
|
332
371
|
end
|
333
372
|
|
334
373
|
if args["limit"]
|
335
|
-
sql << " LIMIT
|
374
|
+
sql << " LIMIT #{args["limit"]}"
|
336
375
|
end
|
337
376
|
|
338
377
|
if args["limit_from"] and args["limit_to"]
|
339
378
|
raise "'limit_from' was not numeric: '#{args["limit_from"]}'." if !Knj::Php.is_numeric(args["limit_from"])
|
340
379
|
raise "'limit_to' was not numeric: '#{args["limit_to"]}'." if !Knj::Php.is_numeric(args["limit_to"])
|
341
|
-
|
342
380
|
sql << " LIMIT #{args["limit_from"]}, #{args["limit_to"]}"
|
343
381
|
end
|
344
382
|
end
|
345
383
|
end
|
346
384
|
|
347
|
-
|
385
|
+
#Do IDQuery if given in arguments.
|
386
|
+
if args and args[:idquery]
|
387
|
+
res = Knj::Db::Idquery.new(:db => self, :table => tablename, :query => sql, :col => col, &block)
|
388
|
+
else
|
389
|
+
res = self.q(sql, args_q, &block)
|
390
|
+
end
|
391
|
+
|
392
|
+
#Return result if a block wasnt given.
|
393
|
+
if block
|
394
|
+
return nil
|
395
|
+
else
|
396
|
+
return res
|
397
|
+
end
|
348
398
|
end
|
349
399
|
|
350
400
|
#Returns a single row from a database.
|
@@ -368,7 +418,7 @@ class Knj::Db
|
|
368
418
|
#
|
369
419
|
#===Examples
|
370
420
|
# db.delete(:users, {:lastname => "Doe"})
|
371
|
-
def delete(tablename, arr_terms)
|
421
|
+
def delete(tablename, arr_terms, args = nil)
|
372
422
|
self.conn_exec do |driver|
|
373
423
|
sql = "DELETE FROM #{driver.escape_table}#{tablename}#{driver.escape_table}"
|
374
424
|
|
@@ -376,6 +426,7 @@ class Knj::Db
|
|
376
426
|
sql << " WHERE #{self.makeWhere(arr_terms, driver)}"
|
377
427
|
end
|
378
428
|
|
429
|
+
return sql if args and args[:return_sql]
|
379
430
|
driver.query(sql)
|
380
431
|
end
|
381
432
|
|
@@ -543,6 +594,11 @@ class Knj::Db
|
|
543
594
|
return ret
|
544
595
|
end
|
545
596
|
|
597
|
+
#Yields a query-buffer and flushes at the end of the block given.
|
598
|
+
def q_buffer(&block)
|
599
|
+
Knj::Db::Query_buffer.new(:db => self, &block)
|
600
|
+
end
|
601
|
+
|
546
602
|
#Returns the last inserted ID.
|
547
603
|
#
|
548
604
|
#===Examples
|
@@ -567,18 +623,21 @@ class Knj::Db
|
|
567
623
|
|
568
624
|
alias :esc :escape
|
569
625
|
|
626
|
+
#Escapes the given string to be used as a column.
|
570
627
|
def esc_col(str)
|
571
628
|
self.conn_exec do |driver|
|
572
629
|
return driver.esc_col(str)
|
573
630
|
end
|
574
631
|
end
|
575
632
|
|
633
|
+
#Escapes the given string to be used as a table.
|
576
634
|
def esc_table(str)
|
577
635
|
self.conn_exec do |driver|
|
578
636
|
return driver.esc_table(str)
|
579
637
|
end
|
580
638
|
end
|
581
639
|
|
640
|
+
#Returns the sign for surrounding the string that should be used as a table.
|
582
641
|
def enc_table
|
583
642
|
if !@enc_table
|
584
643
|
self.conn_exec do |driver|
|
@@ -589,6 +648,7 @@ class Knj::Db
|
|
589
648
|
return @enc_table
|
590
649
|
end
|
591
650
|
|
651
|
+
#Returns the sign for surrounding the string that should be used as a column.
|
592
652
|
def enc_col
|
593
653
|
if !@enc_col
|
594
654
|
self.conn_exec do |driver|
|
@@ -663,6 +723,7 @@ class Knj::Db
|
|
663
723
|
return @indexes
|
664
724
|
end
|
665
725
|
|
726
|
+
#Returns the SQLSpec-module and spawns it if it isnt already spawned.
|
666
727
|
def sqlspecs
|
667
728
|
if !@sqlspecs
|
668
729
|
require "#{File.dirname(__FILE__)}/drivers/#{@opts[:type]}/knjdb_#{@opts[:type]}_sqlspecs" if (!@opts.key?(:require) or @opts[:require])
|
@@ -674,6 +735,23 @@ class Knj::Db
|
|
674
735
|
return @sqlspecs
|
675
736
|
end
|
676
737
|
|
738
|
+
#Beings a transaction and commits when the block ends.
|
739
|
+
#
|
740
|
+
#===Examples
|
741
|
+
# db.transaction do |db|
|
742
|
+
# db.insert(:users, {:name => "John"})
|
743
|
+
# db.insert(:users, {:name => "Kasper"})
|
744
|
+
# end
|
745
|
+
def transaction(&block)
|
746
|
+
self.conn_exec do |driver|
|
747
|
+
driver.transaction(&block)
|
748
|
+
end
|
749
|
+
end
|
750
|
+
|
751
|
+
def col_table
|
752
|
+
return "`"
|
753
|
+
end
|
754
|
+
|
677
755
|
#Proxies the method to the driver.
|
678
756
|
#
|
679
757
|
#===Examples
|
@@ -687,21 +765,4 @@ class Knj::Db
|
|
687
765
|
|
688
766
|
raise "Method not found: #{method_name}"
|
689
767
|
end
|
690
|
-
|
691
|
-
#Beings a transaction and commits when the block ends.
|
692
|
-
#
|
693
|
-
#===Examples
|
694
|
-
# db.transaction do |db|
|
695
|
-
# db.insert(:users, {:name => "John"})
|
696
|
-
# db.insert(:users, {:name => "Kasper"})
|
697
|
-
# end
|
698
|
-
def transaction
|
699
|
-
self.query("START TRANSACTION")
|
700
|
-
|
701
|
-
begin
|
702
|
-
yield(self)
|
703
|
-
ensure
|
704
|
-
self.query("COMMIT")
|
705
|
-
end
|
706
|
-
end
|
707
768
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#This class buffers a lot of queries and flushes them out via transactions.
|
2
|
+
class Knj::Db::Query_buffer
|
3
|
+
#Constructor. Takes arguments to be used and a block.
|
4
|
+
def initialize(args)
|
5
|
+
@args = args
|
6
|
+
@queries = []
|
7
|
+
@debug = @args[:debug]
|
8
|
+
|
9
|
+
begin
|
10
|
+
yield(self)
|
11
|
+
ensure
|
12
|
+
self.flush if !@queries.empty?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
#Adds a query to the buffer.
|
17
|
+
def query(str)
|
18
|
+
STDOUT.print "Adding to buffer: #{str}\n" if @debug
|
19
|
+
@queries << str
|
20
|
+
self.flush if @queries.length > 1000
|
21
|
+
return nil
|
22
|
+
end
|
23
|
+
|
24
|
+
#Delete as on a normal Knj::Db.
|
25
|
+
def delete(table, where)
|
26
|
+
self.query(@args[:db].delete(table, where, :return_sql => true))
|
27
|
+
return nil
|
28
|
+
end
|
29
|
+
|
30
|
+
#Flushes all queries out in a transaction.
|
31
|
+
def flush
|
32
|
+
return nil if @queries.empty?
|
33
|
+
|
34
|
+
@args[:db].transaction do
|
35
|
+
@queries.shift(1000).each do |str|
|
36
|
+
STDOUT.print "Executing via buffer: #{str}\n" if @debug
|
37
|
+
@args[:db].q(str)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
return nil
|
42
|
+
end
|
43
|
+
end
|
data/lib/knj/locales.rb
CHANGED
@@ -20,19 +20,15 @@ module Knj::Locales
|
|
20
20
|
def self.localeconv
|
21
21
|
f = Knj::Locales.lang["first"]
|
22
22
|
|
23
|
-
dec = "."
|
24
|
-
thousand = ","
|
25
|
-
csv_delimiter = ","
|
26
|
-
|
27
23
|
case f
|
28
|
-
when "da", "es", "
|
24
|
+
when "da", "de", "es", "pl", "sv"
|
29
25
|
dec = ","
|
30
26
|
thousand = "."
|
31
27
|
csv_delimiter = ";"
|
32
|
-
when "en"
|
33
|
-
#do nothing.
|
34
28
|
else
|
35
|
-
|
29
|
+
dec = "."
|
30
|
+
thousand = ","
|
31
|
+
csv_delimiter = ","
|
36
32
|
end
|
37
33
|
|
38
34
|
return {
|
@@ -220,8 +220,8 @@ class Knj::Objects
|
|
220
220
|
)
|
221
221
|
sql_where << " AND #{table}`#{db.esc_col(key)}` IN (#{escape_sql})"
|
222
222
|
end
|
223
|
-
elsif val.is_a?(Hash) and val[:type] ==
|
224
|
-
raise "No table was given for join." if !val.key?(:table)
|
223
|
+
elsif val.is_a?(Hash) and val[:type] == :col
|
224
|
+
raise "No table was given for join: '#{val}', key: '#{key}' on table #{table}." if !val.key?(:table)
|
225
225
|
|
226
226
|
do_joins[val[:table].to_sym] = true
|
227
227
|
sql_where << " AND #{table}`#{db.esc_col(key)}` = `#{db.esc_table(val[:table])}`.`#{db.esc_col(val[:name])}`"
|
data/lib/knj/process.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "#{$knjpath}errors"
|
2
2
|
require "#{$knjpath}thread"
|
3
3
|
|
4
|
+
#This class is able to control communicate with another Ruby-process also running Knj::Process.
|
4
5
|
class Knj::Process
|
5
6
|
attr_reader :blocks, :blocks_send
|
6
7
|
|
@@ -56,10 +57,12 @@ class Knj::Process
|
|
56
57
|
end
|
57
58
|
end
|
58
59
|
|
60
|
+
#Kills the listen-thread.
|
59
61
|
def kill_listen
|
60
62
|
@listen_thread.kill if @listen_thread
|
61
63
|
end
|
62
64
|
|
65
|
+
#Joins the listen-thread and the error-thread.
|
63
66
|
def join
|
64
67
|
@listen_thread.join if @listen_thread
|
65
68
|
sleep 0.5
|
@@ -76,6 +79,7 @@ class Knj::Process
|
|
76
79
|
end
|
77
80
|
end
|
78
81
|
|
82
|
+
#This method is called by listen on every loop.
|
79
83
|
def listen_loop
|
80
84
|
$stderr.print "listen-loop called.\n" if @debug
|
81
85
|
|
@@ -421,6 +425,8 @@ class Knj::Process
|
|
421
425
|
end
|
422
426
|
|
423
427
|
err.set_backtrace(bt)
|
428
|
+
|
429
|
+
$stderr.print Knj::Errors.error_str(err) if @debug
|
424
430
|
raise err
|
425
431
|
end
|
426
432
|
|
data/lib/knj/process_meta.rb
CHANGED
@@ -84,12 +84,14 @@ class Knj::Process_meta
|
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
87
|
+
#Finalizer for proxy-objects. Used for unsetting objects on the process-side.
|
87
88
|
def proxy_finalizer(id)
|
88
89
|
@finalize_mutex.synchronize do
|
89
90
|
@finalize << id
|
90
91
|
end
|
91
92
|
end
|
92
93
|
|
94
|
+
#Flushes all finalized objects on the process-side.
|
93
95
|
def check_finalizers
|
94
96
|
return nil if @finalize.empty?
|
95
97
|
|
@@ -383,8 +385,8 @@ class Knj::Process_meta
|
|
383
385
|
raise e if e.message.index("No such process") == nil
|
384
386
|
end
|
385
387
|
|
386
|
-
|
387
|
-
retry
|
388
|
+
#$stderr.print "Try to kill again...\n"
|
389
|
+
#retry
|
388
390
|
end
|
389
391
|
|
390
392
|
@process = nil
|
data/lib/knj/threadpool.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
#A small threadpool framework.
|
1
2
|
class Knj::Threadpool
|
2
3
|
def self.worker_data
|
3
4
|
raise "This thread is not running via the threadpool." if !Thread.current[:knj_threadpool]
|
@@ -6,6 +7,9 @@ class Knj::Threadpool
|
|
6
7
|
|
7
8
|
attr_reader :workers, :blocks, :mutex, :args, :events
|
8
9
|
|
10
|
+
#Constructor.
|
11
|
+
#===Examples
|
12
|
+
# tp = Knj::Threadpool.new(:threads => 5)
|
9
13
|
def initialize(args = {})
|
10
14
|
@args = args
|
11
15
|
@args[:sleep] = 0.2 if !@args.key?(:sleep)
|
@@ -21,6 +25,7 @@ class Knj::Threadpool
|
|
21
25
|
self.start
|
22
26
|
end
|
23
27
|
|
28
|
+
#Starts the threadpool. This is automatically called from the constructor.
|
24
29
|
def start
|
25
30
|
@mutex.synchronize do
|
26
31
|
if !@running
|
@@ -33,6 +38,7 @@ class Knj::Threadpool
|
|
33
38
|
end
|
34
39
|
end
|
35
40
|
|
41
|
+
#Stops the threadpool.
|
36
42
|
def stop
|
37
43
|
if @running
|
38
44
|
@workers.each do |worker|
|
@@ -46,6 +52,7 @@ class Knj::Threadpool
|
|
46
52
|
end
|
47
53
|
end
|
48
54
|
|
55
|
+
#Runs the given block, waits for the result and returns the result.
|
49
56
|
def run(*args, &block)
|
50
57
|
raise "No block given." if !block_given?
|
51
58
|
blockdata = {:block => block, :result => nil, :running => false, :runned => false, :args => args}
|
@@ -70,16 +77,18 @@ class Knj::Threadpool
|
|
70
77
|
end
|
71
78
|
end
|
72
79
|
|
80
|
+
#Runs the given block in the threadpool asynced. Returns a 'Knj::Threadpool::Asynced'-object that can be used to get the result and more.
|
73
81
|
def run_async(*args, &block)
|
74
82
|
raise "No block given." if !block_given?
|
75
83
|
|
76
84
|
@mutex.synchronize do
|
77
85
|
blockdata = {:block => block, :running => false, :runned => false, :args => args}
|
78
86
|
@blocks << blockdata
|
79
|
-
return blockdata
|
87
|
+
return Knj::Threadpool::Asynced.new(blockdata)
|
80
88
|
end
|
81
89
|
end
|
82
90
|
|
91
|
+
#Returns a new block to be runned if there is one. Otherwise false.
|
83
92
|
def get_block
|
84
93
|
return false if !@running
|
85
94
|
|
@@ -96,9 +105,11 @@ class Knj::Threadpool
|
|
96
105
|
end
|
97
106
|
end
|
98
107
|
|
108
|
+
#This is the threadpool worker-object. No need to spawn this manually.
|
99
109
|
class Knj::Threadpool::Worker
|
100
110
|
attr_reader :running
|
101
111
|
|
112
|
+
#Constructor. Should not be called manually.
|
102
113
|
def initialize(args)
|
103
114
|
@args = args
|
104
115
|
@tp = @args[:threadpool]
|
@@ -112,6 +123,8 @@ class Knj::Threadpool::Worker
|
|
112
123
|
def spawn_thread
|
113
124
|
@thread = Knj::Thread.new do
|
114
125
|
loop do
|
126
|
+
break if !@sleep or !@tp
|
127
|
+
|
115
128
|
if !@blockdata
|
116
129
|
sleep @sleep
|
117
130
|
@blockdata = @tp.get_block if !@blockdata
|
@@ -128,47 +141,28 @@ class Knj::Threadpool::Worker
|
|
128
141
|
}
|
129
142
|
|
130
143
|
begin
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
@mutex_tp.synchronize do
|
137
|
-
@blockdata[:error] = e
|
138
|
-
end
|
139
|
-
ensure
|
140
|
-
@running = false
|
141
|
-
|
142
|
-
@mutex_tp.synchronize do
|
143
|
-
@blockdata[:result] = res
|
144
|
-
@blockdata[:runned] = true
|
145
|
-
@blockdata[:running] = false
|
146
|
-
end
|
147
|
-
|
148
|
-
#Try to avoid slowdown of sleep by checking if there is a new block right away.
|
149
|
-
@blockdata = @tp.get_block
|
150
|
-
end
|
151
|
-
else
|
152
|
-
begin
|
153
|
-
@blockdata[:block].call(*@blockdata[:args])
|
154
|
-
rescue Exception => e
|
155
|
-
if @tp.events.connected?(:on_error)
|
156
|
-
@tp.events.call(:on_error, e)
|
157
|
-
else
|
158
|
-
STDOUT.print Knj::Errors.error_str(e)
|
159
|
-
end
|
160
|
-
ensure
|
161
|
-
@mutex_tp.synchronize do
|
162
|
-
@blockdata.clear if @blockdata
|
163
|
-
@tp.blocks.delete(@blockdata)
|
164
|
-
end
|
165
|
-
|
166
|
-
#Try to avoid slowdown of sleep by checking if there is a new block right away.
|
167
|
-
@blockdata = @tp.get_block
|
168
|
-
end
|
144
|
+
@running = true
|
145
|
+
res = @blockdata[:block].call(*@blockdata[:args])
|
146
|
+
rescue => e
|
147
|
+
@mutex_tp.synchronize do
|
148
|
+
@blockdata[:error] = e
|
169
149
|
end
|
170
150
|
ensure
|
151
|
+
#Reset thread.
|
171
152
|
Thread.current[:knj_threadpool] = nil
|
153
|
+
|
154
|
+
#Set running-status on worker.
|
155
|
+
@running = false
|
156
|
+
|
157
|
+
#Update block-data.
|
158
|
+
@mutex_tp.synchronize do
|
159
|
+
@blockdata[:result] = res if res
|
160
|
+
@blockdata[:runned] = true
|
161
|
+
@blockdata[:running] = false
|
162
|
+
end
|
163
|
+
|
164
|
+
#Try to avoid slowdown of sleep by checking if there is a new block right away.
|
165
|
+
@blockdata = @tp.get_block
|
172
166
|
end
|
173
167
|
end
|
174
168
|
end
|
@@ -196,7 +190,7 @@ class Knj::Threadpool::Worker
|
|
196
190
|
begin
|
197
191
|
sleep 0.1
|
198
192
|
raise "The worker was stopped during execution of the block."
|
199
|
-
rescue
|
193
|
+
rescue => e
|
200
194
|
@blockdata[:error] = e
|
201
195
|
end
|
202
196
|
end
|
@@ -224,4 +218,54 @@ class Knj::Threadpool::Worker
|
|
224
218
|
@thread.kill
|
225
219
|
end
|
226
220
|
end
|
221
|
+
end
|
222
|
+
|
223
|
+
#An object of this class will be returned when calling 'run_async'.
|
224
|
+
class Knj::Threadpool::Asynced
|
225
|
+
#Constructor. Should not be called manually.
|
226
|
+
def initialize(args)
|
227
|
+
@args = args
|
228
|
+
end
|
229
|
+
|
230
|
+
#Returns true if the asynced job is still running.
|
231
|
+
def running?
|
232
|
+
return true if @args[:running]
|
233
|
+
return false
|
234
|
+
end
|
235
|
+
|
236
|
+
#Returns true if the asynced job is done running.
|
237
|
+
def done?
|
238
|
+
return true if @args[:runned] or @args.empty? or @args[:error]
|
239
|
+
return false
|
240
|
+
end
|
241
|
+
|
242
|
+
#Returns true if the asynced job is still waiting to run.
|
243
|
+
def waiting?
|
244
|
+
return true if !@args.empty? and !@args[:running] and !@args[:runned]
|
245
|
+
return false
|
246
|
+
end
|
247
|
+
|
248
|
+
#Raises error if one has happened in the asynced job.
|
249
|
+
def error!
|
250
|
+
raise @args[:error] if @args.key?(:error)
|
251
|
+
end
|
252
|
+
|
253
|
+
#Sleeps until the asynced job is done. If an error occurred in the job, that error will be raised when calling the method.
|
254
|
+
def join
|
255
|
+
loop do
|
256
|
+
self.error!
|
257
|
+
break if self.done?
|
258
|
+
sleep 0.1
|
259
|
+
end
|
260
|
+
|
261
|
+
self.error!
|
262
|
+
end
|
263
|
+
|
264
|
+
#Returns the result of the job. If an error occurred in the job, that error will be raised when calling the method.
|
265
|
+
def result(args = nil)
|
266
|
+
self.join if args and args[:wait]
|
267
|
+
raise "Not done yet." unless self.done?
|
268
|
+
self.error!
|
269
|
+
return @args[:result]
|
270
|
+
end
|
227
271
|
end
|
data/lib/knj/web.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
class Knj::Web
|
2
2
|
#Parses URI and returns hash with data.
|
3
3
|
def self.parse_uri(str)
|
4
|
-
uri_match = str.to_s.match(/^\/(
|
4
|
+
uri_match = str.to_s.match(/^\/(.+?\..*?|)(\?(.*)|)$/)
|
5
5
|
raise "Could not parse the URI: '#{str}'." if !uri_match
|
6
6
|
|
7
7
|
return {
|