hq-engine 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,431 @@
1
+ module HQ
2
+ module Engine
3
+ module LibXmlRubyMixin
4
+
5
+ def load_data_file filename
6
+
7
+ ret = []
8
+
9
+ doc =
10
+ XML::Document.file \
11
+ filename,
12
+ :options =>XML::Parser::Options::NOBLANKS
13
+
14
+ return doc.find("//data/*").to_a
15
+
16
+ end
17
+
18
+ def load_data_string string
19
+
20
+ ret = []
21
+
22
+ doc =
23
+ XML::Document.string \
24
+ string,
25
+ :options =>XML::Parser::Options::NOBLANKS
26
+
27
+ return doc.find("//data/*").to_a
28
+
29
+ end
30
+
31
+ def write_data_file filename, data
32
+
33
+ doc = XML::Document.new
34
+ doc.root = XML::Node.new "data"
35
+
36
+ data.each do
37
+ |item|
38
+ doc.root << doc.import(item)
39
+ end
40
+
41
+ File.open filename, "w" do |f|
42
+ f.print doc.to_s
43
+ end
44
+
45
+ end
46
+
47
+
48
+ def load_schema_file filename
49
+
50
+ schema_doc =
51
+ XML::Document.file filename
52
+
53
+ schema =
54
+ Hash[
55
+ schema_doc.find("*").map do
56
+ |schema_elem|
57
+ [
58
+ "%s/%s" % [
59
+ schema_elem.name,
60
+ schema_elem["name"],
61
+ ],
62
+ schema_elem,
63
+ ]
64
+ end
65
+ ]
66
+
67
+ return schema
68
+
69
+ end
70
+
71
+ def field_to_json schemas, schema_elem, fields_elem, elem, value
72
+
73
+ fields_elem.find(
74
+ "* [name() != 'option']
75
+ ").each do
76
+ |field_elem|
77
+
78
+ field_name =
79
+ field_elem["name"]
80
+
81
+ case field_elem.name
82
+
83
+ when "text"
84
+
85
+ value[field_name] =
86
+ elem[field_name]
87
+
88
+ when "int", "ts-update"
89
+
90
+ temp = elem.attributes[field_name]
91
+
92
+ value[field_name] = temp.empty? ? nil : temp.to_i
93
+
94
+ when "list"
95
+
96
+ value[field_name] = []
97
+
98
+ elem.find("* [ name () = #{xp field_name} ]") \
99
+ .each do |child_elem|
100
+
101
+ prop = {}
102
+
103
+ field_to_json \
104
+ schemas,
105
+ schema_elem,
106
+ field_elem,
107
+ child_elem,
108
+ prop
109
+
110
+ value[field_name] << prop
111
+ end
112
+
113
+ when "struct"
114
+
115
+ prop = {}
116
+
117
+ child_elem =
118
+ elem.find_first \
119
+ "* [ name () = #{xp field_name} ]"
120
+
121
+ if child_elem
122
+ field_to_json \
123
+ schemas,
124
+ schema_elem,
125
+ field_elem,
126
+ child_elem,
127
+ prop
128
+ end
129
+
130
+ value[field_name] = prop unless prop.empty?
131
+
132
+ when "xml"
133
+
134
+ value[field_name] = ""
135
+
136
+ elem.find("* [ name () = #{xp field_name} ] / *") \
137
+ .each do |prop|
138
+
139
+ value[field_name] += prop.to_s
140
+ end
141
+
142
+ when "bool"
143
+
144
+ value[field_name] = \
145
+ elem.attributes[field_name] == "yes"
146
+
147
+ when "bigtext"
148
+
149
+ value[field_name] =
150
+ elem.find_first("* [ name () = #{xp field_name} ]") \
151
+ .content
152
+
153
+ else
154
+
155
+ raise "unexpected element #{field_elem.name} found in " \
156
+ "field list for schema " \
157
+ "#{schema_elem.attributes["name"]}"
158
+
159
+ end
160
+ end
161
+
162
+ content = []
163
+
164
+ elem.find("*").each do |child_elem|
165
+
166
+ option_elem =
167
+ fields_elem.find_first \
168
+ "option [ @name = #{xp child_elem.name} ]"
169
+
170
+ next unless option_elem
171
+
172
+ option_ref =
173
+ option_elem.attributes["ref"]
174
+
175
+ schema_option_elem =
176
+ schemas["schema-opion/#{option_ref}"]
177
+
178
+ raise "Error" \
179
+ unless schema_option_elem
180
+
181
+ schema_option_props_elem =
182
+ schema_option_elem.find_first "props"
183
+
184
+ prop = {}
185
+
186
+ field_to_json \
187
+ schemas,
188
+ schema_elem,
189
+ schema_option_props_elem,
190
+ child_elem,
191
+ prop
192
+
193
+ content << {
194
+ "type" => child_elem.name,
195
+ "value" => prop,
196
+ }
197
+
198
+ end
199
+
200
+ value["content"] = content \
201
+ unless content.empty?
202
+
203
+ end
204
+
205
+ def js_to_xml schemas, type, value
206
+
207
+ schema_elem =
208
+ schemas["schema/#{type}"]
209
+
210
+ elem =
211
+ XML::Node.new type
212
+
213
+ field_to_xml \
214
+ schemas,
215
+ schema_elem.find_first("id"),
216
+ value,
217
+ elem
218
+
219
+ field_to_xml \
220
+ schemas,
221
+ schema_elem.find_first("fields"),
222
+ value,
223
+ elem
224
+
225
+ return elem
226
+
227
+ end
228
+
229
+ def xml_to_json schemas, schema_elem, elem
230
+
231
+ value = {}
232
+
233
+ field_to_json \
234
+ schemas,
235
+ schema_elem,
236
+ schema_elem.find_first("id"),
237
+ elem,
238
+ value
239
+
240
+ field_to_json \
241
+ schemas,
242
+ schema_elem,
243
+ schema_elem.find_first("fields"),
244
+ elem,
245
+ value
246
+
247
+ return value
248
+ end
249
+
250
+ def field_to_xml schemas, fields_elem, value, elem
251
+
252
+ unless value.is_a? Hash
253
+ value = {}
254
+ end
255
+
256
+ fields_elem.find("
257
+ * [name() != 'option']
258
+ ").each do
259
+ |field_elem|
260
+
261
+ field_name =
262
+ field_elem["name"]
263
+
264
+ case field_elem.name
265
+
266
+ when "text", "int", "ts-update", "enum"
267
+ elem[field_name] = value[field_name].to_s
268
+
269
+ when "bigtext"
270
+ prop = XML::Node.new field_name
271
+ prop << value[field_name]
272
+ elem << prop
273
+
274
+ when "bool"
275
+ elem[field_name] = "yes" if value[field_name]
276
+
277
+ when "list"
278
+
279
+ items = value[field_name]
280
+
281
+ if items.is_a? Array
282
+
283
+ items.each do
284
+ |item|
285
+
286
+ prop =
287
+ XML::Node.new field_name
288
+
289
+ field_to_xml \
290
+ schemas,
291
+ field_elem,
292
+ item,
293
+ prop
294
+
295
+ elem << prop
296
+
297
+ end
298
+
299
+ end
300
+
301
+ when "struct"
302
+
303
+ prop =
304
+ XML::Node.new field_name
305
+
306
+ field_to_xml \
307
+ schemas,
308
+ field_elem,
309
+ value[field_name],
310
+ prop
311
+
312
+ if prop.attributes.length + prop.children.size > 0
313
+ elem << prop
314
+ end
315
+
316
+ when "xml"
317
+
318
+ prop =
319
+ XML::Node.new field_name
320
+
321
+ temp_doc =
322
+ XML::Document.string \
323
+ "<xml>#{value[field_name]}</xml>",
324
+ :options =>XML::Parser::Options::NOBLANKS
325
+
326
+ temp_doc.root.each do
327
+ |temp_elem|
328
+ prop << temp_elem.copy(true)
329
+ end
330
+
331
+ elem << prop
332
+
333
+ else
334
+
335
+ raise "unexpected element #{field_elem.name} found in field "
336
+ "list for schema #{schema_elem["name"]}"
337
+
338
+ end
339
+
340
+ end
341
+
342
+ if value["content"].is_a? Array
343
+
344
+ value["content"].each do
345
+ |item|
346
+
347
+ item_type = item["type"]
348
+ item_value = item["value"]
349
+
350
+ option_elem =
351
+ fields_elem.find_first "
352
+ option [@name = '#{item_type}']
353
+ "
354
+
355
+ next unless option_elem
356
+
357
+ option_ref =
358
+ option_elem["ref"]
359
+
360
+ schema_option_elem =
361
+ schemas["schema-option/#{option_ref}"]
362
+
363
+ next unless schema_option_elem
364
+
365
+ schema_option_props_elem =
366
+ schema_option_elem.find_first "props"
367
+
368
+ prop =
369
+ XML::Node.new item_type
370
+
371
+ field_to_xml \
372
+ schemas,
373
+ schema_option_props_elem,
374
+ item_value,
375
+ prop
376
+
377
+ elem << prop
378
+
379
+ end
380
+
381
+ end
382
+
383
+ end
384
+
385
+ def get_record_id_short schemas, record_elem
386
+
387
+ schema_elem =
388
+ schemas["schema/#{record_elem.name}"]
389
+
390
+ unless schema_elem
391
+ raise "No schema for #{record_elem.name}"
392
+ end
393
+
394
+ id_parts =
395
+ schema_elem.find("id/*").to_a.map do
396
+ |id_elem|
397
+
398
+ part =
399
+ record_elem[id_elem["name"]]
400
+
401
+ unless part
402
+ raise "No #{id_elem["name"]} for #{record_elem.name}"
403
+ end
404
+
405
+ part
406
+
407
+ end
408
+
409
+ id =
410
+ id_parts.join "/"
411
+
412
+ return id
413
+
414
+ end
415
+
416
+ def get_record_id_long schemas, record_elem
417
+
418
+ return "%s/%s" % [
419
+ record_elem.name,
420
+ get_record_id_short(schemas, record_elem),
421
+ ]
422
+
423
+ end
424
+
425
+ def to_xml_string elem
426
+ return elem.to_s
427
+ end
428
+
429
+ end
430
+ end
431
+ end
@@ -0,0 +1,95 @@
1
+ module HQ
2
+ module Engine
3
+ class MVCC
4
+
5
+ attr_accessor :transactions
6
+
7
+ def initialize
8
+ @transactions = {}
9
+ end
10
+
11
+ def generate_transaction_id
12
+ chars = (?a..?z).to_a
13
+ return (0...20).map { chars.sample }.join
14
+ end
15
+ -
16
+ def transaction_begin
17
+
18
+ tx_id =
19
+ generate_transaction_id
20
+
21
+ @transactions[tx_id] =
22
+ {
23
+ state: :begun,
24
+ changes: {},
25
+ }
26
+
27
+ return tx_id
28
+
29
+ end
30
+
31
+ def transaction_commit transaction_id
32
+
33
+ transaction =
34
+ @transactions[transaction_id]
35
+
36
+ transaction[:state] =
37
+ :committed
38
+
39
+ end
40
+
41
+ def transaction_rollback transaction_id
42
+
43
+ transaction =
44
+ @transactions[transaction_id]
45
+
46
+ transaction[:state] =
47
+ :rolled_back
48
+
49
+ end
50
+
51
+ def get_transaction_info transaction_id
52
+
53
+ transaction =
54
+ @transactions[transaction_id]
55
+
56
+ unless transaction
57
+ return nil
58
+ end
59
+
60
+ transaction_info = {
61
+ state: transaction[:state],
62
+ }
63
+
64
+ return transaction_info
65
+
66
+ end
67
+
68
+ def data_store \
69
+ transaction_id,
70
+ record_id,
71
+ record_value
72
+
73
+ transaction =
74
+ @transactions[transaction_id]
75
+
76
+ transaction[:changes][record_id] =
77
+ record_value
78
+
79
+ end
80
+
81
+ def data_retrieve \
82
+ transaction_id,
83
+ record_id
84
+
85
+ transaction =
86
+ @transactions[transaction_id]
87
+
88
+ return \
89
+ transaction[:changes][record_id]
90
+
91
+ end
92
+
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,20 @@
1
+ module HQ
2
+ module Engine
3
+
4
+ def self.register_commands hq
5
+
6
+ hq.register_command \
7
+ "unlock",
8
+ nil,
9
+ "Unlock crashed deployment" \
10
+ do
11
+ require "hq/engine/unlock-command"
12
+ command = HQ::Engine::UnlockCommand.new
13
+ command.hq = hq
14
+ command
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ module HQ
2
+ module Engine
3
+
4
+ class RuleError < RuntimeError
5
+
6
+ attr_accessor :file
7
+ attr_accessor :line
8
+ attr_accessor :column
9
+ attr_accessor :message
10
+
11
+ def to_s
12
+ return "bananas"
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,70 @@
1
+ require "multi_json"
2
+
3
+ module HQ
4
+ module Engine
5
+ class SubProcessRuleProvider
6
+
7
+ def initialize req_wr, resp_rd
8
+
9
+ @state = :error
10
+
11
+ @req_wr = req_wr
12
+ @resp_rd = resp_rd
13
+
14
+ @state = :open
15
+
16
+ end
17
+
18
+ def close
19
+
20
+ @state == :open \
21
+ or raise "Invalid state #{@state}"
22
+
23
+ @state = :error
24
+
25
+ @req_wr.close
26
+ @resp_rd.close
27
+
28
+ @state = :closed
29
+
30
+ end
31
+
32
+ def session
33
+
34
+ @state == :open \
35
+ or raise "Invalid state #{@state}"
36
+
37
+ require "hq/engine/subprocess-rule-provider/session"
38
+
39
+ chars = "abcdefghijklmnopqrstuvwxyz"
40
+ session_id = (0...16).map { chars[rand chars.length] }.join("")
41
+
42
+ return Session.new self, session_id
43
+
44
+ end
45
+
46
+ def perform request
47
+
48
+ @state == :open \
49
+ or raise "Invalid state #{@state}"
50
+
51
+ # send request
52
+
53
+ request_string =
54
+ MultiJson.dump request
55
+
56
+ @req_wr.puts request_string.length + 1
57
+ @req_wr.puts request_string
58
+
59
+ # receive reply
60
+
61
+ reply_len = @resp_rd.gets.to_i
62
+ reply_string = @resp_rd.read reply_len
63
+
64
+ return MultiJson.load reply_string
65
+
66
+ end
67
+
68
+ end
69
+ end
70
+ end