Class: Xampl::Persister

Inherits:
Object
  • Object
show all
Defined in:
lib/xamplr/persister.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name = nil, format = nil) ⇒ Persister

Returns a new instance of Persister.



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/xamplr/persister.rb', line 20

def initialize(name=nil, format=nil)
  @name = name
  @format = format
  @automatic = false
  @changed = {}
  @expunged = Set.new
  @cache_hits = 0
  @total_cache_hits = 0
  @read_count = 0
  @total_read_count = 0
  @write_count = 0
  @total_write_count = 0
  @last_write_count = 0
  @last_cache_hits = 0
  @total_sync_count = 0
  @total_rollback_count = 0
  @rolled_back = false
  @syncing = false
  @slow_sync = 0.25

  @busy_count = 0
end

Instance Attribute Details

#automaticObject

Returns the value of attribute automatic.



7
8
9
# File 'lib/xamplr/persister.rb', line 7

def automatic
  @automatic
end

#block_changesObject

Returns the value of attribute block_changes.



7
8
9
# File 'lib/xamplr/persister.rb', line 7

def block_changes
  @block_changes
end

#cache_hitsObject

Returns the value of attribute cache_hits.



7
8
9
# File 'lib/xamplr/persister.rb', line 7

def cache_hits
  @cache_hits
end

#expungedObject

Returns the value of attribute expunged.



7
8
9
# File 'lib/xamplr/persister.rb', line 7

def expunged
  @expunged
end

#formatObject (readonly)

Returns the value of attribute format.



18
19
20
# File 'lib/xamplr/persister.rb', line 18

def format
  @format
end

#last_write_countObject

Returns the value of attribute last_write_count.



7
8
9
# File 'lib/xamplr/persister.rb', line 7

def last_write_count
  @last_write_count
end

#nameObject

Returns the value of attribute name.



7
8
9
# File 'lib/xamplr/persister.rb', line 7

def name
  @name
end

#read_countObject

Returns the value of attribute read_count.



7
8
9
# File 'lib/xamplr/persister.rb', line 7

def read_count
  @read_count
end

#rolled_backObject

Returns the value of attribute rolled_back.



7
8
9
# File 'lib/xamplr/persister.rb', line 7

def rolled_back
  @rolled_back
end

#slow_syncObject

Returns the value of attribute slow_sync.



7
8
9
# File 'lib/xamplr/persister.rb', line 7

def slow_sync
  @slow_sync
end

#syncingObject (readonly)

Returns the value of attribute syncing.



18
19
20
# File 'lib/xamplr/persister.rb', line 18

def syncing
  @syncing
end

#total_cache_hitsObject

Returns the value of attribute total_cache_hits.



7
8
9
# File 'lib/xamplr/persister.rb', line 7

def total_cache_hits
  @total_cache_hits
end

#total_read_countObject

Returns the value of attribute total_read_count.



7
8
9
# File 'lib/xamplr/persister.rb', line 7

def total_read_count
  @total_read_count
end

#total_rollback_countObject

Returns the value of attribute total_rollback_count.



7
8
9
# File 'lib/xamplr/persister.rb', line 7

def total_rollback_count
  @total_rollback_count
end

#total_sync_countObject

Returns the value of attribute total_sync_count.



7
8
9
# File 'lib/xamplr/persister.rb', line 7

def total_sync_count
  @total_sync_count
end

#total_write_countObject

Returns the value of attribute total_write_count.



7
8
9
# File 'lib/xamplr/persister.rb', line 7

def total_write_count
  @total_write_count
end

#write_countObject

Returns the value of attribute write_count.



7
8
9
# File 'lib/xamplr/persister.rb', line 7

def write_count
  @write_count
end

Class Method Details

.replace(old_xampl, new_xampl) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/xamplr/persister.rb', line 105

def Persister.replace(old_xampl, new_xampl)
  pid = old_xampl.get_the_index
  if old_xampl.persister != @@persister then
    raise MixedPersisters.new(@@persister, old_xampl.persister)
  end
  if new_xampl.persister != @@persister then
    raise MixedPersisters.new(@@persister, new_xampl.persister)
  end

  new_xampl.note_replacing(old_xampl)

  unless old_xampl.load_needed then
    Xampl.log.warn("Replacing live xampl: #{old_xampl} pid: #{pid}")
    @@persister.uncache(old_xampl)
    old_xampl.invalidate
  end
  new_xampl.pid = nil
  new_xampl.pid = pid
  @@persister.introduce(new_xampl)
end

Instance Method Details

#busy(yes) ⇒ Object



55
56
57
58
59
60
61
# File 'lib/xamplr/persister.rb', line 55

def busy(yes)
  if yes then
    @busy_count += 1
  elsif 0 < @busy_count then
    @busy_count -= 1
  end
end

#cache(xampl) ⇒ Object

Raises:



93
94
95
# File 'lib/xamplr/persister.rb', line 93

def cache(xampl)
  raise XamplException.new(:unimplemented)
end

#clear_cacheObject

Raises:



101
102
103
# File 'lib/xamplr/persister.rb', line 101

def clear_cache
  raise XamplException.new(:unimplemented)
end

#closeObject



46
47
48
# File 'lib/xamplr/persister.rb', line 46

def close
  self.sync
end

#count_changedObject



86
87
88
89
90
91
# File 'lib/xamplr/persister.rb', line 86

def count_changed
#      @changed.each{ | thing, ignore |
  #        puts "changed: #{thing}, index: #{thing.get_the_index}"
  #      }
  return @changed.size
end

#do_sync_writeObject



229
230
231
232
233
234
235
236
237
# File 'lib/xamplr/persister.rb', line 229

def do_sync_write
  unchanged_in_changed_list = 0
  @changed.each do |xampl, ignore|
    unchanged_in_changed_list += 1 unless xampl.is_changed
    unless xampl.kind_of?(InvalidXampl) then
      write(xampl)
    end
  end
end

#done_sync_writeObject



225
226
227
# File 'lib/xamplr/persister.rb', line 225

def done_sync_write
  # only if needed
end

#expunge(xampl) ⇒ Object



173
174
175
# File 'lib/xamplr/persister.rb', line 173

def expunge(xampl)
  false
end

#find_known(klass, pid) ⇒ Object



193
194
195
196
197
198
199
# File 'lib/xamplr/persister.rb', line 193

def find_known(klass, pid)
  #raise XamplException.new(:live_across_rollback) if @rolled_back

  xampl = read_from_cache(klass, pid, nil)

  return xampl
end

#find_xampl(hint = false) ⇒ Object



165
166
167
168
169
170
171
# File 'lib/xamplr/persister.rb', line 165

def find_xampl(hint=false)
  if hint then
    return [], "no query made"
  else
    return []
  end
end

#has_changed(xampl) ⇒ Object



74
75
76
77
78
79
# File 'lib/xamplr/persister.rb', line 74

def has_changed(xampl)
  if xampl.persist_required && xampl.is_changed then
    raise MixedPersisters.new(xampl.persister, self) unless self == xampl.persister
    @changed[xampl] = xampl
  end
end

#has_not_changed(xampl) ⇒ Object



81
82
83
84
# File 'lib/xamplr/persister.rb', line 81

def has_not_changed(xampl)
  #       puts "!!!! has_not_changed #{xampl} #{xampl.get_the_index} -- in @changed: #{nil != @changed[xampl]}"
  @changed.delete(xampl) if xampl
end

#introduce(xampl) ⇒ Object



67
68
69
70
71
72
# File 'lib/xamplr/persister.rb', line 67

def introduce(xampl)
  if xampl.introduce_persister(self) then
    cache(xampl)
  end
  has_changed(xampl) if xampl.is_changed
end

#is_busyObject



63
64
65
# File 'lib/xamplr/persister.rb', line 63

def is_busy
  return 0 < @busy_count
end

#lazy_load(target, klass, pid) ⇒ Object



201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/xamplr/persister.rb', line 201

def lazy_load(target, klass, pid)
  #      puts "#{File.basename(__FILE__)} #{__LINE__} LAZY_LOAD:: klass: #{klass} pid: #{pid} target: #{target}"

  xampl = read(klass, pid, target)

  # puts "   LAZY_LOAD --> #{xampl}"
  unless xampl
    puts "*******************************************************************************"
    puts "***** LAZY_LOAD FAILED:: klass: #{klass} pid: #{pid} target: #{target}"
    puts "*******************************************************************************"
  end

  return xampl
end

#lookup(klass, pid) ⇒ Object



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/xamplr/persister.rb', line 177

def lookup(klass, pid)
  #raise XamplException.new(:live_across_rollback) if @rolled_back
  #puts "#{File.basename(__FILE__)} #{__LINE__} LOOKUP:: klass: #{klass} pid: #{pid}"

  begin
    busy(true)
    xampl = read(klass, pid)
  ensure
    busy(false)
  end

  #puts "#{File.basename(__FILE__)} #{__LINE__}       ---> #{ xampl }"

  return xampl
end

#optimise(opts) ⇒ Object



43
44
# File 'lib/xamplr/persister.rb', line 43

def optimise(opts)
end


321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
# File 'lib/xamplr/persister.rb', line 321

def print_stats
  printf("SYNC[%s]:: TOTAL cache_hits: %d, reads: %d, writes: %d\n",
         self.name, @total_cache_hits, @total_read_count, @total_write_count)
  printf("             cache_hits: %d, reads: %d, writes: %d, time: %fms \n",
         @last_cache_hits, @read_count, @last_write_count, @last_sync_time)
  printf("             syncs: %d\n", @total_sync_count)
  if 0 < @changed.size then
    printf("             changed count: %d (%d)\n", count_changed, @changed.size)
    @changed.each do |thing, ignore|
      if thing.is_changed then
        puts "             changed: #{thing}, index: #{thing.get_the_index}"
      else
        puts "             UNCHANGED: #{thing}, index: #{thing.get_the_index} <<<<<<<<<<<<<<<<<<< BAD!"
      end
    end
  end
end

#put_changed(msg = "") ⇒ Object



216
217
218
219
# File 'lib/xamplr/persister.rb', line 216

def put_changed(msg="")
  puts "Changed::#{msg}:"
  @changed.each { |xampl, ignore| puts " #{xampl.tag} #{xampl.get_the_index}" }
end

#query_implementedObject



161
162
163
# File 'lib/xamplr/persister.rb', line 161

def query_implemented
  false
end

#read(klass, pid, target = nil) ⇒ Object

Raises:



157
158
159
# File 'lib/xamplr/persister.rb', line 157

def read(klass, pid, target=nil)
  raise XamplException.new(:unimplemented)
end

#realise(representation, target = nil) ⇒ Object



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/xamplr/persister.rb', line 136

def realise(representation, target=nil)
  # This is a bit brutal, but it works (and, anyway, it *is* the rule is that this is supposed to be UTF-8)
  representation_fixed = representation.encode('UTF-8', 'UTF-8', :invalid => :replace, :undef => :replace)

  xampl = nil

  # These days 'new' representations can only be XML. Historically it could have been Ruby. Check the
  # representations (quickly) and choose appropriately.
  if '<' == representation_fixed[0] then
    # well it isn't ruby, so it must be XML. Of course this means no leading whitespace, which happens to be true.
    xampl = XamplObject.realise_from_xml_string(representation_fixed, target)
  else
    xampl = XamplObject.from_ruby(representation_fixed, target)
  end
  return xampl.note_realised
end

#represent(xampl, mentions = []) ⇒ Object



126
127
128
129
130
131
132
133
134
# File 'lib/xamplr/persister.rb', line 126

def represent(xampl, mentions=[])
  rep = xampl.persist("", mentions)
  return rep
rescue => e
  msg = "Failed to represent #{ xampl } due to: #{ e }"
  puts msg
  puts e.backtrace
  raise msg
end

#rollbackObject



307
308
309
310
311
312
313
314
315
# File 'lib/xamplr/persister.rb', line 307

def rollback
  begin
    busy(true)

    return Xampl.rollback(self)
  ensure
    busy(false)
  end
end

#rollback_cleanupObject



317
318
319
# File 'lib/xamplr/persister.rb', line 317

def rollback_cleanup
  @changed = {}
end

#shutdownObject



50
51
52
53
# File 'lib/xamplr/persister.rb', line 50

def shutdown
#      self.sync
#      self.close
end

#start_sync_writeObject



221
222
223
# File 'lib/xamplr/persister.rb', line 221

def start_sync_write
  #only if needed
end

#syncObject



239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/xamplr/persister.rb', line 239

def sync
  @last_sync_time = Time.now
  #raise XamplException.new(:live_across_rollback) if @rolled_back
  begin
    if 0 < @changed.size then
#          puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] SYNC changed: #{@changed.size}"
#          @changed.each do | key, value |
#            puts "    key: #{key.class.name}, pid: #{key.get_the_index}"
#          end

#          caller(0).each do | trace |
#            next if /xamplr/ =~ trace
#            puts " #{trace}"
#            break if /actionpack/ =~ trace
#          end

      duration = Time.now
      begin
        busy(true)
        @syncing = true

        start_sync_write
        do_sync_write
      ensure
        done_sync_write
        @syncing = false
      end

      duration = Time.now - duration
      if @slow_sync < duration.to_f then
        puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] SLOW SYNC(#{ duration.to_f }s), changed: #{ @changed.size }"
        @changed.each do |key, value|
          puts "    key: #{ key.class.name }, pid: #{ key.get_the_index }"
        end
      end
    end

    @changed = {}

    puts "SOME NOT EXPUNGED: #{ @expunged.inspect }" unless 0 == @expunged.size
    @expunged = Set.new

    @total_read_count += @read_count
    @total_write_count += @write_count
    @total_cache_hits += @cache_hits
    @total_sync_count += 1

    @last_cache_hits = @cache_hits
    @last_write_count = @write_count
    @cache_hits = 0
    @read_count = 0
    @write_count = 0

    self.sync_done()

    return @last_write_count
  ensure
    busy(false)
#        puts "#{ __FILE__ }:#{ __LINE__ } [#{__method__}] **** SYNCING IS FALSE"
    @syncing = false
    @last_sync_time = Time.now - @last_sync_time
  end
end

#sync_doneObject

Raises:



303
304
305
# File 'lib/xamplr/persister.rb', line 303

def sync_done
  raise XamplException.new(:unimplemented)
end

#uncache(xampl) ⇒ Object

Raises:



97
98
99
# File 'lib/xamplr/persister.rb', line 97

def uncache(xampl)
  raise XamplException.new(:unimplemented)
end

#write(xampl) ⇒ Object

Raises:



153
154
155
# File 'lib/xamplr/persister.rb', line 153

def write(xampl)
  raise XamplException.new(:unimplemented)
end