sadie 0.0.52 → 0.1.6

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 (61) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +2 -1
  3. data/README +76 -22
  4. data/Rakefile +41 -1
  5. data/TODO +2 -31
  6. data/bin/sadie +17 -0
  7. data/bin/sadie_query_server +15 -0
  8. data/bin/sadie_server +27 -0
  9. data/bin/sadie_server.rb +23 -0
  10. data/doc/v2 +161 -0
  11. data/lib/primer.rb +201 -0
  12. data/lib/sadie/version.rb +1 -1
  13. data/lib/sadie_server.rb +59 -0
  14. data/lib/sadie_session.rb +194 -0
  15. data/lib/sadie_storage_manager.rb +60 -0
  16. data/lib/sadie_storage_mechanism.rb +18 -0
  17. data/lib/storage/memory.rb +24 -0
  18. data/sadie.gemspec +6 -2
  19. data/spec/primer.rb +167 -0
  20. data/spec/sadie_server.rb +39 -0
  21. data/spec/sadie_server_lib.rb +31 -0
  22. data/spec/sadie_session.rb +99 -0
  23. data/spec/storage_manager.rb +58 -0
  24. data/spec/storage_mechanisms/memory.rb +28 -0
  25. data/test/v2/test_installation/primers/minimal.rb +5 -0
  26. data/test/v2/test_installation/primers/onelevel/twolevel/test_subdir.rb +5 -0
  27. data/test/v2/test_installation/primers/test_after_each.rb +14 -0
  28. data/test/v2/test_installation/primers/test_after_key.rb +14 -0
  29. data/test/v2/test_installation/primers/test_before_each.rb +14 -0
  30. data/test/v2/test_installation/primers/test_before_key.rb +14 -0
  31. data/test/v2/test_installation/primers/test_expires_after_n_secs.rb +6 -0
  32. data/test/v2/test_installation/primers/test_expires_on_get.rb +6 -0
  33. data/test/v2/test_installation/primers/test_refresh.rb +10 -0
  34. metadata +84 -49
  35. data/lib/sadie/debug.rb +0 -1
  36. data/lib/sadie/defaults.rb +0 -14
  37. data/lib/sadie/primer_plugins/DatabaseConnection.plugin.rb +0 -80
  38. data/lib/sadie/primer_plugins/IniFile.plugin.rb +0 -23
  39. data/lib/sadie/primer_plugins/Resource.plugin.rb +0 -7
  40. data/lib/sadie/primer_plugins/SQLQueryTo2DArray.plugin.rb +0 -39
  41. data/lib/sadie/primer_plugins/TemplateTextFile.plugin.rb +0 -13
  42. data/lib/sadie.rb +0 -1315
  43. data/test/README +0 -9
  44. data/test/tc_sadie_toplevel.rb +0 -43
  45. data/test/tc_sadie_twodeep.rb +0 -48
  46. data/test/test_primers/.gitignore +0 -1
  47. data/test/test_primers/onedeep/multiresult.res +0 -5
  48. data/test/test_primers/toplevel.ini +0 -5
  49. data/test/test_primers/toplevel.somegroup.somekey.each +0 -15
  50. data/test/test_primers/toplevel_destructonget.res.rb +0 -9
  51. data/test/test_primers/toplevel_double.oneprime.each +0 -14
  52. data/test/test_primers/toplevel_double.res.rb +0 -5
  53. data/test/test_primers/toplevel_single.res.rb +0 -3
  54. data/test/test_primers/toplevel_testeach.res.rb +0 -4
  55. data/test/test_primers/two/deep/conf.ini +0 -2
  56. data/test/test_primers/two/deep/expensive.res +0 -3
  57. data/test/test_primers/two/deep/test.dbi.conx +0 -4
  58. data/test/test_primers/two/deep/test_template.txt.tmpl +0 -10
  59. data/test/test_primers/two/deep/testquery.test.sql2ar +0 -1
  60. data/test/test_primers/two/deep/testquery.test.sql2ar.each +0 -16
  61. data/test/test_primers/two/deep/two_results.res +0 -8
data/lib/sadie.rb DELETED
@@ -1,1315 +0,0 @@
1
- # this requires the gem: ini
2
- require 'rubygems'
3
- require "bundler/setup"
4
- require 'bundler'
5
- Bundler.require(:default)
6
- require 'sadie/defaults'
7
- require 'sadie/version'
8
- require 'erb'
9
-
10
- # ==Description: Sadie
11
- # Sadie is a data framework intended to ease the pain of constructing, accessing, and
12
- # managing the resources required by large stores of inter-related data. It supports
13
- # sessions, lazy, on-demand, one-time evaluation and file-based storage/retrieval
14
- # operations for resource-heavy data.
15
- #
16
- # New types of data primers can be added by calling addPrimerPluginsDirPath with a
17
- # directory containing plugin definitions
18
- #
19
-
20
- def S( key )
21
- instance = Sadie::getCurrentSadieInstance
22
- return instance.get( key )
23
- end
24
-
25
- class Sadie
26
-
27
-
28
- BEFORE = 1
29
- AFTER = 2
30
- EACH = 3
31
-
32
- # ==method: Sadie::getSadieInstance
33
- #
34
- # returns a new Sadie instance. Options match those of Sadie's constructor method
35
- def self.getSadieInstance( options )
36
- Sadie.new(options)
37
- end
38
-
39
- # ==method: Sadie::setCurrentSadieInstance
40
- #
41
- # this is called just prior to calling a primer plugin to handle a primer to provide
42
- # a current sadie instance for Sadie::getCurrentSadieInstance to return
43
- def self.setCurrentSadieInstance ( instance )
44
- @current_sadie_instance = instance
45
- end
46
-
47
- # ==method: Sadie::getCurrentSadieInstance
48
- #
49
- # called by plugin handlers to get access to the current Sadie instance
50
- def self.getCurrentSadieInstance
51
- @current_sadie_instance
52
- end
53
-
54
- # ==method: Sadie::Prime
55
- #
56
- # called by the .res files to register the keys the .res will prime for
57
- #
58
- # accepts as an argument a hash and a block. The hash must include the key:
59
- # 'provides' and it must define an array
60
- # of keys that the calling resource (.res) file will have provided after the block is
61
- # evaluated
62
- def self.prime ( primer_definition, &block )
63
- current_sadie_instance = Sadie::getCurrentSadieInstance
64
- current_sadie_instance.prime( primer_definition, &block )
65
- end
66
-
67
- # ==method: Sadie::eacher
68
- #
69
- # called by eacher files to hook into priming operations and calls to set method
70
- def self.eacher( eacher_params, &block )
71
- current_sadie_instance = Sadie::getCurrentSadieInstance
72
- current_sadie_instance.eacher( eacher_params, &block )
73
- end
74
-
75
- # ==method: Sadie::eacherFrame
76
- #
77
- # eacherFrame is called by get and set methods and is available to primer plugins
78
- # as well. when eacher primer files call eacher, they are registering code to
79
- # be run either BEFORE or AFTER the key/value store is set. Note that the BEFORE
80
- # eacherFrame runs just before priming when a primer exists and just before set
81
- # for keys set without primers. EACH eacherFrames are called as the data is being
82
- # assembled, if such a thing makes sense. The included SQLQueryTo2DArray plugin
83
- # tries to call any eacherFrame with an EACH occurAt parameter with each row and
84
- # the registering an EACH eacher might make sense for any number of incrementally
85
- # built data types
86
- #
87
- def self.eacherFrame( sadiekey, occur_at, param=nil )
88
- current_sadie_instance = Sadie::getCurrentSadieInstance
89
- current_sadie_instance.eacherFrame( sadiekey, occur_at, param )
90
- end
91
-
92
- # ==method: Sadie::registerPrimerPlugin
93
- #
94
- # this method is called in the .plugin.rb files to register new plugin types
95
- #
96
- def self.registerPrimerPlugin ( arghash, &block )
97
- current_sadie_instance = Sadie::getCurrentSadieInstance
98
- current_sadie_instance.registerPrimerPlugin( arghash, &block )
99
- end
100
-
101
- # ==method: Sadie::iniFileToHash
102
- #
103
- # utility class method. accepts a filepath. digests ini file and returns hash of hashes.
104
- #
105
- def self.iniFileToHash ( filepath )
106
- section = nil
107
- ret = Hash.new
108
- File.open( filepath, "r" ).each do |f|
109
- f.each_line do |line|
110
- next if line.match(/^;/) # skip comments
111
- if matches = line.match(/\[([^\]]+)\]/)
112
- section = matches[1]
113
- ret[section] = Hash.new
114
- elsif matches = line.match(/^\s*([^\s\=]+)\s*\=\s*([^\s]+.*)\s*$/)
115
- key = matches[1]
116
- value = matches[2]
117
-
118
- # strip quotes
119
- if qmatches = value.match(/[\'\"](.*)[\'\"]/)
120
- value = qmatches[1]
121
- end
122
-
123
- if defined? section
124
- ret[section][key] = value
125
- end
126
- end
127
- end
128
- end
129
- ret.empty? and return nil
130
- return ret
131
- end
132
-
133
- # ==method: Sadie::templatedFileToString
134
- #
135
- # utility class method. accepts a filepath. digests a template and returns
136
- # a string containing processed template output
137
- #
138
- def self.templatedFileToString( filepath, binding=nil )
139
-
140
- template = ERB.new File.new(filepath).read
141
- current_sadie_instance = Sadie::getCurrentSadieInstance
142
- if defined? binding
143
- template.result binding
144
- else
145
- template.result self
146
- end
147
-
148
- end
149
-
150
-
151
-
152
- # ==method: constructor
153
- # options can include any kay, value pairs but the following key values bear mention:
154
- # REQUIRED
155
- #
156
- # sadie.sessions_dirpath
157
- # or
158
- # sadie.session_id
159
- # or
160
- # sadie.session_filepath <- this is probably a bad call, use with caution
161
- #
162
- # and
163
- #
164
- # sadie.primers_dirpath
165
- #
166
- # and
167
- # sadie.primer_plugins_dirpath
168
- def initialize( options )
169
-
170
- # check instance sanity
171
- _checkInstanceSanity
172
- _checkClassSanity
173
-
174
- Sadie::setCurrentSadieInstance( self )
175
-
176
- # internalize defaults to shortterm
177
- DEFAULTS.each do |key, value|
178
- _set( key, value )
179
- end
180
-
181
- # iterate over constructor args, but do primers_dirpath last since it
182
- # causes a call to initializePrimers
183
- options.each do |key, value|
184
- set( key, value )
185
- end
186
-
187
- # if a path to a session is given, init using session file
188
- if options.has_key?( "sadie.session_filepath" )
189
- set( "sadie.session_filepath", options["sadie.session_filepath"] )
190
- _initializeWithSessionFilePath( get("sadie.session_filepath") )
191
- elsif options.has_key?( "sadie.session_id" )
192
- set( "sadie.session_id", options["sadie.session_id"] )
193
- _initializeWithSessionId( get( "sadie.session_id" ) )
194
- else
195
- set( "sadie.session_id", _generateNewSessionId )
196
- end
197
-
198
- # add the default sadie plugins dir
199
- plugins_dirpath = "lib/sadie/primer_plugins" # for dev
200
- if ! File.exists? plugins_dirpath
201
- plugins_dirpath = File.join(
202
- ENV['GEM_HOME'],
203
- "gems/sadie-#{Sadie::VERSION}",
204
- "lib/sadie/primer_plugins"
205
- )
206
-
207
- if ! File.exists? plugins_dirpath
208
- plugins_dirpath = File.expand_path "../sadie/lib/sadie/primer_plugins"
209
- end
210
-
211
- end
212
- addPrimerPluginsDirPath plugins_dirpath
213
-
214
- end
215
-
216
- # ==method: setDebugLevel
217
- #
218
- # from 0 to 10 with 0 being no debugging messages and 10 being all debugging messages
219
- #
220
- def setDebugLevel( lvl )
221
- lvl > 10 and lvl = 10
222
- lvl < 0 and lvl = 0
223
- @debug_level = lvl.to_i
224
- end
225
-
226
- # ==method: getDebugLevel
227
- #
228
- # return current debug level (default is 10)
229
- #
230
- def getDebugLevel
231
- defined? @debug_level or @debug_level = 10
232
- @debug_level
233
- end
234
-
235
- # ==method: getDebugLevel
236
- #
237
- # will print a debugging message if the current debug level is greater than
238
- # or equal to lvl
239
- #
240
- def debug!( lvl, msg )
241
- defined? @debug_level or @debug_level = 10
242
- (lvl <= @debug_level) and puts "SADIE(#{lvl}): #{msg}"
243
- end
244
-
245
- # ==method: eacher
246
- #
247
- # ( usually this will be called by the class method...it looks better )
248
- #
249
- # see class method eacher for an explanation
250
- #
251
- def eacher( params, &block )
252
- filepath = getCurrentPrimerFilepath
253
- key_prefix = getCurrentPrimerKeyPrefix
254
- occur_at = params[:when]
255
-
256
- # gen sadie key
257
- basefilename = filepath.gsub(/^.*\//,"")
258
- sadiekey = key_prefix + "." + basefilename.gsub(/\.each(?:\..*)*$/,"")
259
- sadiekey = sadiekey.gsub( /^\.+/,"" )
260
- if params.has_key? :sadiekey
261
- sadiekey = params[:sadiekey]
262
- end
263
-
264
-
265
- whichEacherFrame != Sadie::EACH and debug! 10, "whicheacherframe: #{whichEacherFrame}, occur_at: #{occur_at}"
266
-
267
- if midEacherInit?
268
-
269
- debug! 10, "in mid eacher init (#{sadiekey})"
270
-
271
- memorizeEacherFileLocation( sadiekey, filepath )
272
-
273
- if params.has_key? :provides
274
-
275
- # make sure we're passing an array
276
- provide_array = params[:provides]
277
- provide_array.respond_to? "each" or provide_array = [provide_array]
278
-
279
- # tell sadie that the sadiekey primer also provides everything in the provide array
280
- setEachersProvidedByPrimer( sadiekey, provide_array )
281
-
282
- end
283
-
284
- elsif whichEacherFrame == occur_at
285
-
286
- # bugfix: running eachers that aren't supposed to be run because they're
287
- # in the same eacher file
288
- #puts "sadiekey: #{sadiekey}, getEacherKey: #{getEacherKey}"
289
- #return if sadiekey != getEacherKey
290
-
291
- occur_at != Sadie::EACH and debug! 10, "pre-yield for skey: #{sadiekey}, #{occur_at}"
292
-
293
- if block.arity == 0
294
- yield self
295
- else
296
- yield self, getEacherParam
297
- end
298
-
299
- occur_at != Sadie::EACH and debug! 10, "post-yield for skey: #{sadiekey}, #{occur_at}"
300
- end
301
- end
302
-
303
- # ==method: eacherFrame
304
- #
305
- # ( usually this will be called by the class method...it looks better )
306
- #
307
- # see class method eacherFrame for an explanation
308
- #
309
- def eacherFrame( sadiekey, occur_at, param=nil )
310
-
311
- occur_at != Sadie::EACH and debug! 8, "eacherFrame(#{occur_at}): #{sadiekey}"
312
-
313
- setEacherFrame( occur_at )
314
- defined? param and setEacherParam( param )
315
- setEacherKey sadiekey
316
- if filepaths = eacherFilepaths( sadiekey )
317
- filepaths.each do |filepath|
318
- occur_at != Sadie::EACH and debug! 8, "eacher frame loading: #{filepath} for sadiekey: #{sadiekey}"
319
- load filepath
320
- end
321
- end
322
- unsetEacherParam
323
- unsetEacherFrame
324
- unsetEacherKey
325
- end
326
-
327
-
328
- # ==method: addPrimerPluginsDirPath
329
- #
330
- # addPrimerPluginsDirPath adds a directory which will be scanned for plugins to
331
- # register just before initializePrimers looks for primers to initialize
332
- #
333
- def addPrimerPluginsDirPath( path )
334
-
335
- exppath = File.expand_path(path)
336
-
337
- # add the path to the system load path
338
- $LOAD_PATH.include?(exppath) \
339
- or $LOAD_PATH.unshift(exppath)
340
-
341
- # add the path to the pluginsdir array
342
- defined? @plugins_dir_paths \
343
- or @plugins_dir_paths = Array.new
344
- @plugins_dir_paths.include?(exppath) \
345
- or @plugins_dir_paths.unshift(exppath)
346
-
347
- @primer_plugins_initialized = nil
348
- return self
349
- end
350
-
351
- # ==method: prime
352
- #
353
- # ( usually this will be called by the class method...it looks better )
354
- #
355
- # see class method prime for an explanation
356
- #
357
- def prime( primer_definition, &block )
358
- # validate params
359
- defined? primer_definition \
360
- or raise "Prime called without parameters"
361
- primer_definition.is_a? Hash \
362
- or raise "Prime called without hash parameters"
363
- defined? primer_definition["provides"] \
364
- or raise "Prime called without provides parameter"
365
-
366
- # if initializing primers, just remember how to get back to the primer later,
367
- # otherwise, prime
368
- if midPrimerInit?
369
-
370
- # mid primer init, just memorize primer location
371
- memorizePrimerLocation( @mid_primer_filepath, getCurrentPrimerPluginFilepath, primer_definition["provides"] )
372
- else
373
-
374
- # run code block with the current sadie instance
375
- block.call( self )
376
-
377
- # loop thru all primer provides, ensuring each primed
378
- current_primer_filepath = getCurrentPrimerFilepath
379
- primer_definition["provides"].each do | key |
380
-
381
- # skip blank lines
382
- next if key.match /^\s*$/
383
-
384
- # key primed or raise error
385
- primed? key \
386
- or raise "primer definition file: #{current_primer_filepath} was supposed to define #{key}, but did not"
387
- end
388
- end
389
-
390
- end
391
-
392
- # ==method: registerPrimerPlugin
393
- #
394
- # ( usually this will be called by the class method...it looks better )
395
- #
396
- # see class method registerPrimerPlugin for an explanation
397
- #
398
- def registerPrimerPlugin ( arghash, &block )
399
-
400
- # if mid plugin init is set, we're registering the plugin
401
- # init mode, just store arghash info
402
- accepts_block = arghash.has_key?( "accepts-block" ) && arghash["accepts-block"] ? true : false
403
- prime_on_init = arghash.has_key?( "prime-on-init" ) && arghash["prime-on-init"] ? true : false
404
-
405
- # if mid plugin init, register the plugin params with the match
406
- if midPluginInit?
407
-
408
- regPluginMatch( arghash["match"], @mid_plugin_filepath, accepts_block, prime_on_init )
409
-
410
- # midplugininit returned false, we're actually in the process of either initializing
411
- # a primer or actually priming
412
- else
413
- yield self, getCurrentPrimerKeyPrefix, getCurrentPrimerFilepath
414
- end
415
- end
416
-
417
-
418
-
419
- # ==method: get
420
- #
421
- # a standard getter which primes the unprimed and recalls "expensive" facts from files
422
- # completely behind-the-scenes as directed by the resource (.res) files
423
- def get( k )
424
-
425
- debug! 10, "get(#{k})"
426
-
427
- defined? @eacher_frame_redirect or @eacher_frame_redirect = Hash.new
428
-
429
- if ! isset?( k )
430
- debug! 10, "#{k} is not set"
431
- if isEacherKey?( k )
432
- debug! 10, "sadiekey: #[k} is eacher, fetching: #{@eacher_frame_redirect[k]}"
433
- get @eacher_frame_redirect[k]
434
-
435
- elsif primeable?( k )
436
-
437
- debug! 10, "calling eacher from get method for #{k}"
438
- setUnbalancedEacher k
439
- Sadie::eacherFrame( k, BEFORE )
440
-
441
- # prime if not yet primed
442
- primed?( k ) or _prime( k )
443
- end
444
- end
445
-
446
- return _recallExpensive( k ) if expensive?( k )
447
-
448
- # if it's already set, return known answer
449
- if isset?( k )
450
-
451
- # _get the return value
452
- return_value = _get( k )
453
-
454
- # unset and unprime if destructOnGet?
455
- destroyOnGet?( k ) \
456
- and destroy! k
457
-
458
- return return_value
459
- end
460
-
461
- end
462
-
463
- # ==method: output
464
- #
465
- # an alias for get. intended for use with primers that produce an output beyond their return value
466
- def output( k )
467
- return get( k )
468
- end
469
-
470
- # ==method: isset?
471
- #
472
- # returns true if sadie has a value for the key
473
- def isset?( key )
474
- return true if @shortterm.has_key?( key )
475
- return true if expensive?( key )
476
- false
477
- end
478
-
479
- # ==method: setDestroyOnGet
480
- #
481
- # key value will go away and key will be unprimed and unset after next get
482
- #
483
- # NOTE: this doesn't make sense with keys that were set via setExpensive
484
- # so it can be set, but nothing's going to happen differently
485
- def setDestroyOnGet( key, turnon=true )
486
- if ( turnon )
487
- @flag_destroyonget["#{key}"] = true
488
- return true
489
- end
490
- @flag_destroyonget.has_key?( key ) \
491
- and @flag_destroyonget.delete( key )
492
- end
493
-
494
- # ==method: destroy!
495
- #
496
- # remove the key from sadie
497
- def destroy! ( key )
498
- unset( key )
499
- primed?( key ) and unprime( key )
500
- end
501
-
502
- # ==method: destroyOnGet?
503
- #
504
- # returns true if the destructOnGet flag is set for the key
505
- def destroyOnGet?( key )
506
- ( @flag_destroyonget.has_key?( key ) && @flag_destroyonget["#{key}"] )
507
- end
508
-
509
- # ==method: set
510
- # alias for setCheap(k,v)
511
- def set( k, v )
512
- setCheap( k, v )
513
- end
514
-
515
- # ==method: setCheap
516
- #
517
- # the cheap setter. key, value pairs stored via this method are kept in memory
518
- def setCheap( k, v )
519
-
520
- # debug! 8, "setting cheap: [#{k},#{v}]"
521
- Sadie::eacherFrame( k, BEFORE ) if ! eacherUnbalanced?( k )
522
- setUnbalancedEacher k
523
-
524
- if getDebugLevel == 10
525
- debug! 10, "dumping value:"
526
- pp v
527
- end
528
-
529
- # set it, mark not expensive and primed
530
- _set( k, v )
531
- _expensive( k, false )
532
- _primed( k, true )
533
-
534
- Sadie::eacherFrame( k, AFTER, v )
535
- clearUnbalancedEacher k
536
-
537
- end
538
-
539
- # ==method: setExpensive
540
- #
541
- # the expensive setter. key, value pairs stored via this method are not kept in memory
542
- # but are stored to file and recalled as needed
543
- def setExpensive(k,v)
544
-
545
- debug! 9, "setting expensive: #{k}"
546
- Sadie::eacherFrame( k, BEFORE ) if ! eacherUnbalanced?( k )
547
- setUnbalancedEacher k
548
-
549
-
550
- expensive_filepath = _computeExpensiveFilepath( k )
551
- serialized_value = Marshal::dump( v )
552
-
553
- File.exist? File.dirname( expensive_filepath ) \
554
- or Dir.mkdir File.dirname( expensive_filepath )
555
-
556
- File.open(expensive_filepath, 'w') { |f|
557
- f.write( serialized_value )
558
- }
559
- _expensive( k, true )
560
- _primed( k, true )
561
-
562
- Sadie::eacherFrame( k, AFTER, v )
563
- clearUnbalancedEacher k
564
- end
565
-
566
-
567
- # ==method: save
568
- #
569
- # serialize to session file
570
- def save
571
- session_id = get("sadie.session_id")
572
- session_filepath = File.expand_path( "session."+session_id, get( "sadie.sessions_dirpath" ) )
573
- serialized_value = Marshal::dump( [ @shortterm, @flag_primed, @flag_expensive ] )
574
- File.open(session_filepath, 'w') { |f|
575
- f.write( serialized_value )
576
- }
577
- return session_id
578
- end
579
-
580
- # ==method: revert!
581
- #
582
- # return to last saved state
583
- #
584
- def revert!
585
-
586
- @shortterm = {
587
- "sadie.session_id" => get( "sadie.session_id" ),
588
- "sadie.sessions_dirpath" => get( "sadie.sessions_dirpath" )
589
- }
590
-
591
- _initializeWithSessionId( get( "sadie.session_id" ) )
592
- end
593
-
594
- # ==method: initializePrimers
595
- #
596
- # call this method only after registering all the plugin directories and setting the
597
- # appropriate session and primer directory paths. after this is called, the key/val
598
- # pairs will be available via get
599
- #
600
- def initializePrimers
601
-
602
- Sadie::setCurrentSadieInstance( self )
603
-
604
- # make sure primer plugins have been initialized
605
- primerPluginsInitialized? \
606
- or initializePrimerPlugins
607
-
608
- eachersInitialized? \
609
- or initializeEachers
610
-
611
- primers_dirpath = get( "sadie.primers_dirpath" ) \
612
- or raise "sadie.primers_dirpath not set"
613
-
614
- return true if primersInitialized? primers_dirpath
615
-
616
- debug! 1, "Initializing primers..."
617
- initializePrimerDirectory( "", primers_dirpath )
618
- debug! 1, "...finished initializing primers."
619
-
620
- @flag_primed[primers_dirpath] = true
621
- end
622
-
623
- def getEacherKey
624
- return nil if ! defined? @eacher_key
625
- @eacher_key.last
626
- end
627
-
628
-
629
-
630
- # ------------------------------------------------------------------------------------------------
631
- # ------------------------------------------------------------------------------------------------
632
-
633
- private
634
-
635
- def setUnbalancedEacher( k )
636
- debug! 10, "setting eacher unbalanced: #{k}"
637
- defined? @eacher_unbalanced or @eacher_unbalanced = Hash.new
638
- @eacher_unbalanced[k] = true
639
- end
640
-
641
- def clearUnbalancedEacher( k )
642
- debug! 10, "clearing eacher unbalanced: #{k}"
643
- @eacher_unbalanced[k] = false if defined? @eacher_unbalanced
644
- end
645
-
646
- def eacherUnbalanced?( k )
647
- return false if ! defined? @eacher_unbalanced
648
- return false if ! @eacher_unbalanced.has_key?( k )
649
- return @eacher_unbalanced[k]
650
- end
651
-
652
- def cheap?( k )
653
- ! expensive? ( k )
654
- end
655
-
656
- # ==method: primed?
657
- #
658
- # INTERNAL: this method should only be called the the class method, Prime
659
- #
660
- def expensive?( k )
661
- @flag_expensive.has_key?( k ) or return false;
662
- @flag_expensive["#{k}"] \
663
- and return true
664
- return false
665
- end
666
-
667
-
668
- # == initialize eachers
669
- #
670
- # register all the eachers
671
- #
672
- # called by initializePrimers so it's not necessary to call this separate from that
673
- def initializeEachers
674
-
675
- primers_dirpath = get( "sadie.primers_dirpath" ) \
676
- or raise "sadie.primers_dirpath not set"
677
-
678
- puts "Initializing eachers..."
679
- setEacherInit
680
- initializeEacherDirectory( "", primers_dirpath )
681
- clearEacherInit
682
- puts "...finished initializing eachers."
683
-
684
-
685
- @eachers_initialized = true
686
- end
687
-
688
- def initializeEacherDirectory( key_prefix, current_dirpath )
689
-
690
- debug! 3, "initializing eacher directory: #{current_dirpath}"
691
- Dir.foreach( current_dirpath ) do |filename|
692
-
693
- # skip the dit dirs
694
- next if filename.eql?(".") || filename.eql?("..") || filename =~ /\~$/
695
-
696
-
697
- filepath = File.expand_path( filename, current_dirpath )
698
-
699
- if File.directory? filepath
700
- new_key_prefix = key_prefix + '.' + filename
701
- new_key_prefix = new_key_prefix.gsub(/^\.+/,"")
702
- initializeEacherDirectory( new_key_prefix, filepath )
703
- else
704
- if filename =~ /\.each(?:\..*)*$/
705
- initializeEacherFile( key_prefix, filepath )
706
- end
707
- end
708
- end
709
- end
710
-
711
- def initializeEacherFile( key_prefix, filepath )
712
- debug! 8, "initializing eacher file (#{key_prefix}): #{filepath}"
713
- setCurrentPrimerFilepath filepath
714
- setCurrentPrimerKeyPrefix key_prefix
715
- load filepath
716
- end
717
-
718
- def eachersInitialized?
719
- defined? @eachers_initialized or return false
720
- @eachers_initialized and return true
721
- return false
722
- end
723
-
724
-
725
-
726
-
727
- def whichEacherFrame
728
- return nil if ! defined? @eacher_frame
729
- @eacher_frame.last
730
- end
731
-
732
- def setEacherFrame( f )
733
- defined? @eacher_frame or @eacher_frame = Array.new
734
- @eacher_frame.push f
735
- end
736
-
737
- def unsetEacherFrame
738
- if defined? @eacher_frame
739
- @eacher_frame.pop
740
- end
741
- end
742
-
743
- def setEacherParam( p )
744
- defined? @eacher_param or @eacher_param = Array.new
745
- @eacher_param.push p
746
- end
747
-
748
- def unsetEacherParam
749
- if defined? @eacher_param
750
- @eacher_param.pop
751
- end
752
- end
753
-
754
- def getEacherParam
755
- return nil if ! defined? @eacher_param
756
- @eacher_param.last
757
- end
758
-
759
- def setEacherKey( k )
760
- defined? @eacher_key or @eacher_key = Array.new
761
- @eacher_key.push k
762
- end
763
-
764
- def unsetEacherKey
765
- if defined? @eacher_key
766
- @eacher_key.pop
767
- end
768
- end
769
-
770
-
771
- def isEacherKey?( key )
772
-
773
- defined? @eacher_frame_redirect or return false
774
- @eacher_frame_redirect.has_key? key or return false
775
- return true
776
- end
777
-
778
- def getEacherDependency( key )
779
- defined? @eacher_frame_redirect or return nil
780
- @eacher_frame_redirect.has_key? key or return nil
781
- @eacher_frame_redirect[key]
782
- end
783
-
784
- def getEachersProvidedByPrimer( sadiekey )
785
- defined? @eachers_provided or return nil
786
- @eachers_provided.has_key? sadiekey or return nil
787
- @eachers_provided[sadiekey]
788
- end
789
-
790
-
791
-
792
- def eacherFilepaths( sadiekey )
793
- defined? @eacher_filepaths or return nil
794
- @eacher_filepaths.has_key? sadiekey or return nil
795
- @eacher_filepaths[sadiekey]
796
- end
797
-
798
- def midEacherInit?
799
- defined? @eacher_init or return false
800
- @eacher_init or return false
801
- true
802
- end
803
-
804
- def setEacherInit
805
- @eacher_init = true
806
- end
807
-
808
- def clearEacherInit
809
- @eacher_init = nil
810
- end
811
-
812
-
813
- def setEachersProvidedByPrimer( sadiekey, providers )
814
-
815
- # record reverse map for use by eacherFrame
816
- defined? @eacher_frame_redirect \
817
- or @eacher_frame_redirect = Hash.new
818
- providers.each do |provider|
819
- debug! 10, "setting provider reverse map for #{provider} to #{sadiekey}"
820
- @eacher_frame_redirect[provider] = sadiekey
821
- end
822
-
823
- defined? @eachers_provided or @eachers_provided = Hash.new
824
- if @eachers_provided.has_key? sadiekey
825
- @eachers_provided[sadiekey] = @eachers_provided[sadiekey].concat( providers )
826
- else
827
- @eachers_provided[sadiekey] = providers
828
- end
829
- end
830
-
831
-
832
-
833
- def memorizeEacherFileLocation( sadiekey, filepath )
834
- debug! 8, "memorizing eacher file location: #{filepath} for #{sadiekey}"
835
- # store the file path
836
- defined? @eacher_filepaths or @eacher_filepaths = Hash.new
837
- if ! @eacher_filepaths.has_key? sadiekey
838
- @eacher_filepaths[sadiekey] = [filepath]
839
- elsif ! @eacher_filepaths[sadiekey].include? filepath
840
- @eacher_filepaths[sadiekey].push filepath
841
- end
842
- end
843
-
844
-
845
-
846
- # ==method: unprime
847
- # unprimes k. Note that this does not unset the value, so
848
- # get(key) will continue to return whatever it otherwise would have.
849
- # run unset as well to have the primer run again.
850
- def unprime( key )
851
- _primed( key, false )
852
- end
853
-
854
- # ==method: primed?
855
- #
856
- # INTERNAL: this method should only be called the the class method, Prime
857
- #
858
- def primed?( k )
859
-
860
- isset?( k ) and return true
861
-
862
- @flag_primed.has_key?( k ) \
863
- or return false
864
- @flag_primed["#{k}"] \
865
- and return true
866
- return false
867
- end
868
-
869
- # direct access getter for shortterm memory
870
- def _get( key )
871
- value = @shortterm["#{key}"]
872
- return value
873
- end
874
-
875
-
876
-
877
- def primerPluginRegistered?( filename )
878
-
879
- @primer_plugin_lookup.each do | plugin_array |
880
- re, path,accepts_block = plugin_array
881
- re.match( filename ) \
882
- and return true
883
- end
884
- return false;
885
- end
886
-
887
- def currentPrimerPluginAcceptsBlock( accepts )
888
- @primer_plugin_accepts_block = accepts
889
- end
890
-
891
- def currentPrimerPluginAcceptsBlock?
892
- @primer_plugin_accepts_block
893
- end
894
-
895
- def currentPrimerPluginPrimeOnInit( prime_on_init )
896
- @primer_plugin_prime_on_init = prime_on_init
897
- end
898
-
899
- def currentPrimerPluginPrimeOnInit?
900
- @primer_plugin_prime_on_init
901
- end
902
-
903
- def setMidPluginInit( filepath )
904
- @mid_plugin_initialization = true
905
- @mid_plugin_filepath = filepath
906
- end
907
-
908
- def unsetMidPluginInit
909
- @mid_plugin_initialization = false
910
- end
911
-
912
- def midPluginInit?
913
- @mid_plugin_initialization
914
- end
915
-
916
- def regPluginMatch ( regexp, filepath, accepts_block, prime_on_init )
917
- @primer_plugin_lookup.push( [ regexp, filepath, accepts_block, prime_on_init ] )
918
- end
919
-
920
- def primerPluginsInitialized?
921
- @primer_plugins_initialized
922
- end
923
-
924
- # == initializePrimerPlugins
925
- #
926
- # register all the primer plugins
927
- #
928
- # called by initializePrimers so it's not necessary to call this separate from that
929
- def initializePrimerPlugins
930
-
931
- defined? @plugins_dir_paths \
932
- or raise 'plugins_dir_paths not set'
933
-
934
- debug! 1, "Initializing primer plugins..."
935
-
936
- # load the plugins
937
- @plugins_dir_paths.each do | dirpath |
938
- Dir.foreach( dirpath ) do |filename|
939
- next if ! filename.match( /\.plugin\.rb$/ )
940
-
941
- filepath = File.expand_path( filename, dirpath )
942
-
943
- debug! 2, "initializing primer plugin with file: #{filename}"
944
-
945
- setMidPluginInit( filepath )
946
- load( filename )
947
- unsetMidPluginInit
948
- end
949
- end
950
- debug! 1, "...finished initializing primer plugins"
951
- @primer_plugins_initialized = true
952
- end
953
-
954
- def setMidPrimerInit ( filepath )
955
- @mid_primer_initialization = true
956
- @mid_primer_filepath = filepath
957
- end
958
-
959
- def unsetMidPrimerInit
960
- @mid_primer_initialization = false
961
- end
962
-
963
- def midPrimerInit?
964
- @mid_primer_initialization \
965
- and return true;
966
- return false;
967
- end
968
-
969
-
970
-
971
- def primersInitialized? ( toplevel_dirpath )
972
- @flag_primed.has_key?( toplevel_dirpath ) \
973
- or return false;
974
- return @flag_primed[toplevel_dirpath]
975
- end
976
-
977
- def initializePrimerDirectory( key_prefix, current_dirpath )
978
- puts "initializing primer directory: #{current_dirpath}"
979
- Dir.foreach( current_dirpath ) do |filename|
980
-
981
- # skip the dit dirs
982
- next if filename.eql?(".") || filename.eql?("..") || filename =~ /\~$/
983
-
984
- filepath = File.expand_path( filename, current_dirpath )
985
-
986
- if File.directory? filepath
987
- new_key_prefix = key_prefix + '.' + filename
988
- new_key_prefix = new_key_prefix.gsub(/^\.+/,"")
989
- initializePrimerDirectory( new_key_prefix, filepath )
990
- else
991
- initializePrimerFile( key_prefix, filepath )
992
- end
993
- end
994
- end
995
-
996
- def initializePrimerFile( key_prefix, filepath )
997
-
998
-
999
- basename = File.basename( filepath )
1000
- if primerPluginRegistered? basename
1001
- setCurrentPrimerFilepath filepath
1002
-
1003
- setCurrentPrimerKeyPrefix key_prefix
1004
-
1005
- basename = File.basename( filepath )
1006
- initializePrimerWithPlugin( key_prefix, filepath )
1007
-
1008
-
1009
- end
1010
- end
1011
-
1012
- def initializePrimerWithPlugin( key_prefix, filepath )
1013
-
1014
- debug! 9, "initializing primer file #{File.basename(filepath)} with plugin"
1015
-
1016
- @primer_plugin_lookup.each do | plugin_array |
1017
-
1018
- # we just need to match the basename
1019
- filename = File.basename( filepath )
1020
-
1021
- regexp, plugin_filepath, accepts_block, prime_on_init = plugin_array
1022
-
1023
- if regexp.match( filename )
1024
-
1025
- setCurrentPrimerPluginFilepath( plugin_filepath )
1026
- prime_on_init \
1027
- or setMidPrimerInit( filepath )
1028
-
1029
- plugin_filename = File.basename( plugin_filepath )
1030
-
1031
- load( plugin_filepath )
1032
-
1033
- prime_on_init \
1034
- or unsetMidPrimerInit
1035
-
1036
-
1037
- return
1038
- end
1039
- end
1040
- end
1041
-
1042
- def setCurrentPrimerPluginFilepath( filepath )
1043
- @current_primer_plugin_filepath = filepath
1044
- end
1045
-
1046
- def getCurrentPrimerPluginFilepath
1047
- @current_primer_plugin_filepath
1048
- end
1049
-
1050
- def setCurrentPrimerKeyPrefix ( prefix )
1051
- @current_primer_keyprefix = prefix
1052
- end
1053
-
1054
- def getCurrentPrimerKeyPrefix
1055
- @current_primer_keyprefix
1056
- end
1057
-
1058
- def setCurrentPrimerFilepath ( filepath )
1059
- @current_primer_filepath = filepath
1060
- end
1061
-
1062
- def getCurrentPrimerFilepath
1063
- @current_primer_filepath
1064
- end
1065
-
1066
- def setCurrentPrimerRequestingKey( key )
1067
- @current_primer_requesting_key = key
1068
- end
1069
-
1070
- def getCurrentPrimerRequestingKey
1071
- @current_primer_requesting_key
1072
- end
1073
-
1074
- # ==memorizePrimerLocation
1075
- #
1076
- # internal, ignore the man behind the curtain
1077
- def memorizePrimerLocation( filepath, plugin_filepath, primer_provides )
1078
-
1079
- # validate primer hash
1080
- #primer_dirpath = @mid_primer_toplevel_primer_dirpath
1081
- primer_dirpath = _get("sadie.primers_dirpath")
1082
- @primer_hash.has_key?( primer_dirpath ) \
1083
- or @primer_hash["#{primer_dirpath}"] = Hash.new
1084
-
1085
- # interate over provides setting primer providers for each
1086
- primer_provides.each do | key |
1087
- setPrimerProvider( key, filepath, plugin_filepath, getCurrentPrimerKeyPrefix )
1088
-
1089
- end
1090
-
1091
- end
1092
-
1093
-
1094
- # ==setPrimerProvider
1095
- #
1096
- # internal, ignore the man behind the curtain
1097
- def setPrimerProvider( primer_name, primer_filepath, primer_plugin_filepath, key_prefix )
1098
-
1099
- primer_dirpath = _get( "sadie.primers_dirpath" )
1100
- @primer_hash.has_key?( primer_dirpath ) \
1101
- or @primer_hash[primer_dirpath] = Hash.new
1102
-
1103
- @primer_hash["#{primer_dirpath}"]["#{primer_name}"] = [ primer_filepath, primer_plugin_filepath, key_prefix ]
1104
-
1105
- end
1106
-
1107
- def primeable?( key )
1108
- p = getPrimerProvider( key )
1109
- return nil if ! defined? (p )
1110
- return nil if p == nil
1111
- return true
1112
- end
1113
-
1114
- def getPrimerProvider( key )
1115
-
1116
- # fetch primers dirpath and validate the primer hash
1117
- primer_dirpath = _get( "sadie.primers_dirpath" )
1118
- @primer_hash.has_key?( primer_dirpath ) \
1119
- or @primer_hash[primer_dirpath] = Hash.new
1120
-
1121
- primers = @primer_hash[primer_dirpath]
1122
- primers.has_key?( key ) \
1123
- or return nil # primer not defined
1124
-
1125
- return primers[key]
1126
- end
1127
-
1128
-
1129
-
1130
- def _primed ( k, is_primed )
1131
- defined? k \
1132
- or raise '_primed> reqd parameter, k, was undefined'
1133
- k.is_a?( String ) \
1134
- or raise '_primed> reqd parameter, k, was non-string'
1135
- if ( is_primed )
1136
- @flag_primed[k] = true
1137
- return true
1138
- end
1139
- @flag_primed.has_key?( k ) \
1140
- or return true
1141
- @flag_primed.delete( k )
1142
- end
1143
-
1144
- def _prime ( k )
1145
-
1146
- debug! 10, "priming: #{k}"
1147
-
1148
- if isEacherKey? k
1149
- get( getEacherDependency( k ) )
1150
- else
1151
-
1152
- #Sadie::eacherFrame( k, BEFORE )
1153
- if provider = getPrimerProvider( k )
1154
- primer_filepath, plugin_filepath, key_prefix = provider
1155
-
1156
- currfilepath = getCurrentPrimerFilepath
1157
-
1158
- setCurrentPrimerFilepath(primer_filepath)
1159
- setCurrentPrimerKeyPrefix( key_prefix )
1160
- Sadie::setCurrentSadieInstance( self )
1161
-
1162
- load plugin_filepath
1163
-
1164
- if defined? currfilepath
1165
- setCurrentPrimerFilepath currfilepath
1166
- end
1167
- end
1168
- #Sadie::eacherFrame( k, AFTER )
1169
- end
1170
- end
1171
-
1172
-
1173
- def _newline( rval=true )
1174
- return rval
1175
- end
1176
-
1177
- # ==method: unset
1178
- # unsets the value of k. Note that this does not unprime, so
1179
- # get(key) will simply return nil. Run with unprime to have the
1180
- # primer run again
1181
- def unset( key )
1182
- _unset( key )
1183
- end
1184
-
1185
- def _recallExpensive( k )
1186
- expensive_filepath = _computeExpensiveFilepath( k )
1187
- File.exists? expensive_filepath \
1188
- or raise "expensive filepath: #{filepath} does not exist"
1189
- f = open( expensive_filepath )
1190
- v = Marshal::load( f.read )
1191
-
1192
- return v
1193
- end
1194
-
1195
- def _computeExpensiveFilepath( k )
1196
- session_id = get( "sadie.session_id" )
1197
- File.expand_path("session."+session_id+".exp."+k, _get( "sadie.sessions_dirpath" ) )
1198
- end
1199
-
1200
- def _expensive( k, isexpensive )
1201
- if isexpensive
1202
- @flag_expensive["#{k}"] = true
1203
- return
1204
- end
1205
- @flag_expensive.delete( k )
1206
- end
1207
-
1208
- # direct access setter for shortterm memory
1209
- def _set( key, value )
1210
- @shortterm["#{key}"] = value
1211
- end
1212
-
1213
- def _unset( key )
1214
- @shortterm.has_key?( key ) \
1215
- and @shortterm.delete( key )
1216
- end
1217
-
1218
-
1219
- # init given path to session file
1220
- def _initializeWithSessionFilePath( session_filepath )
1221
-
1222
- puts "session_filepath: #{session_filepath}"
1223
-
1224
- defined?( session_filepath ) \
1225
- or raise "session_filepath was undefined"
1226
-
1227
- /^\s*$/.match("#{session_filepath}") \
1228
- and raise "session_filepath was empty string"
1229
-
1230
- # bail on non-existant file
1231
- File.exist?( session_filepath ) \
1232
- or raise "session file, " + session_filepath + " does not exist"
1233
-
1234
- # open session file and read internal vars from it
1235
- File.open( session_filepath, "r" ).each do |f|
1236
-
1237
- # make sure no writing happens while we read
1238
- f.flock(File::Lock_SH)
1239
-
1240
- # read vars from file
1241
- mem, primed, expensive = Marshal::load( f.read )
1242
- end
1243
-
1244
- # destructive set on flag vars
1245
- @flag_primed = primed
1246
- @flag_expensive = expensive
1247
-
1248
- # additive set on shortterm mem
1249
- mem.each do |k,v|
1250
- set(k, v)
1251
- end
1252
- end
1253
-
1254
- # init given session id
1255
- def _initializeWithSessionId(session_id)
1256
- session_filepath = File.expand_path( "session."+session_id, _get( "sadie.sessions_dirpath" ) )
1257
- _initializeWithSessionFilePath( session_filepath )
1258
- end
1259
-
1260
- # gen new session id
1261
- def _generateNewSessionId
1262
- begin
1263
- value = ""
1264
- 24.times{value << (65 + rand(25)).chr}
1265
- end while File.exist?(File.expand_path("session."+value, get( "sadie.sessions_dirpath" ) ) )
1266
- return value
1267
- end
1268
-
1269
- # ==method: checkInstanceSanity
1270
- #
1271
- # verifies that needed instance variables are defined
1272
- def _checkInstanceSanity
1273
- defined? @shortterm \
1274
- or @shortterm = Hash.new
1275
- defined? @flag_expensive \
1276
- or @flag_expensive = Hash.new
1277
- defined? @flag_destroyonget \
1278
- or @flag_destroyonget = Hash.new
1279
- defined? @flag_primed \
1280
- or @flag_primed = Hash.new
1281
-
1282
- end
1283
-
1284
- # ==method: checkClassSanity
1285
- #
1286
- # verifies that needed class variables are defined
1287
- def _checkClassSanity
1288
- defined? @flag_primed \
1289
- or @flag_primed = Hash.new
1290
-
1291
- # init primer plugin vars
1292
- if ( ! defined? @primer_plugin_lookup )
1293
- @mid_plugin_initialization = false
1294
- @primer_plugin_lookup = Array.new
1295
- @primer_plugins_initialized = false
1296
- end
1297
-
1298
- # init primer vars
1299
- defined? @primer_hash \
1300
- or @primer_hash = Hash.new
1301
- defined? @flag_primed \
1302
- or @flag_primed = Hash.new
1303
- if ! defined? @mid_primer_initialization
1304
- @mid_primer_initialization = false
1305
- @mid_primer_filepath = nil
1306
- end
1307
-
1308
- end
1309
-
1310
-
1311
- end
1312
-
1313
- require "sadie/version"
1314
- require "sadie/defaults"
1315
-