トップ «前の日記(2010-08-10) 最新 次の日記(2010-08-12)» 編集

ヨタの日々

2001|08|09|10|11|12|
2002|01|02|03|04|05|06|07|08|09|10|11|12|
2003|01|02|03|04|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|12|
2024|01|02|03|

2010-08-11 :-)

_ 朝ッ

1030 起床

_ [コードリーディング][Ruby][QuickML]QuickML を読む - config

QuickML の設定ファイルを管理するクラス。

/usr/local/sbin/quickml で QuickML::Config::load(config_file) としていたので、initialize() が最初に呼ばれるのではなく load が呼ばれる。

    def self.load (filename)
      self.new(eval(File.safe_open(filename).read))
    end

load() の中で new() している。どうして load() 経由で呼んでいるのかは分からない。誰か教えて。def self.ナントカ とするとクラスメソッドとして定義することになる。どうしてクラスメソッドにしておくのかというと、インスタンスを生成する手間を省きたいからじゃないでしょうか。たぶん

new() に渡している引数を見ていく。以下のような順番で処理される。

  1. File.safe_open(filename)
  2. それを read()
  3. それを eval()
  4. それを new() に渡す

File.safe_open() は lib/quickml/utils.rb の中で定義している。

class File
  def self.safe_open (filename, mode = "r")
    begin
      f = File.open(filename, mode)
      if block_given?
        yield(f)
        f.close
      else
        return f
      end
    rescue => e
      STDERR.printf "%s: %s\n", $0, e.message
      exit(1)
    end
  end
end

block_given? とはなんぞや

block_given?
メソッドにブロックが与えられている時には真、そうでない時に偽を返します。

つまり、以下のように呼ぶと block_given? は真

File.safe_open(hogehoge) {|f|
  何かの処理
}

以下のように呼ぶと block_given? は偽となる。

f = File.safe_open(hogehoge)

self.load では File.safe_open(filename) と、ブロックを渡していないので File.safe_open() では File オブジェクトが返る。

次に、その File オブジェクトの read() を呼ぶ。quickmlrc の全て読み込んでいる。

File.safe_open(filename).read

quickmlrc の内容はこう。Ruby のハッシュである。ここではまだハッシュオブジェクトではなく、たんなる文字列になっている。

# -*- mode: ruby -*-
Config = {
  :user => "quickml",
  :group => "quickml",
  :port => 10025,
  :bind_address => "0.0.0.0",

  :smtp_host => '127.0.0.1',
  :smtp_port => 25,
  :domain => 'qml.area51.gr.jp',
  :postmaster => "rin@maaya.jp",
  :info_url => "http://QuickML.com/",

  :data_dir => '/usr/local/var/quickml',
  :pid_file => '/var/run/quickml.pid',
  :log_file => '/var/log/quickml.log',

  :verbose_mode => true,
  :max_members => 100,
  :max_mail_length => 100 * 1024,
  :ml_life_time => 86400 * 31,
  :ml_alert_time => 86400 * 30,
  :auto_unsubscribe_count => 5,

  :sweep_interval => 3600,
  :max_threads => 10,
  :timeout => 120,
  :use_qmail_verp => false,

  :confirm_ml_creation => false, # for confirming ML creation. (experimental)

  # :message_catalog => nil  # for English messages
  :message_catalog => '/usr/local/share/messages.ja',
}

次に、ここで読み込んだ Config を eval() する。

eval(File.safe_open(filename).read))

eval() してようやく Config はハッシュオブジェクトとして生成されたことになる。

その Config を self.new() に渡す。

new() を呼ぶと initialize() が呼ばれるので initialize() を見てみる。長いので省略

    def initialize (config = {})
      @data_dir = config[:data_dir]
      @smtp_host = config[:smtp_host]
      @domain = config[:domain]

      raise ArgumentError if @data_dir.nil?
      raise ArgumentError if @smtp_host.nil?
      raise ArgumentError if @domain.nil?

      @pid_file = (config[:pid_file] or "/var/run/quickml.pid")
      @max_members = (config[:max_members] or 100)
      @max_mail_length = (config[:max_mail_length] or 100 * 1024) # 100KB
        :

見たとおりに config にあるキーから値を取得などしている。

(config[:pid_file] or "/var/run/quickml.pid") という処理は config[:pid_file] が nil ならば "/var/run/quickml.pid" を設定するということを意味している。つまり quickmlrc に pid_file が定義されていなければ "/var/run/quickml.pid" を使う。いわゆるデフォルト値になる。

initialize() の最後に注目。

      instance_variables.each {|name|
        self.class.class_eval { attr_reader name.delete('@') }
      }

instance_variables とはなんぞや

instance_variables
オブジェクトのインスタンス変数名を文字列の配列として返します。

obj = Object.new
obj.instance_eval { @foo, @bar = nil }
p obj.instance_variables

# => ["@foo", "@bar"]

これで

["@data_dir", "@smtp_host", "@domain" ...]

といった配列が返る。それを each する。

self.class.class_eval { attr_reader name.delete('@') } を 1 つずつ見ていく。

self.class はつまり自分自身のクラス。

class_eval とはなんぞや。これは結局 module_eval である。

module_eval とはなんぞや。

ブロックが与えられた場合にはそのブロックをモジュールのコンテキストで評価してその結果を返します。ブロックの引数 mod には self が渡されます。

モジュールのコンテキストで評価するとは、実行中そのモジュールが self になるということです。つまり、そのモジュールの定義文の中にあるかのように実行されます。

ええと、つまり @data_dir などに attr_reader 属性を付加していることになるらしい。へー

_ また処女か

「処女」かどうかと「乙女チック」「乙女心」「清純」などというものは別の問題なので、そこをゴチャゴチャすると話にならない。

前者はたんに肉体の問題であり、後者は精神、立ち居振る舞いの問題である。

処女厨が叩かれるのは「処女イコール清純」という前提になってるからであろうよ。

だと思うんだよね。

_ [QuickML][Ruby][コードリーディング]QuickML を読む - logger

ログを印字する処理。同期に対して注意している。

require 'quickml/utils'
require 'thread'

module QuickML
  class Logger
    def initialize (log_filename, verbose_mode = nil)
      @mutex = Mutex.new
      @log_file = File.safe_open(log_filename, "a")
      @log_file.sync = true
      @verbose_mode = verbose_mode
    end

log_file.sync は結局 IO の sync を設定している。

sync
現在の出力同期モードを真偽値で返します。同期モードが真の時は出力関数の呼出毎にバッファがフラッシュされます。

そのまま。

    private
    def puts_log (msg)
      @mutex.synchronize {
        time = Time.now.strftime("%Y-%m-%dT%H:%M:%S")
        @log_file.puts "#{time}: #{msg}"
      }
    end

    public
    def log (msg)
      puts_log(msg)
    end

    def vlog (msg)
      puts_log(msg) if @verbose_mode
    end

外部には log() と vlog() を公開しておき、結局各々 puts_log() を呼んでいる。puts_log() では RFC 3339 ぽい日付時間フォーマットに整形している(ref. RFC3339 インターネット上の日付と時間:タイムスタンプ )。( タイムオフセットが無いよね? )

    def reopen
      @mutex.synchronize {
        log_filename = @log_file.path
              @log_file.close
              @log_file = File.safe_open(log_filename, "a")
      }
    end

同期を気にしつつファイルを一度閉じて開いている。reopen() は HUP を貰ったときに実行される。

 trap(:HUP)  { config.logger.reopen }

_ ,

結局個体差なので「処女だから云々」というのはつまり主語が大きいんである。

_ 散歩

広角で遊ぶ

IMG_4971

_ 買い物

@紀伊国屋

ラノベ分が枯渇した

4044748187

4094511539

4086305577

4840131627

4840134049

4840124019

4840126003

4044740046

4044740054

4044740062

4044740070