<commit_before># frozen_string_literal: true

#
# Copyright (C) 2011 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.

module Canvas
  # defines the behavior when a protected attribute is assigned to in mass
  # assignment. The default, and Rails' normal behavior, is to just :log. Set
  # this to :raise to raise an exception.
  mattr_accessor :protected_attribute_error

  def self.active_record_foreign_key_check(name, type, options)
    if name.to_s =~ /_id\z/ && type.to_s == 'integer' && options[:limit].to_i < 8
      raise ArgumentError, <<-EOS
        All foreign keys need to be at least 8-byte integers. #{name}
        looks like a foreign key, please add this option: `:limit => 8`
      EOS
    end
  end

  def self.redis
    CanvasCache::Redis.redis
  end

  def self.redis_config
    CanvasCache::Redis.config
  end

  def self.redis_enabled?
    CanvasCache::Redis.enabled?
  end

  def self.reconnect_redis
    Canvas::Redis.reconnect_redis
  end

  def self.cache_store_config_for(cluster)
    yaml_config = ConfigFile.load("cache_store", cluster)
    consul_config = YAML.load(Canvas::DynamicSettings.find(tree: :private, cluster: cluster)["cache_store.yml"] || "{}") || {}
    consul_config = consul_config.with_indifferent_access if consul_config.is_a?(Hash)

    consul_config.presence || yaml_config
  end

  def self.lookup_cache_store(config, cluster)
    config = {'cache_store' => 'nil_store'}.merge(config)
    if config['cache_store'] == 'redis_store'
      ActiveSupport::Deprecation.warn("`redis_store` is no longer supported. Please change to `redis_cache_store`, and change `servers` to `url`.")
      config['cache_store'] = 'redis_cache_store'
      config['url'] = config['servers'] if config['servers']
    end

    case config.delete('cache_store')
    when 'redis_cache_store'
      Canvas::Redis.patch
      # if cache and redis data are configured identically, we want to share connections
      if config == {} && cluster == Rails.env && Canvas.redis_enabled?
        ActiveSupport::Cache.lookup_store(:redis_cache_store, redis: Canvas.redis)
      else
        # merge in redis.yml, but give precedence to cache_store.yml
        redis_config = (ConfigFile.load('redis', cluster) || {})
        config = redis_config.merge(config) if redis_config.is_a?(Hash)
        # config has to be a vanilla hash, with symbol keys, to auto-convert to kwargs
        ActiveSupport::Cache.lookup_store(:redis_cache_store, config.to_h.symbolize_keys)
      end
    when 'memory_store'
      ActiveSupport::Cache.lookup_store(:memory_store)
    when 'nil_store', 'null_store'
      ActiveSupport::Cache.lookup_store(:null_store)
    end
  end

  # `sample` reports KB, not B
  if File.directory?("/proc")
    # linux w/ proc fs
    LINUX_PAGE_SIZE = (size = `getconf PAGESIZE`.to_i; size > 0 ? size : 4096)
    def self.sample_memory
      s = File.read("/proc/#{Process.pid}/statm").to_i rescue 0
      s * LINUX_PAGE_SIZE / 1024
    end
  else
    # generic unix solution
    def self.sample_memory
      if Rails.env.test?
        0<commit_msg>fix MultiCache.cache when it's not specifically configured<commit_after># frozen_string_literal: true

#
# Copyright (C) 2011 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.

module Canvas
  # defines the behavior when a protected attribute is assigned to in mass
  # assignment. The default, and Rails' normal behavior, is to just :log. Set
  # this to :raise to raise an exception.
  mattr_accessor :protected_attribute_error

  def self.active_record_foreign_key_check(name, type, options)
    if name.to_s =~ /_id\z/ && type.to_s == 'integer' && options[:limit].to_i < 8
      raise ArgumentError, <<-EOS
        All foreign keys need to be at least 8-byte integers. #{name}
        looks like a foreign key, please add this option: `:limit => 8`
      EOS
    end
  end

  def self.redis
    CanvasCache::Redis.redis
  end

  def self.redis_config
    CanvasCache::Redis.config
  end

  def self.redis_enabled?
    CanvasCache::Redis.enabled?
  end

  def self.reconnect_redis
    Canvas::Redis.reconnect_redis
  end

  def self.cache_store_config_for(cluster)
    yaml_config = ConfigFile.load("cache_store", cluster)
    consul_config = YAML.load(Canvas::DynamicSettings.find(tree: :private, cluster: cluster)["cache_store.yml"] || "{}") || {}
    consul_config = consul_config.with_indifferent_access if consul_config.is_a?(Hash)

    consul_config.presence || yaml_config
  end

  def self.lookup_cache_store(config, cluster)
    config = {'cache_store' => 'nil_store'}.merge(config)
    if config['cache_store'] == 'redis_store'
      ActiveSupport::Deprecation.warn("`redis_store` is no longer supported. Please change to `redis_cache_store`, and change `servers` to `url`.")
      config['cache_store'] = 'redis_cache_store'
      config['url'] = config['servers'] if config['servers']
    end

    case config.delete('cache_store')
    when 'redis_cache_store'
      Canvas::Redis.patch
      # if cache and redis data are configured identically, we want to share connections
      if config.except('expires_in') == {} && cluster == Rails.env && Canvas.redis_enabled?
        ActiveSupport::Cache.lookup_store(:redis_cache_store, redis: Canvas.redis)
      else
        # merge in redis.yml, but give precedence to cache_store.yml
        redis_config = (ConfigFile.load('redis', cluster) || {})
        config = redis_config.merge(config) if redis_config.is_a?(Hash)
        # back compat
        config[:url] = config[:servers] if config[:servers]
        # config has to be a vanilla hash, with symbol keys, to auto-convert to kwargs
        ActiveSupport::Cache.lookup_store(:redis_cache_store, config.to_h.symbolize_keys)
      end
    when 'memory_store'
      ActiveSupport::Cache.lookup_store(:memory_store)
    when 'nil_store', 'null_store'
      ActiveSupport::Cache.lookup_store(:null_store)
    end
  end

  # `sample` reports KB, not B
  if File.directory?("/proc")
    # linux w/ proc fs
    LINUX_PAGE_SIZE = (size = `getconf PAGESIZE`.to_i; size > 0 ? size : 4096)
    def self.sample_memory
      s = File.read("/proc/#{Process.pid}/statm").to_i rescue 0
      s * LINUX_PAGE_SIZE / 1024
    end
  else
    # generic unix solution
    def self.sample_memory
      if Rails.env.test?
        0
{'fraction_non_alphanumeric': 0.09928134149587436, 'fraction_numerical': 0.005057226510513707, 'mean_word_length': 3.579524680073126, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '6762145', 'n_tokens_mistral': 2377, 'n_tokens_neox': 2287, 'n_words': 711}