Class: FilesystemEnv::GlueEnv

Inherits:
Object
  • Object
show all
Includes:
FilesystemViews
Defined in:
lib/glue_envs/filesystem_glue_env.rb

Constant Summary collapse

PersistLayerKey =

is the full path including node_key transform

:node_path
VersionKey =

see mysql_glue_env to decouple persistent layer key from node key

:_rev
NamespaceKey =

to have timestamp

:files_namespace
MoabDataStoreDir =

FileSystemMetadataKeys = [PersistLayerKey]

".model"
MoabDatastoreName =
".node_data.json"
@@log =

This class provides a generic persistence layer interface to the outside world that maps to the specific implementations of the underlying persistent layers Set Logger

TinkitLog.set(self.name, :warn)

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from FilesystemViews

by_my_category, #call_view

Constructor Details

#initialize(persist_env, data_model_bindings) ⇒ GlueEnv

Returns a new instance of GlueEnv.



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/glue_envs/filesystem_glue_env.rb', line 167

def initialize(persist_env, data_model_bindings)
  #TODO: determine if class_name is needed to segment cluster data within user data
  
  #via environmental settings
  filesystem_env = persist_env[:env]
  #key_fields = persist_env[:key_fields]
  fs_path = filesystem_env[:path]
  @user_id = filesystem_env[:user_id]
  @cluster_name = persist_env[:name]
  
  #data_model_bindings from NodeElementOperations
  key_fields = data_model_bindings[:key_fields] 
  initial_views_data = data_model_bindings[:views]
  
  @required_instance_keys = key_fields[:required_keys] #DataStructureModels::Tinkit::RequiredInstanceKeys
  @required_save_keys = key_fields[:required_keys] #DataStructureModels::Tinkit::RequiredSaveKeys
  @node_key = key_fields[:primary_key] #DataStructureModels::Tinkit::NodeKey


  @moab_datastore_name = MoabDatastoreName
  @version_key = VersionKey  #
  @model_key = @node_key #ModelKey
  
  #Change model key to persiste layer key ...
  #TODO: See about not making the filesystem dependent upon the node key
  @persist_layer_key = PersistLayerKey
  
  @namespace_key = NamespaceKey
  @metadata_keys = [@persist_layer_key, @version_key, @namespace_key ] #@persist_layer_key, @namespace_key] 
  @user_datastore_location = File.join(fs_path, @user_id, MoabDataStoreDir)    
  
  
  
  @model_save_params = {:nodes_save_path => @user_datastore_location, :data_file => @moab_datastore_name, :node_key => @node_key}
  @_files_mgr_class = FilesystemInterface::FilesMgr
  @views = TinkitFileSystemViews
  @moab_data = {:moab_datastore_name => @moab_datastore_name}
  #@views_mgr = ViewsMgr.new({:data_file => @data_file_name})
  
  FileUtils.mkdir_p(fs_path) unless File.exists?(fs_path)
end

Instance Attribute Details

#_files_mgr_classObject

TODO: Rather than using File class directly, should a special class be used?



149
150
151
# File 'lib/glue_envs/filesystem_glue_env.rb', line 149

def _files_mgr_class
  @_files_mgr_class
end

#metadata_keysObject

TODO: Rather than using File class directly, should a special class be used?



149
150
151
# File 'lib/glue_envs/filesystem_glue_env.rb', line 149

def 
  @metadata_keys
end

#moab_dataObject

TODO: Rather than using File class directly, should a special class be used?



149
150
151
# File 'lib/glue_envs/filesystem_glue_env.rb', line 149

def moab_data
  @moab_data
end

#moab_datastore_nameObject

TODO: Rather than using File class directly, should a special class be used?



149
150
151
# File 'lib/glue_envs/filesystem_glue_env.rb', line 149

def moab_datastore_name
  @moab_datastore_name
end

#model_keyObject

TODO: Rather than using File class directly, should a special class be used?



149
150
151
# File 'lib/glue_envs/filesystem_glue_env.rb', line 149

def model_key
  @model_key
end

#model_save_paramsObject

TODO: Rather than using File class directly, should a special class be used?



149
150
151
# File 'lib/glue_envs/filesystem_glue_env.rb', line 149

def model_save_params
  @model_save_params
end

#namespace_keyObject

TODO: Rather than using File class directly, should a special class be used?



149
150
151
# File 'lib/glue_envs/filesystem_glue_env.rb', line 149

def namespace_key
  @namespace_key
end

#node_keyObject

TODO: Rather than using File class directly, should a special class be used?



149
150
151
# File 'lib/glue_envs/filesystem_glue_env.rb', line 149

def node_key
  @node_key
end

#persist_layer_keyObject

TODO: Rather than using File class directly, should a special class be used?



149
150
151
# File 'lib/glue_envs/filesystem_glue_env.rb', line 149

def persist_layer_key
  @persist_layer_key
end

#required_instance_keysObject

TODO: Rather than using File class directly, should a special class be used?



149
150
151
# File 'lib/glue_envs/filesystem_glue_env.rb', line 149

def required_instance_keys
  @required_instance_keys
end

#required_save_keysObject

TODO: Rather than using File class directly, should a special class be used?



149
150
151
# File 'lib/glue_envs/filesystem_glue_env.rb', line 149

def required_save_keys
  @required_save_keys
end

#user_datastore_locationObject

TODO: Rather than using File class directly, should a special class be used?



149
150
151
# File 'lib/glue_envs/filesystem_glue_env.rb', line 149

def user_datastore_location
  @user_datastore_location
end

#user_idObject

TODO: Rather than using File class directly, should a special class be used?



149
150
151
# File 'lib/glue_envs/filesystem_glue_env.rb', line 149

def user_id
  @user_id
end

#version_keyObject

TODO: Rather than using File class directly, should a special class be used?



149
150
151
# File 'lib/glue_envs/filesystem_glue_env.rb', line 149

def version_key
  @version_key
end

#viewsObject

TODO: Rather than using File class directly, should a special class be used?



149
150
151
# File 'lib/glue_envs/filesystem_glue_env.rb', line 149

def views
  @views
end

Instance Method Details

#convert_node_value_to_file_value(node_key_value) ⇒ Object



389
390
391
392
# File 'lib/glue_envs/filesystem_glue_env.rb', line 389

def convert_node_value_to_file_value(node_key_value)
  file_base_value = node_key_value.to_s.gsub("::", "_")
  file_value = File.join(@user_datastore_location, file_base_value)
end

#destroy_bulk(list_of_native_records) ⇒ Object



377
378
379
380
381
382
383
384
385
386
387
# File 'lib/glue_envs/filesystem_glue_env.rb', line 377

def destroy_bulk(list_of_native_records)
  @@log.info {"Bulk Destroy: #{list_of_native_records.inspect}"} if @@log.info?
  return [] unless (list_of_native_records)
  list_of_native_records.each do |recs|
    next unless (recs && recs.size > 0)#raise "recs not hash: #{recs}" unless recs.class == Hash
    rec_id = recs[@persist_layer_key] || generate_model_key(nil, recs[@node_key])
    #rec_id = File.join(@user_datastore_location, rec_id) if File.dirname(rec_id) == "."
    #puts "Removing: #{r.inspect}"
    FileUtils.rm_rf(rec_id)
  end
end

#destroy_node(model_metadata) ⇒ Object



349
350
351
352
353
354
355
356
357
358
# File 'lib/glue_envs/filesystem_glue_env.rb', line 349

def destroy_node()
  #root_dir = @user_datastore_location
  #model_path(model_metadata[@model_key])
  node_id = [@persist_layer_key] || generate_model_key(nil, [@node_key])
  
  node_dir = node_id #File.join(root_dir, node_id)
  
  FileUtils.rm_rf(node_dir)
  #node = nil
end

#find_contains(key, this_value) ⇒ Object



264
265
266
267
268
269
270
271
# File 'lib/glue_envs/filesystem_glue_env.rb', line 264

def find_contains(key, this_value) 
  results =[]
  query_all.each do |record|
    test_val = record[key]
    results << record  if find_contains_type_helper(test_val, this_value)
  end
  results 
end

#find_contains_type_helper(stored_data, this_value) ⇒ Object



273
274
275
276
277
278
279
280
281
282
283
# File 'lib/glue_envs/filesystem_glue_env.rb', line 273

def find_contains_type_helper(stored_data, this_value)
  #p stored_dataj
  resp = nil
  #stored_data = jparse(stored_dataj)
  if stored_data.respond_to?(:"include?")
    resp = (stored_data.include?(this_value))
  else
    resp = (stored_data == this_value)
  end
  return resp
end

#find_equals(key, this_value) ⇒ Object



255
256
257
258
259
260
261
262
# File 'lib/glue_envs/filesystem_glue_env.rb', line 255

def find_equals(key, this_value) 
  results =[]
  query_all.each do |record|
    test_val = record[key]
    results << record  if test_val == this_value
  end
  results
end

#find_nodes_where(key, relation, this_value) ⇒ Object

  • :equals (data in the key field matches this_value)

  • :contains (this_value is contained in the key field data (same as equals for non-enumerable types )



245
246
247
248
249
250
251
252
253
# File 'lib/glue_envs/filesystem_glue_env.rb', line 245

def find_nodes_where(key, relation, this_value)
  res = case relation
    when :equals
      find_equals(key, this_value)
    when :contains
      find_contains(key, this_value)
  end #case
  return res    
end

#generate_model_key(namespace, node_key_value) ⇒ Object

namespace is used to distinguish between unique data sets (i.e., users) within the model



362
363
364
365
366
367
368
369
370
371
# File 'lib/glue_envs/filesystem_glue_env.rb', line 362

def generate_model_key(namespace, node_key_value)
  #was in FileSystemEnv mixin
  #fs_generate_model_key(namespace, node_key)
  #TODO: Make sure namespace is portable across model migrations
  file_name = convert_node_value_to_file_value(node_key_value)
  #TODO: Expand bad character set
  #FIXME namespace is redundant so removed it
  #"#{namespace}/#{node_key}"
  file_name
end

#get(id) ⇒ Object



285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
# File 'lib/glue_envs/filesystem_glue_env.rb', line 285

def get(id)
 return nil unless id
  #maybe put in some validations to ensure its from the proper collection namespace?
  #id may be the entry or the full path
  id_path = if id.include? (@user_datastore_location)
    id
  else
    convert_node_value_to_file_value(id)
  end
  #id_path = id #convert_node_value_to_file_value(id)
  data_file_path = File.join(id_path, @moab_datastore_name)
  rtn = if File.exists?(data_file_path)
    #data_file_path = File.join(id_path, @moab_datastore_name)
    json_data = File.open(data_file_path, 'r'){|f| f.read}
    node_data = JSON.parse(json_data)
    node_data = HashKeys.str_to_sym(node_data)
  else
    puts "Warning: File path doesn't exist: #{data_file_path.inspect}"
    []
  end
end

#model_path(model_key_value) ⇒ Object



373
374
375
# File 'lib/glue_envs/filesystem_glue_env.rb', line 373

def model_path(model_key_value)
  #model_key_value.gsub("::","/")
end

#query_allObject

TODO move to ViewsMgr



209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/glue_envs/filesystem_glue_env.rb', line 209

def query_all  #TODO move to ViewsMgr
  unless File.exists?(@user_datastore_location)
    @@log.debug {"Warning: Can't query records. The File System Directory to work from does not exist: #{@user_datastore_location}"} if @@log.debug?
  end
  all_records = []
  my_dir = @user_datastore_location + '/' #TODO: Can this be removed?
  all_entries = Dir.working_entries(my_dir) || []
  @@log.debug "querying directory: #{my_dir.inspect} and got entries: #{all_entries.inspect}"
  all_entries.each do|entry|
    all_records << get(entry) || {}
  end
  @@log.debug {"query_all returning: #{all_records.inspect}" } if @@log.debug?
  return all_records
end

#raw_allObject

TODO: reconcile raw_all with query_all, this is the only glue env using raw_all



225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/glue_envs/filesystem_glue_env.rb', line 225

def raw_all
  query_all
=begin  
  @@log.debug {"Getting All (Raw) Data using "\
                       "data loc: #{@user_datastore_location.inspect} "\
                       "datastore name: #{@moab_datastore_name.inspect}" } if @@log.debug?
  entries = query_all
  raw_nodes = []
  entries.each do |record|
    data_path = File.join(record[@persist_layer_key], @moab_datastore_name)
    data_json = File.open(data_path, 'r'){|f| f.read}
    data = JSON.parse(data_json)
    raw_nodes << data
  end
  raw_nodes
=end
end

#save(new_data) ⇒ Object



307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
# File 'lib/glue_envs/filesystem_glue_env.rb', line 307

def save(new_data)
  save_data = nil
  if new_data[@persist_layer_key]
    save_data = new_data
  elsif new_data[@node_key]
    persist_key_value = convert_node_value_to_file_value(new_data[@node_key])
    save_data = new_data.merge({@persist_layer_key => persist_key_value})
  else
    raise "Save Data did not include any keys for saving, data: #{new_data.inspect}"
  end
  save_path = @user_datastore_location
  save_location = save_data[@persist_layer_key]
  @@log.debug {"Save Directory: #{save_location.inspect}"} if @@log.debug?
  #was in FileSystemEnv mixin
  #fs_save(@model_save_params, model_data)
  #puts "FSG save udl: #{@user_datastore_location.inspect}"
    #parent_path = @user_datastore_location
    #node_key = @model_save_params[:node_key]
    #node_key = @node_key
    #puts "parent_path: #{parent_path.inspect}"
    #puts "new data node key: #{new_data[node_key].inspect}"
    #node_path = File.join(parent_path, new_data[node_key])
    file_name = File.basename(@moab_datastore_name)
    file_location = File.join(save_location, file_name) 
    
    #error_str = "Filesystem can't handle some characters in/
       #{file_location.inspect}"
    #raise error_str if new_data [node_key] =~ /::/ #FilesystemEnv::BADCHARS
    @@log.info {"File Location: #{file_location.inspect}"} if @@log.info?
    model_data = HashKeys.sym_to_str(save_data)
    
    FileUtils.mkdir_p(save_location) unless File.exist?(save_location)
    #raise "WTF?" unless File.exist?(save_location)
    rev = Time.now.hash #<- I would use File.mtime, but how to get the mod time before saving?
    model_data[@version_key] = rev
    f = File.open(file_location, 'w')
    f.write(model_data.to_json)
    f.close
    model_data['rev'] = model_data[@version_key] #TODO <-Investigate to see if it could be consistent
    return model_data
end