<commit_before>require 'tree'

class ServiceManager

  attr_accessor :last_error
  def initialize
    if File.exists?(SysConfig.ServiceTreeFile)
      @service_tree = tree_from_yaml()
    else
      @service_tree = Tree::TreeNode.new("Service Manager", "Managed Services and Engines")
      @service_tree << Tree::TreeNode.new("ManagedEngine","Engines")
      @service_tree << Tree::TreeNode.new("Services","Managed Services")
    end
    rescue Exception=>e
        puts e.message 
        log_exception(e)
        
  end

  def get_software_service_container_name(params)
   server_service =  software_service_definition(params)
   if server_service == nil || server_service == false
     p :no_luck_getint_service_container_for
     p params
     return nil
   end
    return server_service[:service_container]
    
  end
  def list_providers_in_use
     providers =  managed_service_tree.children
     if providers == nil
       return false
      end
     retval=Array.new
     providers.each do |provider|
       retval.push(provider.name)
     end 
     return retval
  end
  
  def managed_service_tree 
    return @service_tree["Services"]
  end
  
  def get_service_provider_tree(publisher)
    managed_service_tree[publisher]
  end
  
  
  
  def find_service_consumers(service_hash)
      
      if service_hash.has_key?(:publisher_namespace) == false || service_hash[:publisher_namespace]  == nil
       p :no_publisher_namespace
        return false
      end
      
    provider_tree = get_service_provider_tree(service_hash[:publisher_namespace])
     
      if service_hash.has_key?(:type_path) == false  || service_hash[:service_type] == nil
        return provider_tree
      end
            
      service_path_tree = provider_tree[service_hash[:type_path]]
     
      if service_path_tree == nil
        return false
      end
            
      if service_hash.has_key?(:name) == false || service_hash[:name]  == nil
        return  service_path_tree
      end
      
     if  service_path_tree[service_hash[:name]] == nil
       return false
      end

      return service_path_tree[service_hash[:name]]
      
  end
    
#  def attached_services(object)
#
#  end
#
#  def load_system_services
#
#  end
#
#  def deregister_available_service service_info_hash
#
#  end
#
#  def register_available_service service_info_hash
#
#  end

  def list_attached_services_for(objectName,identifier)
    p :services_on_objects_4
    p objectName
    p identifier

    case objectName
    when "ManagedEngine"
      return attached_managed_engine_services(identifier)
    when "Volume"
      return attached_volume_services(identifier)
    when "Database"
      return attached_database_services(identifier)
    end
    p :no_object_name_match
    p objectName
    rescue Exception=>e
        puts e.message 
        log_exception(e)
        
  end

  def attached_volume_services (identifier)
    retval=Hash.new
    return retval
  end
  
  def attached_database_services (identifier)
    retval=Hash.new
    return retval
  end
  
  def attached_managed_engine_services(identifier)

    retval = Hash.new

    if identifier == nil
      p :panic_passed_nil_identifier
      return retval
    end
   
    engines_node =  @service_tree["ManagedEngine"]
    if  engines_node ==nil
      p :panic_loaded_managedengine_tree
      return retval
    end

    engine_node =engines_node[identifier]

    if engine_node == nil
      p :cant_find
      p identifier
      return retval
    end
   engine_node.children.each do |service_node|      
      p :service_type
      p service_node.name
      if  service_node.name == nil
        p :no_service_type
        return retval
      end
      if retval.has_key?( service_node.name) == false
        retval[ service_node.name] = Array.new
      end
      retval[ service_node.name].push(get_service_content(service_node))
    end
#    p :retval
#    p retval
    return retval
 
rescue Exception=>e
    puts e.message 
    log_exception(e)
    
  end
  
  def get_service_content(service_node)
    retval = Hash.new
    service_node.children.each do |provider_node|
#      p :provider_node_name
#      p provider_node.name
      retval[provider_node.name] = Array.new
          provider_node.children.each do |service_node|
#            p :service_node_name
#            p service_node.name
            retval[provider_node.name].push(service_node.content)
          end       
    end
    return retval
  end
  
  def attached_services(service_type,identifier)
    retval = Array.new
    if @service_tree["ManagedService"] ==nil
      p :panic_no_managed_service_node
      return retval
    end
    services = @service_tree["ManagedService"][service_type]
    if services == nil
      return retval
    end
    service = services[identifier]
    if service == nil
      return  retval
    end
    service.each do |node|
      retval.push(node.content)
#      p node
    end
    
rescue Exception=>e
    puts e.message 
    log_exception(e)
    
  end

  #hash has parent_engine
  #hash parent
  def add_service service_hash
    #@service_tree.print_tree
    if(@service_tree == nil)
      p :panic_loaded_nil_tree
      return false
    end
 
      add_to_managed_services_tree(service_hash)
      add_to_services_tree(service_hash) 
      save_tree
  rescue Exception=>e
      puts e.message 
      log_exception(e)
      
  end
  
  def add_to_managed_services_tree(service_hash)
    #write managed engine tree
    active_engines_node = @service_tree["ManagedEngine"]

    if (active_engines_node == nil )
      p :nil_active_node
      return false
    end

    if service_hash.has_key?(:parent_engine) == false && service_hash[:parent_engine] != nil
      p :no_parent_engine_key
      return false
    end
    if active_engines_node[service_hash[:parent_engine] ] != nil
      engine_node = active_engines_node[ service_hash[:parent_engine] ]
    else
      engine_node = Tree::TreeNode.new(service_hash[:parent_engine],service_hash[:parent_engine] + " Engine Service Tree")
      active_engines_node << engine_node
    end

    service_type_node = engine_node[service_hash[:type_path]]
      
     if service_type_node == nil
      service_type_node = Tree::TreeNode.new(service_hash[:type_path], service_hash[:service_type] + " Service")
       engine_node << service_type_node       
    end
    
    
    service_label = get_service_label(service_hash)
if service_label == nil
  p service_hash
  p :error_service_hash_has_nil_name
  return false
end

    service_node = Tree::TreeNode.new(service_label,service_hash)
     service_type_node << service_node
    
#    provider = service_hash[:publisher_namespace]
#     if provider == nil || provider.length ==0
#       provider="Engines"
#     end
#     
#    service_provider_node = service_type_node[provider]
#    if service_provider_node == nil
#      service_provider_node = Tree::TreeNode.new(provider,service_hash[:type_path] + " Provider:"+ provider)
#      service_type_node << service_provider_node
#    end
#   # p :service_name
##    p service_hash[:name]
    
#    service_label = get_service_label(service_hash)
#   
#      
#      if service_label == nil
#        p service_hash
#        p :error_service_hash_has_nil_name
#        return false
#      end
#    if service_provider_node[service_label] != nil
#      #FixME need to explain why
#      return false
#    else
#      service_node = Tree::TreeNode.new(service_label,service_hash)
#      service_type_node << service_node
#    end

end
    
def get_service_label(params)
  if params.has_key?(:name) && params[:name] != nil
       service_label = params[:name]
     elsif  params.has_key?(:variables) && params[:variables].has_key?(:name)
       service_label = params[:variables][:name]
     else
       return nil
     end
end

 #write services tree
   def add_to_services_tree(service_hash)
   
     services_node = @service_tree["Services"]
   

       provider_node = services_node[service_hash[:publisher_namespace] ]
        if provider_node == nil
          provider_node = Tree::TreeNode.new(service_hash[:publisher_namespace] ," Provider:" + service_hash[:publisher_namespace] + ":" + service_hash[:type_path]  )
          services_node << provider_node
        end
        
        servicetype_node =  provider_node[service_hash[:type_path] ]
          if servicetype_node == nil
            servicetype_node =  Tree::TreeNode.new(service_hash[:type_path],service_hash[:type_path])
            provider_node << servicetype_node
          end
          
          service_node = servicetype_node[service_hash[:parent_engine]]
            if service_node == nil
              service_node = Tree::TreeNode.new(service_hash[:parent_engine],service_hash)
              servicetype_node << service_node
            end
    #FIXME need to handle updating service 
            
rescue Exception=>e
    puts e.message 
    log_exception(e)
    
  end

  def find_engine_services(params)
    engine_node = @service_tree["ManagedEngine"][params[:engine_name]]
      if params.has_key?(:type_path) && params[:type_path] != nil
        services = engine_node[params[:type_path]]
          if params.has_key?(:publisher_namespace) && params[:publisher_namespace] != nil
            providers = engine_node[params[:publisher_namespace]]              
              if params.has_key?(:name) && params[:name] != nil
                 services = providers[params[:name]]
                return services
              else
            return providers
          end
       end
      else
        return engine_node
      end
  end

  
  
  def remove_service service_hash
   
      parent_engine_node = @service_tree["ManagedEngine"][service_hash[:parent_engine]]
        if parent_engine_node == nil
          @last_error ="No service record found for "+ service_hash[:parent_engine] 
          return false
        end
      service_type_node = parent_engine_node[service_hash[:type_path]]
        if service_type_node == nil
          @last_error ="No service record found for " + service_hash[:parent_engine] + ":" +  service_hash[:service_type]
          return false
        end
       service_provider_node =  service_type_node[service_hash[:publisher_namespace]]
       if service_provider_node == nil
          @last_error ="No service record found for " + service_hash[:parent_engine] + " type_path:" +  service_hash[:type_path] + " Provider " + service_hash[:publisher_namespace] 
          return false
        end
        service_name = get_service_label(service_hash)
        if service_name  == nil
          p service_hash
          p :notfound
        end 
        service_node = service_provider_node[service_name]
        #deal with new way variables are pass 
      

#          p :really_removing
#          p service_node
#         p :from
         # p service_provider_node
          #FIXME a method should do this in a loop
          
          if service_node != nil
            service_provider_node.remove!(service_node)
            if service_provider_node.children.count ==0
              service_type_node.remove!(service_provider_node)              
                if service_type_node.children.count ==0
                  parent_engine_node.remove!(service_type_node)
                    if parent_engine_node.children.count == 0
                      @service_tree["ManagedEngine"].remove!(parent_engine_node)
                    end
                end
            end

            
      services_node = @service_tree["Services"]
      if services_node !=nil
        provider_node = services_node[service_hash[:publisher_namespace] ]
        if provider_node != nil
          servicetype_node =  provider_node[service_hash[:type_path] ]
          if servicetype_node != nil
            service_node = servicetype_node[service_hash[:parent_engine]]
            if service_node != nil
              servicetype_node.remove!(service_node)
              if servicetype_node.children.count == 0
                provider_node.remove!(service_node)
                if provider_node.children.count == 0
                  service_node.remove!(provider_node)
                end
              end
            end                          
          end
        end
      end
            
            
            sucess =  true
          end         
          
          if sucess == true
            save_tree
            return true
          end
          
@last_error ="No service record found for " + service_hash[:variables][:parent_engine].to_s
@last_error += " service_type:" +  service_hash[:type_path].to_s 
@last_error  += " Provider " + service_hash[:publisher_namespace].to_s 
@last_error += " Name " + service_hash[:variables][:name].to_s
        return false 

rescue Exception=>e
  if service_hash != nil
    p service_hash
  end
  log_exception(e)    
  end

def software_service_definition(params)
  require 'json'
  
  if params[:publisher_namespace]   == nil ||  params[:type_path] == nil
    p :nil_in_params
    p params
    return nil
  end
  
  service_filename = SysConfig.ServiceTemplateDir + "/" + params[:publisher_namespace] + "/" + params[:service_type]+ ".yaml"
  if File.exists?(service_filename)
    yaml = File.read(service_filename)
    software_service_def  = SoftwareServiceDefinition.from_yaml(yaml)
    return software_service_def.to_h
  else
    p :no_file_named
    p  service_filename 
    return nil
  end

    
rescue Exception=>e
  p :error
  p params
  p service_filename
log_exception(e)
  return nil
end  


  
  
  def tree_from_yaml()
    begin
      tree_data = File.read(SysConfig.ServiceTreeFile)
      service_tree =   YAML::load(tree_data)
      return service_tree
    rescue Exception=>e
      puts e.message + " with " + tree_data.to_s
      log_exception(e)
    end
  end

  def save_tree
  #  serialized_object = Marshal.dump(@service_tree)
    serialized_object = YAML::dump(@service_tree)
    f = File.new(SysConfig.ServiceTreeFile,File::CREAT|File::TRUNC|File::RDWR, 0644)
    f.puts(serialized_object)
    f.close
    return true
  rescue Exception=>e
    @last_error=( "load error")
    log_exception(e)
    return false
  end

  def log_exception(e)
    e_str = e.to_s()
    e.backtrace.each do |bt |
      e_str += bt
    end
    @last_error = e_str
    SystemUtils.log_output(e_str,10)
  end
end<commit_msg>handle case when node alread registered<commit_after>require 'tree'

class ServiceManager

  attr_accessor :last_error
  def initialize
    if File.exists?(SysConfig.ServiceTreeFile)
      @service_tree = tree_from_yaml()
    else
      @service_tree = Tree::TreeNode.new("Service Manager", "Managed Services and Engines")
      @service_tree << Tree::TreeNode.new("ManagedEngine","Engines")
      @service_tree << Tree::TreeNode.new("Services","Managed Services")
    end
    rescue Exception=>e
        puts e.message 
        log_exception(e)
        
  end

  def get_software_service_container_name(params)
   server_service =  software_service_definition(params)
   if server_service == nil || server_service == false
     p :no_luck_getint_service_container_for
     p params
     return nil
   end
    return server_service[:service_container]
    
  end
  def list_providers_in_use
     providers =  managed_service_tree.children
     if providers == nil
       return false
      end
     retval=Array.new
     providers.each do |provider|
       retval.push(provider.name)
     end 
     return retval
  end
  
  def managed_service_tree 
    return @service_tree["Services"]
  end
  
  def get_service_provider_tree(publisher)
    managed_service_tree[publisher]
  end
  
  
  
  def find_service_consumers(service_hash)
      
      if service_hash.has_key?(:publisher_namespace) == false || service_hash[:publisher_namespace]  == nil
       p :no_publisher_namespace
        return false
      end
      
    provider_tree = get_service_provider_tree(service_hash[:publisher_namespace])
     
      if service_hash.has_key?(:type_path) == false  || service_hash[:service_type] == nil
        return provider_tree
      end
            
      service_path_tree = provider_tree[service_hash[:type_path]]
     
      if service_path_tree == nil
        return false
      end
            
      if service_hash.has_key?(:name) == false || service_hash[:name]  == nil
        return  service_path_tree
      end
      
     if  service_path_tree[service_hash[:name]] == nil
       return false
      end

      return service_path_tree[service_hash[:name]]
      
  end
    
#  def attached_services(object)
#
#  end
#
#  def load_system_services
#
#  end
#
#  def deregister_available_service service_info_hash
#
#  end
#
#  def register_available_service service_info_hash
#
#  end

  def list_attached_services_for(objectName,identifier)
    p :services_on_objects_4
    p objectName
    p identifier

    case objectName
    when "ManagedEngine"
      return attached_managed_engine_services(identifier)
    when "Volume"
      return attached_volume_services(identifier)
    when "Database"
      return attached_database_services(identifier)
    end
    p :no_object_name_match
    p objectName
    rescue Exception=>e
        puts e.message 
        log_exception(e)
        
  end

  def attached_volume_services (identifier)
    retval=Hash.new
    return retval
  end
  
  def attached_database_services (identifier)
    retval=Hash.new
    return retval
  end
  
  def attached_managed_engine_services(identifier)

    retval = Hash.new

    if identifier == nil
      p :panic_passed_nil_identifier
      return retval
    end
   
    engines_node =  @service_tree["ManagedEngine"]
    if  engines_node ==nil
      p :panic_loaded_managedengine_tree
      return retval
    end

    engine_node =engines_node[identifier]

    if engine_node == nil
      p :cant_find
      p identifier
      return retval
    end
   engine_node.children.each do |service_node|      
      p :service_type
      p service_node.name
      if  service_node.name == nil
        p :no_service_type
        return retval
      end
      if retval.has_key?( service_node.name) == false
        retval[ service_node.name] = Array.new
      end
      retval[ service_node.name].push(get_service_content(service_node))
    end
#    p :retval
#    p retval
    return retval
 
rescue Exception=>e
    puts e.message 
    log_exception(e)
    
  end
  
  def get_service_content(service_node)
    retval = Hash.new
    service_node.children.each do |provider_node|
#      p :provider_node_name
#      p provider_node.name
      retval[provider_node.name] = Array.new
          provider_node.children.each do |service_node|
#            p :service_node_name
#            p service_node.name
            retval[provider_node.name].push(service_node.content)
          end       
    end
    return retval
  end
  
  def attached_services(service_type,identifier)
    retval = Array.new
    if @service_tree["ManagedService"] ==nil
      p :panic_no_managed_service_node
      return retval
    end
    services = @service_tree["ManagedService"][service_type]
    if services == nil
      return retval
    end
    service = services[identifier]
    if service == nil
      return  retval
    end
    service.each do |node|
      retval.push(node.content)
#      p node
    end
    
rescue Exception=>e
    puts e.message 
    log_exception(e)
    
  end

  #hash has parent_engine
  #hash parent
  def add_service service_hash
    #<EMAIL>
    if(@service_tree == nil)
      p :panic_loaded_nil_tree
      return false
    end
 
      add_to_managed_services_tree(service_hash)
      add_to_services_tree(service_hash) 
      save_tree
  rescue Exception=>e
      puts e.message 
      log_exception(e)
      
  end
  
  def add_to_managed_services_tree(service_hash)
    #write managed engine tree
    active_engines_node = @service_tree["ManagedEngine"]

    if (active_engines_node == nil )
      p :nil_active_node
      return false
    end

    if service_hash.has_key?(:parent_engine) == false && service_hash[:parent_engine] != nil
      p :no_parent_engine_key
      return false
    end
    if active_engines_node[service_hash[:parent_engine] ] != nil
      engine_node = active_engines_node[ service_hash[:parent_engine] ]
    else
      engine_node = Tree::TreeNode.new(service_hash[:parent_engine],service_hash[:parent_engine] + " Engine Service Tree")
      active_engines_node << engine_node
    end

    service_type_node = engine_node[service_hash[:type_path]]
      
     if service_type_node == nil
      service_type_node = Tree::TreeNode.new(service_hash[:type_path], service_hash[:service_type] + " Service")
       engine_node << service_type_node       
    end
    
    
    service_label = get_service_label(service_hash)
    
if service_label == nil
  p service_hash
  p :error_service_hash_has_nil_name
  return false
end

    service_node = service_type_node[service_label]
    if  service_node == nil
      service_node = Tree::TreeNode.new(service_label,service_hash)
      service_type_node << service_node
    else
      p :Node_existed
      p service_label
    end
    
    
#    provider = service_hash[:publisher_namespace]
#     if provider == nil || provider.length ==0
#       provider="Engines"
#     end
#     
#    service_provider_node = service_type_node[provider]
#    if service_provider_node == nil
#      service_provider_node = Tree::TreeNode.new(provider,service_hash[:type_path] + " Provider:"+ provider)
#      service_type_node << service_provider_node
#    end
#   # p :service_name
##    p service_hash[:name]
    
#    service_label = get_service_label(service_hash)
#   
#      
#      if service_label == nil
#        p service_hash
#        p :error_service_hash_has_nil_name
#        return false
#      end
#    if service_provider_node[service_label] != nil
#      #FixME need to explain why
#      return false
#    else
#      service_node = Tree::TreeNode.new(service_label,service_hash)
#      service_type_node << service_node
#    end

end
    
def get_service_label(params)
  if params.has_key?(:name) && params[:name] != nil
       service_label = params[:name]
     elsif  params.has_key?(:variables) && params[:variables].has_key?(:name)
       service_label = params[:variables][:name]
     else
       return nil
     end
end

 #write services tree
   def add_to_services_tree(service_hash)
   
     services_node = @service_tree["Services"]
   

       provider_node = services_node[service_hash[:publisher_namespace] ]
        if provider_node == nil
          provider_node = Tree::TreeNode.new(service_hash[:publisher_namespace] ," Provider:" + service_hash[:publisher_namespace] + ":" + service_hash[:type_path]  )
          services_node << provider_node
        end
        
        servicetype_node =  provider_node[service_hash[:type_path] ]
          if servicetype_node == nil
            servicetype_node =  Tree::TreeNode.new(service_hash[:type_path],service_hash[:type_path])
            provider_node << servicetype_node
          end
          
          service_node = servicetype_node[service_hash[:parent_engine]]
            if service_node == nil
              service_node = Tree::TreeNode.new(service_hash[:parent_engine],service_hash)
              servicetype_node << service_node
            end
    #FIXME need to handle updating service 
            
rescue Exception=>e
    puts e.message 
    log_exception(e)
    
  end

  def find_engine_services(params)
    engine_node = @service_tree["ManagedEngine"][params[:engine_name]]
      if params.has_key?(:type_path) && params[:type_path] != nil
        services = engine_node[params[:type_path]]
          if params.has_key?(:publisher_namespace) && params[:publisher_namespace] != nil
            providers = engine_node[params[:publisher_namespace]]              
              if params.has_key?(:name) && params[:name] != nil
                 services = providers[params[:name]]
                return services
              else
            return providers
          end
       end
      else
        return engine_node
      end
  end

  
  
  def remove_service service_hash
   
      parent_engine_node = @service_tree["ManagedEngine"][service_hash[:parent_engine]]
        if parent_engine_node == nil
          @last_error ="No service record found for "+ service_hash[:parent_engine] 
          return false
        end
      service_type_node = parent_engine_node[service_hash[:type_path]]
        if service_type_node == nil
          @last_error ="No service record found for " + service_hash[:parent_engine] + ":" +  service_hash[:service_type]
          return false
        end
       service_provider_node =  service_type_node[service_hash[:publisher_namespace]]
       if service_provider_node == nil
          @last_error ="No service record found for " + service_hash[:parent_engine] + " type_path:" +  service_hash[:type_path] + " Provider " + service_hash[:publisher_namespace] 
          return false
        end
        service_name = get_service_label(service_hash)
        if service_name  == nil
          p service_hash
          p :notfound
        end 
        service_node = service_provider_node[service_name]
        #deal with new way variables are pass 
      

#          p :really_removing
#          p service_node
#         p :from
         # p service_provider_node
          #FIXME a method should do this in a loop
          
          if service_node != nil
            service_provider_node.remove!(service_node)
            if service_provider_node.children.count ==0
              service_type_node.remove!(service_provider_node)              
                if service_type_node.children.count ==0
                  parent_engine_node.remove!(service_type_node)
                    if parent_engine_node.children.count == 0
                      @service_tree["ManagedEngine"].remove!(parent_engine_node)
                    end
                end
            end

            
      services_node = @service_tree["Services"]
      if services_node !=nil
        provider_node = services_node[service_hash[:publisher_namespace] ]
        if provider_node != nil
          servicetype_node =  provider_node[service_hash[:type_path] ]
          if servicetype_node != nil
            service_node = servicetype_node[service_hash[:parent_engine]]
            if service_node != nil
              servicetype_node.remove!(service_node)
              if servicetype_node.children.count == 0
                provider_node.remove!(service_node)
                if provider_node.children.count == 0
                  service_node.remove!(provider_node)
                end
              end
            end                          
          end
        end
      end
            
            
            sucess =  true
          end         
          
          if sucess == true
            save_tree
            return true
          end
          
@last_error ="No service record found for " + service_hash[:variables][:parent_engine].to_s
@last_error += " service_type:" +  service_hash[:type_path].to_s 
@last_error  += " Provider " + service_hash[:publisher_namespace].to_s 
@last_error += " Name " + service_hash[:variables][:name].to_s
        return false 

rescue Exception=>e
  if service_hash != nil
    p service_hash
  end
  log_exception(e)    
  end

def software_service_definition(params)
  require 'json'
  
  if params[:publisher_namespace]   == nil ||  params[:type_path] == nil
    p :nil_in_params
    p params
    return nil
  end
  
  service_filename = SysConfig.ServiceTemplateDir + "/" + params[:publisher_namespace] + "/" + params[:service_type]+ ".yaml"
  if File.exists?(service_filename)
    yaml = File.read(service_filename)
    software_service_def  = SoftwareServiceDefinition.from_yaml(yaml)
    return software_service_def.to_h
  else
    p :no_file_named
    p  service_filename 
    return nil
  end

    
rescue Exception=>e
  p :error
  p params
  p service_filename
log_exception(e)
  return nil
end  


  
  
  def tree_from_yaml()
    begin
      tree_data = File.read(SysConfig.ServiceTreeFile)
      service_tree =   YAML::load(tree_data)
      return service_tree
    rescue Exception=>e
      puts e.message + " with " + tree_data.to_s
      log_exception(e)
    end
  end

  def save_tree
  #  serialized_object = Marshal.dump(@service_tree)
    serialized_object = YAML::dump(@service_tree)
    f = File.new(SysConfig.ServiceTreeFile,File::CREAT|File::TRUNC|File::RDWR, 0644)
    f.puts(serialized_object)
    f.close
    return true
  rescue Exception=>e
    @last_error=( "load error")
    log_exception(e)
    return false
  end

  def log_exception(e)
    e_str = e.to_s()
    e.backtrace.each do |bt |
      e_str += bt
    end
    @last_error = e_str
    SystemUtils.log_output(e_str,10)
  end
end
{'fraction_non_alphanumeric': 0.07832428882513567, 'fraction_numerical': 0.0008986899865196502, 'mean_word_length': 2.5569215638062452, 'pattern_counts': {'":': 4, '<': 44, '<?xml version=': 0, '>': 24, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1203279', 'n_tokens_mistral': 8660, 'n_tokens_neox': 8541, 'n_words': 1741}