#!/usr/bin/env ruby # -*- coding: utf-8 -*- require 'digest/md5' require 'fileutils' require 'rack' require 'uri' require File.expand_path(File.dirname(__FILE__) + "/../lib/sekkaconfig") require File.expand_path(File.dirname(__FILE__) + "/../lib/sekka/sekkaversion") DICTDIR = File.expand_path( "~/.sekka-server" ) DICTURL = "http://sumibi.org/sekka/dict/" + SekkaVersion.version PIDFILE = DICTDIR + "/pid" TC_FILE = DICTDIR + "/SEKKA-JISYO.SMALL.tch" TSVFILE = DICTDIR + "/SEKKA-JISYO.SMALL.tsv" SUMFILE = DICTDIR + "/SEKKA-JISYO.SMALL.md5" TSVURL = DICTURL + "/SEKKA-JISYO.SMALL.tsv" SUMURL = DICTURL + "/SEKKA-JISYO.SMALL.md5" TC_FILE_LIST = [ DICTDIR + "/SEKKA-JISYO.CUSTOM.tch", DICTDIR + "/SEKKA-JISYO.LARGE.tch", DICTDIR + "/SEKKA-JISYO.SMALL.tch" ] MEMCACHED = "localhost:11211" # memcahced def getSekkaDbInfo( env ) if env.has_key?( 'SEKKA_DB' ) m = env['SEKKA_DB'].match( /^redis:(.*)$/ ) if m dictSource = if 0 == m[1].size dictSource = "localhost" else dictSource = m[1] end [ :redis, dictSource ] elsif m = ENV['SEKKA_DB'].match( /^tokyo[a-z]+$/ ) [ :tokyocabinet, nil ] else raise RuntimeError, "Error: env var SEKKA_DB requires [redis:hostname] or [redis:] or [tokyocabinet]" end else [ :tokyocabinet, nil ] end end def main if not File.directory?( DICTDIR ) Dir.mkdir( DICTDIR ) STDERR.printf( "Info: created directory [%s]\n", DICTDIR ) end # sekka-server自身のpidを書きこむ(デーモン化したときの停止用) open( PIDFILE, "w" ) {|f| f.printf( "%d\n", Process.pid ) } # 環境変数からHTTPプロキシサーバーの情報を取得する proxyHost = nil proxyPort = nil if ENV.key?( 'http_proxy' ) uri = URI.parse ENV[ 'http_proxy' ] proxyPort = uri.port proxyHost = uri.host end if not File.exist?( TSVFILE ) STDERR.printf( "Info: Downloading SEKKA-JISYO\n" ) # 辞書をダウンロードする cmd = sprintf( "curl -o %s %s", TSVFILE, TSVURL ) STDERR.printf( "Command : %s\n", cmd ) system( cmd ) cmd = sprintf( "curl -o %s %s", SUMFILE, SUMURL ) STDERR.printf( "Command : %s\n", cmd ) system( cmd ) # チェックサムを確認する downloadSum = "" open( TSVFILE ) { |f| dataBody = f.read downloadSum = Digest::MD5.hexdigest( dataBody ) } open( SUMFILE ) { |f| correctSum = f.readline.chomp.split[0] STDERR.printf( " downloaded file's MD5 : %s\n", downloadSum ) STDERR.printf( " correct MD5 : %s\n", correctSum ) if downloadSum == correctSum STDERR.printf( "Info: downloaded file [%s] verify OK.\n", TSVFILE ) else STDERR.printf( "Error: downloaded file [%s] verify NG.\n", TSVFILE ) File.unlink( TSVFILE ) exit( 1 ) end } end # 環境変数から、DBの接続先情報を取得する。 ( dictType, dictSource ) = getSekkaDbInfo( ENV ) case dictType when :tokyocabinet # .tchファイルが存在すうるか調べる list = TC_FILE_LIST.select { |name| File.exist?( name ) } if 0 == list.size # tsvファイルをTokyo CabinetのHashDB化する STDERR.printf( "Info: Converting TSV file to Tokyo Cabinet *.tch\n" ) cmd = sprintf( "tchmgr importtsv %s %s", TC_FILE, TSVFILE ) STDERR.printf( "Command : %s\n", cmd ) system( cmd ) # 中身を確認する(tchmgrで読めるものができている) STDERR.printf( "Info: inform *.tch\n" ) cmd = sprintf( "tchmgr inform %s", TC_FILE ) STDERR.printf( "Command : %s\n", cmd ) system( cmd ) end # 存在する.tchファイルの中で一番最初のファイルを使う。 list = TC_FILE_LIST.select { |name| File.exist?( name ) } dictSource = list[0] when :redis key = "SEKKA::VERSION" # redisサーバーに辞書が投入済みか確認する STDERR.printf( "Info: Checking SEKKA jisyo on redis server...\n" ) require 'redis' require 'sekka/kvs' redis = Kvs.new( :redis ) begin redis.open( dictSource ) result = redis.get( key ) rescue => e STDERR.printf( "Error: sekka-server can't connect to redis(port=%s)...\n", dictSource ) exit 1 end unless result # tsvファイルをuploadする。 STDERR.printf( "Info: Uploading...\n" ) cmd = sprintf( "sekka-jisyo restore %s %s:%s", TSVFILE, dictType, dictSource ) STDERR.printf( "Command : %s\n", cmd ) system( cmd ) end STDERR.printf( "Info: [OK]\n" ) else raise RuntimeError, sprintf( "Error: unknown dictType [%s]", dictType ) end # 設定項目をConfigオブジェクトに代入 SekkaServer::Config.setup( dictType, dictSource, MEMCACHED, 12929, proxyHost, proxyPort ) # サーバースクリプトのrootディレクトリへ移動 FileUtils.cd(File.dirname(__FILE__) + "/../") # サーバー起動 Rack::Server.start( :environment => "development", :pid => nil, :Port => SekkaServer::Config.listenPort, :Host => "0.0.0.0", :AccessLog => [], :config => "./lib/sekka.ru" ) end main()