<commit_before>module Netica
  require 'json'

  # provides a persistable object container for a Netica Bayes net.
  class ActiveNetwork
    class ActiveNetwork::NodeNotFound < RuntimeError; end
    class ActiveNetwork::NetworkNotFound < RuntimeError; end

    attr_accessor :network, :token, :created_at, :updated_at, :reloaded_at

    def initialize(token, filepath = nil)
      Netica::NeticaLogger.info "initializing active network for #{token}"
      self.created_at = Time.now
      self.updated_at = Time.now
      self.token = token
      if filepath
        self.network = BayesNetwork.new(filepath)
      end
      processor = Netica::Environment.instance
      processor.active_networks << self
    end

    def to_s
      token
    end

    # Increment a specified network node
    #
    # @param nodeName [String] name of the node to be incremented
    # @return [true,false,nil] outcome of the incr() attempt
    def incr_node(nodeName)
      Netica::NeticaLogger.info "Incrementing #{nodeName} for #{token}, object_id: #{self.object_id}."
      if network
        node = network.node(nodeName)
        if node
          self.updated_at = Time.now
          return node.incr()
        else
          raise ActiveNetwork::NodeNotFound, "Node #{nodeName} not found in network."
        end
      else
        raise ActiveNetwork::NetworkNotFound
      end
    end

    # Export the state of the ActiveNetwork as a Hash
    #
    # @return [Hash] network state and object class name
    def state
      {
        :network     => network.state,
        :class       => self.class.to_s,
        :created_at  => self.created_at,
        :updated_at  => self.updated_at,
        :reloaded_at => self.reloaded_at
      }
    end

    # Save ActiveNetwork to an associated redis store, if one is defined.
    #
    # @return [true,false,nil] outcome of redis.set, or nil if redis is not found
    def save
      if Netica::Environment.instance.redis
        return Netica::Environment.instance.redis.set(token, JSON.dump(state))
      end
    end

    # Retrieve ActiveNetwork from current Netica Environment instance
    # or an associated redis store, if one is defined.
    #
    # @param token [String] identifying token for ActiveNetwork sought
    # @return [ActiveNetwork] ActiveNetwork object found
    def self.find(token)
      environment = Netica::Environment.instance
      Netica::NeticaLogger.info "Searching in #{environment.network_container.class} #{environment.network_container.object_id} for #{token}."
      environment.network_container.each do |an|
        return an if an.token == token
      end
      Netica::NeticaLogger.info "Network #{token} not found in current instance #{environment.object_id}."
      if Netica::Environment.instance.redis
        stored_state = Netica::Environment.instance.redis.get(token)
        if stored_state
          hash = JSON.parse(stored_state)
          active_network = Object.const_get(hash['class']).new(token)
          active_network.load_from_saved_state(hash)
          Netica::NeticaLogger.info "Network #{token} reloaded from saved state: #{hash}"
          return active_network
        else<commit_msg>Lockable ActiveNetwork<commit_after>module Netica
  require 'json'

  # provides a persistable object container for a Netica Bayes net.
  class ActiveNetwork
    class ActiveNetwork::NodeNotFound < RuntimeError; end
    class ActiveNetwork::NetworkNotFound < RuntimeError; end

    attr_accessor :network, :token, :created_at, :updated_at, :reloaded_at, :in_use

    def initialize(token, filepath = nil)
      Netica::NeticaLogger.info "initializing active network for #{token}"
      self.created_at = Time.now
      self.updated_at = Time.now
      self.token = token
      if filepath
        self.network = BayesNetwork.new(filepath)
      end
      processor = Netica::Environment.instance
      processor.active_networks << self
    end

    def to_s
      token
    end

    # Increment a specified network node
    #
    # @param nodeName [String] name of the node to be incremented
    # @return [true,false,nil] outcome of the incr() attempt
    def incr_node(nodeName)
      Netica::NeticaLogger.info "Incrementing #{nodeName} for #{token}, object_id: #{self.object_id}."
      if network
        node = network.node(nodeName)
        if node
          self.updated_at = Time.now
          return node.incr()
        else
          raise ActiveNetwork::NodeNotFound, "Node #{nodeName} not found in network."
        end
      else
        raise ActiveNetwork::NetworkNotFound
      end
    end

    # Export the state of the ActiveNetwork as a Hash
    #
    # @return [Hash] network state and object class name
    def state
      {
        :network     => network.state,
        :class       => self.class.to_s,
        :created_at  => self.created_at,
        :updated_at  => self.updated_at,
        :reloaded_at => self.reloaded_at
      }
    end

    # Save ActiveNetwork to an associated redis store, if one is defined.
    #
    # @return [true,false,nil] outcome of redis.set, or nil if redis is not found
    def save
      if Netica::Environment.instance.redis
        return Netica::Environment.instance.redis.set(token, JSON.dump(state))
      end
    end

    # Retrieve ActiveNetwork from current Netica Environment instance
    # or an associated redis store, if one is defined.
    #
    # @param token [String] identifying token for ActiveNetwork sought
    # @return [ActiveNetwork] ActiveNetwork object found
    def self.find(token)
      environment = Netica::Environment.instance
      Netica::NeticaLogger.info "Searching in #{environment.network_container.class} #{environment.network_container.object_id} (length: #{environment.network_container.length}) for #{token}."
      environment.network_container.each do |an|
        if an.token == token
          until !an.in_use
            Netica::NeticaLogger.info "Network #{token} is locked."
            wait 1000
          end
          return an
        end
      end
      Netica::NeticaLogger.info "Network #{token} not found in current instance #{environment.object_id}."
      if Netica::Environment.instance.redis
        stored_state = Netica::Environment.instance.redis.get(token)
        if stored_state
          hash = JSON.parse(stored_state)
          active_network = Object.const_get(hash['class']).new(token)
          active_network.load_from_saved_state(hash)
          Netica::NeticaLogger.info "Network #{token} reloaded from saved state: #{hash}"
          return active_network
        else
{'fraction_non_alphanumeric': 0.08580106302201974, 'fraction_numerical': 0.0006074411541381929, 'mean_word_length': 2.7272212790039614, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2617834', 'n_tokens_mistral': 1842, 'n_tokens_neox': 1819, 'n_words': 530}