manqod-server 1.257.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.
- data/bin/manqod-server +96 -0
- data/doc/HOWTO +8 -0
- data/doc/INSTALL +2 -0
- data/doc/LICENCE +450 -0
- data/doc/README +24 -0
- data/doc/gentoo/etc/conf.d/manqod-server +2 -0
- data/doc/gentoo/etc/init.d/manqod-server +32 -0
- data/doc/manqod.sql +440 -0
- data/doc/manqod_structure.sql +356 -0
- data/doc/server.conf.example +19 -0
- data/etc/update.sql +35 -0
- data/lib/DBSetup.rb +98 -0
- data/lib/DrbDB/Cron.rb +66 -0
- data/lib/DrbDB/DrbForm.rb +79 -0
- data/lib/DrbDB/DrbImages.rb +39 -0
- data/lib/DrbDB/DrbListModel.rb +671 -0
- data/lib/DrbDB/EventCache.rb +47 -0
- data/lib/DrbDB/GtkAttributes.rb +39 -0
- data/lib/DrbDB/Help.rb +47 -0
- data/lib/DrbDB/Messaging.rb +75 -0
- data/lib/DrbDB/MyMultiSQL/jdbc.rb +107 -0
- data/lib/DrbDB/MyMultiSQL/mysql-ruby.rb +114 -0
- data/lib/DrbDB/MyMultiSQL.rb +226 -0
- data/lib/DrbDB/Users.rb +61 -0
- data/lib/DrbDB.rb +274 -0
- data/lib/Eprint.rb +94 -0
- data/lib/HeartBeat.rb +54 -0
- data/lib/ManqodLogger.rb +27 -0
- data/lib/ManqodServer.rb +167 -0
- metadata +132 -0
@@ -0,0 +1,671 @@
|
|
1
|
+
#this file is part of manqod
|
2
|
+
#manqod is distributed under the CDDL licence
|
3
|
+
#the owner of manqod is Dobai-Pataky Balint(dpblnt@gmail.com)
|
4
|
+
|
5
|
+
|
6
|
+
class DrbListModel
|
7
|
+
include Eprint
|
8
|
+
include DRbUndumped
|
9
|
+
def initialize(drbdb,my_id)
|
10
|
+
@my_id=my_id.to_i
|
11
|
+
@drbdb=drbdb
|
12
|
+
@data=nil
|
13
|
+
@rowcount=0
|
14
|
+
@tree_key=nil
|
15
|
+
@tree_parent_key=nil
|
16
|
+
@fetch_filter_key=nil
|
17
|
+
@fetch_filter_value=nil
|
18
|
+
@fetch_filter_negate=false
|
19
|
+
@archive_key=nil
|
20
|
+
@clients=Array.new
|
21
|
+
@base=nil
|
22
|
+
@last_seq=Hash.new
|
23
|
+
@buttons=Array.new
|
24
|
+
@childs=Array.new
|
25
|
+
end
|
26
|
+
attr_reader :data, :rowcount, :headers, :headertypes, :my_id, :moditem, :clients, :querysql
|
27
|
+
|
28
|
+
attr_reader :column_of_visible, :column_of_id, :column_of_sensitive, :column_of_background, :column_of_foreground
|
29
|
+
attr_reader :tree_key, :tree_parent_key, :fetch_filter_key, :fetch_filter_value, :fetch_filter_negate, :archive_key
|
30
|
+
attr_reader :column_of_tree, :column_of_tree_parent, :column_of_iter_depth, :column_of_archive
|
31
|
+
attr_reader :base
|
32
|
+
|
33
|
+
def to_s
|
34
|
+
"Drbmodel{#{@drbdb.name}:#{moditem['display']}(#{my_id})}"
|
35
|
+
end
|
36
|
+
def get_id
|
37
|
+
@my_id
|
38
|
+
end
|
39
|
+
def mod_type
|
40
|
+
"list"
|
41
|
+
end
|
42
|
+
def gtk_attribute(gattr)
|
43
|
+
@drbdb.gtk_attribute(gattr,self)
|
44
|
+
end
|
45
|
+
|
46
|
+
def lock_iter(locked_id)
|
47
|
+
edebug("lock for #{locked_id}") unless @clients.size==0
|
48
|
+
if @data.has_key?(locked_id) && @data[locked_id][@column_of_sensitive]
|
49
|
+
@data[locked_id][@column_of_sensitive]=false
|
50
|
+
begin
|
51
|
+
cache.set("#{@my_id}[#{locked_id}]",@data[locked_id])
|
52
|
+
rescue => err
|
53
|
+
eerror("Locking: #{err}")
|
54
|
+
end
|
55
|
+
notify_clients(locked_id)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def unlock_iter(unlocked_id)
|
60
|
+
if @data.has_key?(unlocked_id) && !@data[unlocked_id][@column_of_sensitive]
|
61
|
+
edebug("unlock for #{unlocked_id}") unless @clients.size==0
|
62
|
+
@data[unlocked_id][@column_of_sensitive]=true
|
63
|
+
begin
|
64
|
+
cache.set("#{@my_id}[#{unlocked_id}]",@data[unlocked_id])
|
65
|
+
rescue => err
|
66
|
+
eerror("Unlocking: #{err}")
|
67
|
+
end
|
68
|
+
notify_clients(unlocked_id)
|
69
|
+
#else the row was locked and removed. we do not unlock it
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
#finds iter by col_num, col_num=colnum number to search for, col_num_data=the data we're looking for
|
74
|
+
def data_iter_of_col_num(col_num,col_num_data)
|
75
|
+
found_iter=nil
|
76
|
+
@data.each{|row_id,iter|
|
77
|
+
if iter[col_num]==col_num_data
|
78
|
+
found_iter=iter
|
79
|
+
break
|
80
|
+
end
|
81
|
+
}
|
82
|
+
found_iter
|
83
|
+
end
|
84
|
+
|
85
|
+
def set_iter_depth(row,depth_check=nil)
|
86
|
+
depth_check=Array.new if depth_check.nil?
|
87
|
+
if @tree_key
|
88
|
+
if piter=data_iter_of_col_num(@column_of_tree_parent,row[@column_of_tree])
|
89
|
+
unless depth_check.include?(piter[@column_of_id])
|
90
|
+
depth_check.push(piter[@column_of_id])
|
91
|
+
set_iter_depth(piter,depth_check)
|
92
|
+
# else
|
93
|
+
# print "circular child=>parent relation: ",depth_check.join("->"),"-/>",piter[@column_of_id],"\n"
|
94
|
+
end
|
95
|
+
row[@column_of_iter_depth]=piter[@column_of_iter_depth]+1
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def child_iter_ids(iter_id)
|
101
|
+
chs=Array.new
|
102
|
+
@data.each{|chid,chrow|
|
103
|
+
chs.push(chid) if iter_id==chrow[@column_of_tree]
|
104
|
+
}
|
105
|
+
chs
|
106
|
+
end
|
107
|
+
|
108
|
+
def set_children_depth(ids)
|
109
|
+
ids.each{|iid|
|
110
|
+
if @data.has_key?(iid)
|
111
|
+
edebug("setting depth for: #{iid}")
|
112
|
+
set_iter_depth(@data[iid])
|
113
|
+
set_children_depth(child_iter_ids(iid))
|
114
|
+
end
|
115
|
+
}
|
116
|
+
end
|
117
|
+
|
118
|
+
def data_of_column(colname,lid)
|
119
|
+
ret=nil
|
120
|
+
if di=@data[lid] and col=headers[colname]
|
121
|
+
ret=di[col["model_col"]]
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def create_skeleton
|
126
|
+
@moditem=@drbdb.admin.qrow("select moditems.*,`queries`.`sql`,tables.name as base_table from moditems left join `queries` on `queries`.`id` = `moditems`.`query_sql_id` left join tables on queries.base = tables.id where moditems.id='#{my_id}'")
|
127
|
+
|
128
|
+
#querysql
|
129
|
+
@querysql=@moditem['sql'] if !@moditem["sql"].nil? and @moditem["sql"].length>5
|
130
|
+
@querysql=@moditem['querysql'] if @moditem["querysql"].length>5
|
131
|
+
|
132
|
+
#base
|
133
|
+
@base=@moditem["base_table"]
|
134
|
+
@base=@drbdb.guess_table(querysql,"id") if @base.nil?
|
135
|
+
|
136
|
+
#id/list_key
|
137
|
+
@list_key=gtk_attribute("list_key") || "#{@base}.id"
|
138
|
+
|
139
|
+
@key_child=gtk_attribute("child_key")
|
140
|
+
@key_parent=gtk_attribute("parent_key")
|
141
|
+
@key_child2=gtk_attribute("second_child_key")
|
142
|
+
@key_parent2=gtk_attribute("second_parent_key")
|
143
|
+
|
144
|
+
if @tree_key=gtk_attribute("tree_key")
|
145
|
+
@tree_parent_key=gtk_attribute("tree_parent_key") || @list_key
|
146
|
+
end
|
147
|
+
|
148
|
+
@fetch_filter_key=gtk_attribute("fetch_filter_key")
|
149
|
+
@fetch_filter_value=gtk_attribute("fetch_filter_value")
|
150
|
+
@fetch_filter_negate=gtk_attribute("fetch_filter_negate") == 'true'
|
151
|
+
@background_key=gtk_attribute("background_key")
|
152
|
+
@foreground_key=gtk_attribute("foreground_key")
|
153
|
+
@archive_key=gtk_attribute("archive_key")
|
154
|
+
|
155
|
+
einfo("base:#{@base}, list_key:#{@list_key}, tree_key:#{@tree_key}, child_key: #{@key_child}, parent_key: #{@key_parent}, child_key2: #{@key_child2}, parent_key2: #{@key_parent2}") unless @drbdb.main_server.starting_up
|
156
|
+
|
157
|
+
@headers=Hash.new
|
158
|
+
headers[@list_key]= { "type" => "Bignum", "visible" => false, "data" => @list_key } #id
|
159
|
+
headers["visible_for_filter"]= { "type" => "TrueClass", "visible" => false, "data" => "visible_for_filter" } #visible_for_filter
|
160
|
+
headers["sensitive"]= { "type" => "TrueClass", "visible" => false, "data" => "sensitive" } #sensitive
|
161
|
+
headers[@background_key]= { "type" => "String", "visible" => false, "data" => @background_key } if @background_key
|
162
|
+
headers[@foreground_key]= { "type" => "String", "visible" => false, "data" => @foreground_key } if @foreground_key
|
163
|
+
headers[@tree_key]= { "type" => "Bignum", "visible" => false, "data" => @tree_key } if @tree_key
|
164
|
+
headers[@tree_parent_key]= { "type" => "Bignum", "visible" => false, "data" => @tree_parent_key } if (!@tree_parent_key.nil?)
|
165
|
+
headers["iter_depth"]= { "type" => "Bignum", "visible" => false, "data" => "iter_depth" } if @tree_key
|
166
|
+
headers[@key_child]= { "type" => "Bignum", "visible" => false, "data" => @key_child } if @key_child
|
167
|
+
headers[@key_child2]= { "type" => "Bignum", "visible" => false, "data" => @key_child2 } if @key_child2
|
168
|
+
headers[@fetch_filter_key]= { "type" => "String", "visible" => false, "data" => @fetch_filter_key } if @fetch_filter_key
|
169
|
+
headers[@archive_key]= { "type" => "TrueClass", "visible" => false, "data" => @archive_key } if @archive_key
|
170
|
+
|
171
|
+
hdebug="\nheaders from query:"
|
172
|
+
@drbdb.admin.rows("select * from gtkheaders where listing='#{my_id}' order by oid asc").each{|row|
|
173
|
+
headers[row["data"]]= row
|
174
|
+
headers[row["data"]]["visible"] = !(['gtk_invisible_int','gtk_invisible_string'].include?(row['type']))
|
175
|
+
hdebug="#{hdebug}\n #{row['data']} #{row['type']}"
|
176
|
+
}
|
177
|
+
|
178
|
+
@headertypes=Array.new
|
179
|
+
header_n=0
|
180
|
+
headers.each_value{|header|
|
181
|
+
header["model_col"]=header_n
|
182
|
+
case header['type']
|
183
|
+
when 'gtk_int','Integer','gtk_invisible_int','Bignum','gtk_duration','gtk_timestamp' then headertypes.push(Bignum)
|
184
|
+
when 'gtk_float','gtk_progress' then headertypes.push(Float)
|
185
|
+
when 'gtk_toggle','TrueClass' then headertypes.push(TrueClass)
|
186
|
+
# when 'gtk_pixbuf' then headertypes.push(Gdk::Pixbuf)
|
187
|
+
when 'gtk_pixbuf' then headertypes.push(Fixnum)
|
188
|
+
else
|
189
|
+
headertypes.push(String)
|
190
|
+
end
|
191
|
+
header_n+=1
|
192
|
+
}
|
193
|
+
|
194
|
+
@data=Hash.new
|
195
|
+
|
196
|
+
@column_of_id=headers[@list_key]["model_col"]
|
197
|
+
@column_of_visible=headers["visible_for_filter"]["model_col"]
|
198
|
+
@column_of_background=headers[@background_key]["model_col"] unless headers[@background_key].nil?
|
199
|
+
@column_of_foreground=headers[@foreground_key]["model_col"] unless headers[@foreground_key].nil?
|
200
|
+
@column_of_sensitive=headers["sensitive"]["model_col"]
|
201
|
+
@column_of_fetch_filter=if @fetch_filter_key then headers[@fetch_filter_key]["model_col"] else nil end
|
202
|
+
@column_of_archive=if @archive_key then headers[@archive_key]["model_col"] else nil end
|
203
|
+
hdebug="#{hdebug}\nheadertypes: #{@headertypes.inspect}\nheaders:\n"
|
204
|
+
|
205
|
+
@headers.each_value{|val| hdebug="#{hdebug} #{val['data']} #{val['model_col']}\n"}
|
206
|
+
# print "#{self} #{hdebug}\n"
|
207
|
+
@column_of_tree=nil
|
208
|
+
@column_of_tree_parent=nil
|
209
|
+
if @tree_key
|
210
|
+
@column_of_tree=if tree_header=headers[@tree_key] then tree_header["model_col"]; else nil;end
|
211
|
+
@column_of_tree_parent=if tree_parent_header=headers[@tree_parent_key] then tree_parent_header["model_col"] else nil end
|
212
|
+
@column_of_iter_depth=headers["iter_depth"]["model_col"]
|
213
|
+
end
|
214
|
+
|
215
|
+
|
216
|
+
|
217
|
+
@relations=Array.new
|
218
|
+
@drbdb.admin.rows("select * from relations where src_table='#{base}' or dst_table='#{base}'").each{|relation|
|
219
|
+
@relations.push(relation)
|
220
|
+
}
|
221
|
+
|
222
|
+
cache.set("#{@my_id}moditem",@moditem)
|
223
|
+
cache.set("#{@my_id}headers",@headers)
|
224
|
+
cache.set("#{@my_id}headertypes",@headertypes)
|
225
|
+
cache.set("#{@my_id}attributes",{
|
226
|
+
:querySQL=>@querysql,
|
227
|
+
:base=>@base,
|
228
|
+
:list_key=>@list_key,
|
229
|
+
:child_key=>@key_child,
|
230
|
+
:parent_key=>@key_parent,
|
231
|
+
:child_key2=>@key_child2,
|
232
|
+
:parent_key2=>@key_parent2,
|
233
|
+
:tree_key=>@tree_key,
|
234
|
+
:column_of_id=>@column_of_id,
|
235
|
+
:column_of_visible=>@column_of_visible,
|
236
|
+
:column_of_sensitive=>@column_of_sensitive,
|
237
|
+
:column_of_background=>@column_of_background,
|
238
|
+
:column_of_foreground=>@column_of_foreground,
|
239
|
+
:column_of_archive=>@column_of_archive,
|
240
|
+
:column_of_tree_parent=>@column_of_tree_parent,
|
241
|
+
:column_of_tree=>@column_of_tree,
|
242
|
+
:fetch_filter_key=>@fetch_filter_key,
|
243
|
+
:column_of_fetch_filter=>@column_of_fetch_filter,
|
244
|
+
:fetch_filter_value=>@fetch_filter_value,
|
245
|
+
:archive_key=>@archive_key
|
246
|
+
})
|
247
|
+
|
248
|
+
reset_buttons
|
249
|
+
reset_childs
|
250
|
+
self
|
251
|
+
end
|
252
|
+
|
253
|
+
def reset_childs
|
254
|
+
#loading childs
|
255
|
+
einfo("resetting childs") unless @drbdb.main_server.starting_up
|
256
|
+
@childs.clear
|
257
|
+
@drbdb.admin.rows("select moditems.id,moditems.display,moditems.oid,modules.modname from moditems left join modules on modid = modules.id where parent='#{my_id}' order by oid").each{|moditem|
|
258
|
+
@childs.push(moditem)
|
259
|
+
}
|
260
|
+
end
|
261
|
+
|
262
|
+
def reset_buttons
|
263
|
+
#loading buttons
|
264
|
+
einfo("resetting buttons") unless @drbdb.main_server.starting_up
|
265
|
+
@buttons.clear
|
266
|
+
@drbdb.admin.rows("select * from buttons where moditemid='#{my_id}' order by oid").each{|button|
|
267
|
+
@buttons.push(button)
|
268
|
+
}
|
269
|
+
notify_clients(nil,"buttons")
|
270
|
+
end
|
271
|
+
|
272
|
+
def update(notifier,ids=nil,rnick=nil)
|
273
|
+
before_update=Time.now
|
274
|
+
before=Time.now
|
275
|
+
if ids
|
276
|
+
if ids=='last' || ids == ["last"]
|
277
|
+
begin
|
278
|
+
sql=@drbdb.select_last(eval("\"#{querysql}\""),@list_key)
|
279
|
+
edebug(sql)
|
280
|
+
rescue =>err
|
281
|
+
eerror("update last: #{err}\n#{querysql}")
|
282
|
+
@drbdb.report_mail("update last: #{err}",{'self'=>self.inspect,'error'=>err.inspect,'query'=>querysql.inspect,'backtrace'=>err.backtrace.join("\n")})
|
283
|
+
end
|
284
|
+
else
|
285
|
+
ids=[ids] if ids.class != Array
|
286
|
+
begin
|
287
|
+
# sql=eval("\"select * from (#{querysql}) as the_query where #{@list_key} in (#{ids.join(',')})\"")
|
288
|
+
s=@drbdb.add_where("#{querysql}","#{@list_key} in (#{ids.join(',')})")
|
289
|
+
# edebug("query:#{s}")
|
290
|
+
sql=eeval("\"#{@drbdb.escape_string(s)}\"")
|
291
|
+
# edebug("query:#{sql}")
|
292
|
+
rescue =>err
|
293
|
+
eerror("update #{ids.inspect}: #{err}\n#{querysql}")
|
294
|
+
@drbdb.report_mail("update ids:#{ids.inspect}",{'self'=>self.inspect,'error'=>err.inspect,'query'=>querysql.inspect,'backtrace'=>err.backtrace.join("\n")})
|
295
|
+
end
|
296
|
+
end
|
297
|
+
else
|
298
|
+
begin
|
299
|
+
sql=eeval("\"#{@drbdb.escape_string(querysql)}\"") #'
|
300
|
+
rescue =>err
|
301
|
+
@drbdb.report_mail("update full: #{err}",{'self'=>self.inspect,'error'=>err.inspect,'query'=>querysql.inspect,'backtrace'=>err.backtrace.join("\n")})
|
302
|
+
end
|
303
|
+
end
|
304
|
+
begin
|
305
|
+
qres=@drbdb.rows(sql,true) if sql
|
306
|
+
rescue =>err
|
307
|
+
eerror("update: #{err}\n#{sql}")
|
308
|
+
@drbdb.report_mail("update: #{err}",{'self'=>self.inspect,'error'=>err.inspect,'query'=>querysql.inspect,'backtrace'=>err.backtrace.join("\n")})
|
309
|
+
end
|
310
|
+
|
311
|
+
sql_time_diff=Time.now.to_f-before.to_f
|
312
|
+
|
313
|
+
if qres then
|
314
|
+
unless ids
|
315
|
+
@data.clear
|
316
|
+
@rowcount=0
|
317
|
+
end
|
318
|
+
last_ids=nil
|
319
|
+
before=Time.now
|
320
|
+
qres.each{|row|
|
321
|
+
last_ids=[row[@list_key].to_i] if ids == "last" || ids == ["last"]
|
322
|
+
#warning about wrongly implemented queries, which force us to overwrite rows
|
323
|
+
ewarn("overwriting row ##{row[@list_key].to_i}:#{@data[row[@list_key].to_i].inspect}") if @data.has_key?(row[@list_key].to_i) and ids.class.name != "Array"
|
324
|
+
#history
|
325
|
+
row_backup=if !rnick.nil? && @data.has_key?(row[@list_key].to_i) then @data[row[@list_key].to_i].clone else nil end
|
326
|
+
#preserve row insensitivity(lock state)
|
327
|
+
row_insens=@data.has_key?(row[@list_key].to_i) ? @data[row[@list_key].to_i][@column_of_sensitive] : true
|
328
|
+
@data[row[@list_key].to_i]=Hash.new
|
329
|
+
iter=@data[row[@list_key].to_i]
|
330
|
+
headers.each_value{|header|
|
331
|
+
if row.has_key?(header['data'])
|
332
|
+
iter[header['model_col']]=
|
333
|
+
case header['type']
|
334
|
+
when 'gtk_toggle','TrueClass' then row[header['data']]=='true'
|
335
|
+
when 'gtk_int','Integer','gtk_invisible_int','Bignum','gtk_duration','gtk_timestamp' then row[header['data']].to_i
|
336
|
+
when 'gtk_float','gtk_progress' then row[header['data']].to_f
|
337
|
+
when 'gtk_pixbuf' then row[header['data']].to_i #we hold only ids here
|
338
|
+
else
|
339
|
+
row[header['data']]
|
340
|
+
end
|
341
|
+
#history
|
342
|
+
unless row_backup.nil?
|
343
|
+
if header.has_key?("id") && row_backup[header['model_col']] != iter[header['model_col']]
|
344
|
+
store_history(rnick,row[@list_key],"u",header['id'],row_backup[header['model_col']])
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
}
|
349
|
+
#history
|
350
|
+
store_history(rnick,row[@list_key],"i") if row_backup.nil? and !rnick.nil?
|
351
|
+
#defaults
|
352
|
+
iter[@column_of_sensitive]=row_insens
|
353
|
+
iter[@column_of_visible]=false
|
354
|
+
iter[@column_of_iter_depth]=0 if @tree_key
|
355
|
+
@rowcount+=1 unless ids
|
356
|
+
}
|
357
|
+
|
358
|
+
if ids and qres.size == 0
|
359
|
+
edebug("removed #{ids.inspect}")
|
360
|
+
#we were called to load_data of a non existing id, which means it was deleted
|
361
|
+
ids.each{|id_to_remove|
|
362
|
+
@data.delete(id_to_remove.to_i);
|
363
|
+
einfo("removing from cache: #{id_to_remove.inspect}")
|
364
|
+
begin
|
365
|
+
cache.delete("#{@my_id}[#{id_to_remove}]")
|
366
|
+
rescue Memcached::NotFound
|
367
|
+
end
|
368
|
+
@rowcount-=1;
|
369
|
+
store_history(rnick,id_to_remove,"d") unless rnick.nil?
|
370
|
+
}
|
371
|
+
end
|
372
|
+
end
|
373
|
+
download_time_diff=Time.now.to_f-before.to_f
|
374
|
+
before=Time.now
|
375
|
+
if @tree_key
|
376
|
+
#set up the iter depth, for tree building
|
377
|
+
if ids.nil?
|
378
|
+
#full reload
|
379
|
+
@data.each_value{|row| set_iter_depth(row)}
|
380
|
+
else
|
381
|
+
#set iter_depth for all recursive children
|
382
|
+
set_children_depth(ids)
|
383
|
+
end
|
384
|
+
end
|
385
|
+
tree_prep_time_diff=Time.now.to_f-before.to_f
|
386
|
+
before=Time.now
|
387
|
+
if @tree_key
|
388
|
+
keys=Array.new
|
389
|
+
tree_sorted.each{|row| keys.push(row[@column_of_id])}
|
390
|
+
else
|
391
|
+
keys=@data.keys
|
392
|
+
end
|
393
|
+
|
394
|
+
if ids.nil?
|
395
|
+
@data.each{|key,row|
|
396
|
+
cache.set("#{@my_id}[#{key}]",row)
|
397
|
+
}
|
398
|
+
else
|
399
|
+
ids.each{|iid|
|
400
|
+
cache.set("#{@my_id}[#{iid}]",@data[iid])
|
401
|
+
}
|
402
|
+
end
|
403
|
+
cache.set("#{@my_id}[ids]",keys)
|
404
|
+
|
405
|
+
cache_time_diff=Time.now.to_f-before.to_f
|
406
|
+
|
407
|
+
ids=last_ids unless last_ids.nil?
|
408
|
+
update_time_diff=Time.now.to_f-before_update.to_f
|
409
|
+
einfo("loaded #{if ids then ids.inspect else @rowcount end}/#{@data.size} in q:"+sprintf("%.1fs",sql_time_diff)+",d:"+sprintf("%.1fs",download_time_diff)+",t:"+sprintf("%.1fs",tree_prep_time_diff)+",c:"+sprintf("%.1fs",cache_time_diff)+"/"+sprintf("%.1fs",update_time_diff)) unless @drbdb.main_server.starting_up
|
410
|
+
notify_clients(ids)
|
411
|
+
ids
|
412
|
+
end
|
413
|
+
|
414
|
+
def tree_sorted
|
415
|
+
if @tree_key
|
416
|
+
@data.values.sort{|a,b|
|
417
|
+
a[@column_of_iter_depth]<=>b[@column_of_iter_depth]
|
418
|
+
}
|
419
|
+
else
|
420
|
+
@data.values
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
def filtered_fetch(ff_value=nil)
|
425
|
+
t=Thread.new{
|
426
|
+
einfo("serving")
|
427
|
+
before=Time.now
|
428
|
+
served_rows=0
|
429
|
+
tree_sorted.each{|row_id,row|
|
430
|
+
if @column_of_fetch_filter.nil? or ff_value.nil? or (not @fetch_filter_negate and row[@column_of_fetch_filter].to_s == ff_value.to_s) or (@fetch_filter_negate and row[@column_of_fetch_filter].to_s != ff_value.to_s)
|
431
|
+
yield row
|
432
|
+
served_rows+=1
|
433
|
+
end
|
434
|
+
}
|
435
|
+
yield served_rows
|
436
|
+
serve_time=Time.now.to_f-before.to_f
|
437
|
+
einfo("served #{served_rows}(of #{@rowcount}) in "+sprintf("%.2fs",serve_time))
|
438
|
+
}
|
439
|
+
end
|
440
|
+
|
441
|
+
def filtered_fetch2(ff_value=nil,archive=false)
|
442
|
+
# t=Thread.new{
|
443
|
+
before=Time.now.to_f
|
444
|
+
tree=tree_sorted
|
445
|
+
sort_time=Time.now.to_f
|
446
|
+
ret=Array.new
|
447
|
+
tree.each{|row|
|
448
|
+
ret.push(row) if (@column_of_fetch_filter.nil? || ff_value.nil? || (!@fetch_filter_negate && row[@column_of_fetch_filter].to_s == ff_value.to_s) || (@fetch_filter_negate && row[@column_of_fetch_filter].to_s != ff_value.to_s) ) && (@column_of_archive.nil? || (archive || !row[@column_of_archive]))
|
449
|
+
}
|
450
|
+
end_time=Time.now.to_f
|
451
|
+
einfo("serving #{ret.size}(of #{@rowcount}) (sort:"+sprintf("%.2fs",sort_time-before)+" filter:"+sprintf("%.2fs",end_time-sort_time)+") "+sprintf("%.2fs",end_time-before))
|
452
|
+
# }
|
453
|
+
ret
|
454
|
+
end
|
455
|
+
|
456
|
+
def rows_changed(chids,nick=nil,chseq=0)
|
457
|
+
ids=if chids.class.name == "Array" then chids.clone else [chids] end
|
458
|
+
#prevent circular calling of rows_changed
|
459
|
+
chseq=Time.new.to_f-@my_id if chseq == 0 #FIXME: not unique
|
460
|
+
|
461
|
+
# edebug("rows_changed:@#{chseq}:#{nick}:#{ids.inspect}")
|
462
|
+
ids_to_remove=Array.new
|
463
|
+
ids.each{|ch_id|
|
464
|
+
if @last_seq[ch_id] == chseq
|
465
|
+
ids_to_remove.push(ch_id)
|
466
|
+
else
|
467
|
+
@last_seq[ch_id]=chseq
|
468
|
+
end
|
469
|
+
}
|
470
|
+
ids_to_remove.each{|to_rem| ids.delete(to_rem)}
|
471
|
+
|
472
|
+
return unless ids.size > 0
|
473
|
+
|
474
|
+
#precaching related ids, thus if update deletes a row, we still have the required data to walk the map
|
475
|
+
pre_ids=Hash.new
|
476
|
+
@drbdb.moditems_with_base(base){|other_list|
|
477
|
+
unless other_list == self
|
478
|
+
pre_ids[other_list]=Array.new unless pre_ids.has_key?(other_list)
|
479
|
+
ids.each{|i| pre_ids[other_list].push(i)}
|
480
|
+
end
|
481
|
+
}
|
482
|
+
|
483
|
+
@relations.each{|relation|
|
484
|
+
if (relation['src_table'] == base) || (relation['dst_table'] == base && relation['rel_type'] == 'o')
|
485
|
+
#forward, update parent lists for group_by queries
|
486
|
+
#update lists with relation.src_table.src_field == relation.dst_table.dst_field
|
487
|
+
@drbdb.moditems_with_base(relation['dst_table']){|other_list|
|
488
|
+
pre_ids[other_list]=Array.new unless pre_ids.has_key?(other_list) #might already be there if multiple relations to each other
|
489
|
+
ids.each{|changed_id|
|
490
|
+
if other_id=data_of_column(relation['src_table']+"."+relation['src_field'],changed_id)
|
491
|
+
pre_ids[other_list].push(other_id.to_i)
|
492
|
+
end
|
493
|
+
}
|
494
|
+
}
|
495
|
+
#else
|
496
|
+
#reverse, update client lists, should be used only if this relation_id is used in the client query
|
497
|
+
#update lists with dst_field == src_table.src_field
|
498
|
+
end
|
499
|
+
}
|
500
|
+
|
501
|
+
rnick=if nick.nil? then nil else nick.clone end
|
502
|
+
ids=update(nil,ids,rnick)
|
503
|
+
|
504
|
+
#postcaching again, if update was insert we have the data to walk the map
|
505
|
+
@relations.each{|relation|
|
506
|
+
if (relation['src_table'] == base) || (relation['dst_table'] == base && relation['rel_type'] == 'o')
|
507
|
+
#forward, update parent lists for group_by queries
|
508
|
+
#update lists with relation.src_table.src_field == relation.dst_table.dst_field
|
509
|
+
@drbdb.moditems_with_base(relation['dst_table']){|other_list|
|
510
|
+
pre_ids[other_list]=Array.new unless pre_ids.has_key?(other_list) #might already be there
|
511
|
+
ids.each{|changed_id|
|
512
|
+
if other_id=data_of_column(relation['src_table']+"."+relation['src_field'],changed_id)
|
513
|
+
pre_ids[other_list].push(other_id.to_i)
|
514
|
+
end
|
515
|
+
}
|
516
|
+
# ecode("postcache #{other_list}:#{pre_ids[other_list].inspect}")
|
517
|
+
}
|
518
|
+
#else
|
519
|
+
#reverse, update client lists, should be used only if this relation_id is used in the client query
|
520
|
+
#update lists with dst_field == src_table.src_field
|
521
|
+
end
|
522
|
+
}
|
523
|
+
# ecode("notifying other drblists with base:#{@base} for #{ids.inspect}")
|
524
|
+
@drbdb.moditems_with_base(base){|other_list|
|
525
|
+
#drblist.rows_changed(ids,nil,chseq) unless drblist == self
|
526
|
+
unless other_list == self
|
527
|
+
pre_ids[other_list]=Array.new unless pre_ids.has_key?(other_list)
|
528
|
+
ids.each{|i| pre_ids[other_list].push(i)}
|
529
|
+
# ecode("postcache #{other_list}:#{pre_ids[other_list].inspect}")
|
530
|
+
end
|
531
|
+
}
|
532
|
+
|
533
|
+
# ecode("notifying other drblists related to:#{@base} for #{ids.inspect}")
|
534
|
+
# ecode("pre_ids:#{pre_ids.inspect}")
|
535
|
+
pre_ids.each{|other_model,other_ids|
|
536
|
+
other_ids.uniq!
|
537
|
+
# ecode("#{other_model}:#{other_ids.inspect}/@#{chseq}")
|
538
|
+
other_model.rows_changed(other_ids,nil,chseq)
|
539
|
+
}
|
540
|
+
end
|
541
|
+
|
542
|
+
def duplicate_iter(iter_to_dup)
|
543
|
+
sql="insert into #{base} set ";
|
544
|
+
q=@drbdb.query("select * from #{base} where #{@list_key}='#{iter_to_dup[@column_of_id]}'")
|
545
|
+
colon=false
|
546
|
+
if row=q.fetch_hash()
|
547
|
+
row.each { |field,data|
|
548
|
+
if "#{base}.#{field}"!=@list_key and data
|
549
|
+
sql="#{sql}, " if colon
|
550
|
+
colon=true
|
551
|
+
sql="#{sql} `#{field}`='#{@drbdb.escape_string(data)}' "
|
552
|
+
end
|
553
|
+
}
|
554
|
+
end
|
555
|
+
@drbdb.query(sql)
|
556
|
+
rows_changed("last")
|
557
|
+
# load_data(nil,"last")
|
558
|
+
end
|
559
|
+
|
560
|
+
def remove_iters(ids_to_remove,nick=nil)
|
561
|
+
unless base.nil?
|
562
|
+
@drbdb.query("delete from #{base} where #{@list_key} in (#{ids_to_remove.join(",")})")
|
563
|
+
einfo("removing ids: #{ids_to_remove.inspect}")
|
564
|
+
rows_changed(ids_to_remove,nick)
|
565
|
+
end
|
566
|
+
end
|
567
|
+
=begin
|
568
|
+
#not yet used
|
569
|
+
def change_value_of_iter(iter, column_data, new_value)
|
570
|
+
sql="update #{base} set `#{column_data}`='#{new_value}' where `id`='#{iter[column_of_id]}' limit 1"
|
571
|
+
einfo("changing #{column_data} to #{new_value} updatesql: #{sql}","list")
|
572
|
+
@drbdb.query(prepare_sql(sql,self))
|
573
|
+
rows_changed(iter[column_of_id].to_i)
|
574
|
+
end
|
575
|
+
def change_value_of_path(path, column_data, new_value)
|
576
|
+
change_value_of_iter(@sorter.get_iter(path), column_data, new_value)
|
577
|
+
end
|
578
|
+
=end
|
579
|
+
|
580
|
+
def subscribe(client)
|
581
|
+
if @clients.include?(client)
|
582
|
+
false
|
583
|
+
else
|
584
|
+
# ecode("subscribing: #{client}, #{client.inspect}")
|
585
|
+
@clients.push(client)
|
586
|
+
true
|
587
|
+
end
|
588
|
+
end
|
589
|
+
|
590
|
+
def unsubscribe(client)
|
591
|
+
# ecode("unsubscribing: #{client}, #{client.inspect}")
|
592
|
+
@clients.delete(client)
|
593
|
+
end
|
594
|
+
|
595
|
+
def notify_clients(*args)
|
596
|
+
to_remove=Array.new
|
597
|
+
th=Array.new
|
598
|
+
edebug("notifying #{@clients.size} clients for #{args.inspect}") unless @drbdb.main_server.starting_up || @clients.size==0
|
599
|
+
@clients.each{|client|
|
600
|
+
th << Thread.new{
|
601
|
+
begin
|
602
|
+
if client.alive?
|
603
|
+
client.update(self.class.name,*args)
|
604
|
+
end
|
605
|
+
rescue =>err
|
606
|
+
ecode("#{err.inspect}\n\t#{err.backtrace.join("\n\t")}")
|
607
|
+
to_remove.push(client)
|
608
|
+
end
|
609
|
+
}
|
610
|
+
}
|
611
|
+
th.each{|t| t.join}
|
612
|
+
to_remove.each{|dead|
|
613
|
+
@clients.delete(dead)
|
614
|
+
edebug("dead client deleted")
|
615
|
+
}
|
616
|
+
end
|
617
|
+
|
618
|
+
def store_history(nick,row_id,operation,header_id=nil,data=nil)
|
619
|
+
# ecode("storing history: nick:#{nick},op:#{operation}, id:#{row_id}, header:#{header_id}, data:#{data}")
|
620
|
+
sql="insert into `history` set `ctime`=now(), `nick`='#{nick}', `base`='#{@base}', `row_id`='#{row_id}', `operation`='#{operation}'"
|
621
|
+
sql+=", `header_id`='#{header_id}'" unless header_id.nil?
|
622
|
+
sql+=",`data`='#{@drbdb.escape_string(data.to_s)}'" unless data.nil?
|
623
|
+
@drbdb.admin.query(sql)
|
624
|
+
end
|
625
|
+
|
626
|
+
def buttons(user_id)
|
627
|
+
ret=Array.new
|
628
|
+
@buttons.each{|button|
|
629
|
+
ret.push(button) if button["grp_id"].to_i < 1 || @drbdb.user_in_group?(user_id.to_i,button["grp_id"].to_i)
|
630
|
+
}
|
631
|
+
ret
|
632
|
+
end
|
633
|
+
|
634
|
+
def childs
|
635
|
+
@childs
|
636
|
+
end
|
637
|
+
def cache
|
638
|
+
@drbdb.cache
|
639
|
+
end
|
640
|
+
|
641
|
+
def alive?
|
642
|
+
@drbdb.alive?
|
643
|
+
end
|
644
|
+
|
645
|
+
def remove_dead_clients
|
646
|
+
alive_clients=0
|
647
|
+
to_remove=Array.new
|
648
|
+
clients.each{|client|
|
649
|
+
begin
|
650
|
+
client.alive?
|
651
|
+
alive_clients+=1
|
652
|
+
rescue
|
653
|
+
to_remove.push(client)
|
654
|
+
end
|
655
|
+
}
|
656
|
+
to_remove.each{|dead|
|
657
|
+
ewarn("removed dead subscription: #{dead.inspect}")
|
658
|
+
clients.delete(dead)
|
659
|
+
}
|
660
|
+
alive_clients
|
661
|
+
end
|
662
|
+
|
663
|
+
# def method_missing(sym,*args)
|
664
|
+
# print "\n!#{self} missing method: #{sym}(#{args})\n"
|
665
|
+
# end
|
666
|
+
def getBinding
|
667
|
+
binding
|
668
|
+
end
|
669
|
+
|
670
|
+
end
|
671
|
+
|