#!/usr/bin/env ruby # -*- coding: utf-8 -*- require 'digest/md5' require 'fileutils' require 'rack' require 'uri' require 'sekkaconfig' require 'sekka/sekkaversion' DICTDIR = File.expand_path( "~/.sekka-server" ) DICTURL = "https://raw.githubusercontent.com/kiyoka/sekka/master/public_dict/" + SekkaVersion.dictVersion PIDFILE = DICTDIR + "/pid" DICTTYPE = "N" if ENV.has_key?( 'SEKKA_AZIK' ) STDERR.printf( "Error: SEKKA_AZIK became obsolute. sekka-server use normal dictionary.\n" ) end DICTSIZE = if ENV.has_key?( 'SEKKA_LARGE' ) if 1 == ENV[ 'SEKKA_LARGE' ].to_i "LARGE" else "SMALL" end else "SMALL" end TC_OPTS = "#xmsiz=256m" TC_FILE = DICTDIR + "/SEKKA-JISYO.#{DICTSIZE}.#{DICTTYPE}.tch" + TC_OPTS TSVFILE = DICTDIR + "/SEKKA-JISYO.#{DICTSIZE}.#{DICTTYPE}.tsv" SUMFILE = DICTDIR + "/SEKKA-JISYO.#{DICTSIZE}.#{DICTTYPE}.md5" GDBM_FILE = DICTDIR + "/SEKKA-JISYO.#{DICTSIZE}.#{DICTTYPE}.db" URLURL = DICTURL + "/SEKKA-JISYO.#{DICTSIZE}.#{DICTTYPE}.url" SUMURL = DICTURL + "/SEKKA-JISYO.#{DICTSIZE}.#{DICTTYPE}.md5" 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 ] elsif m = ENV['SEKKA_DB'].match( /^gdbm$/i ) [ :gdbm, nil ] else raise RuntimeError, "Error: env var SEKKA_DB requires [redis:hostname] or [redis:] or [tokyocabinet]" end else [ :tokyocabinet, nil ] end end def checkJisyoIsInstalled( dictType, dictSource ) key = "SEKKA:VERSION" STDERR.printf( "Info: Checking SEKKA jisyo on #{dictType} server...\n" ) begin result = case dictType when :gdbm require 'sekka/kvs' tc = Kvs.new( :gdbm ) tc.open( dictSource ) ret = tc.get( key ) tc.close() ret when :tokyocabinet require 'tokyocabinet' require 'sekka/kvs' tc = Kvs.new( :tokyocabinet ) tc.open( dictSource ) ret = tc.get( key ) tc.close() ret when :redis begin require 'redis' require 'sekka/kvs' redis = Kvs.new( :redis ) redis.open( dictSource ) ret = redis.get( key ) redis.close() ret rescue => e STDERR.printf( "Error: sekka-server can't connect to redis(port=%s)...\n", dictSource ) exit 1 end end 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 %s", URLURL ) STDERR.printf( "Command : %s\n", cmd ) tsvurl = open( "|" + cmd ) { |f| f.read } STDERR.printf( " download URL of tsv file : %s\n", tsvurl ); 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 :gdbm # GDBMに辞書が投入済みか確認する ok = checkJisyoIsInstalled( dictType, GDBM_FILE ) unless ok # tsvファイルをuploadする STDERR.printf( "Info: Uploading...\n" ) cmd = sprintf( "sekka-jisyo restore %s %s", TSVFILE, GDBM_FILE ) STDERR.printf( "Command : %s\n", cmd ) system( cmd ) end STDERR.printf( "Info: [OK]\n" ) dictSource = GDBM_FILE when :tokyocabinet # TokyoCabinetに辞書が投入済みか確認する ok = checkJisyoIsInstalled( dictType, TC_FILE ) unless ok # tsvファイルをuploadする STDERR.printf( "Info: Uploading...\n" ) cmd = sprintf( "sekka-jisyo restore %s %s", TSVFILE, TC_FILE ) STDERR.printf( "Command : %s\n", cmd ) system( cmd ) end STDERR.printf( "Info: [OK]\n" ) dictSource = TC_FILE when :redis # redisサーバーに辞書が投入済みか確認する ok = checkJisyoIsInstalled( dictType, dictSource ) unless ok # 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 ) # rackに渡すための sekka.ru のインストールパスを求める。 vendordir = File.expand_path(File.dirname(__FILE__) + "/../lib") if RbConfig::CONFIG[ 'vendordir' ] if File.exists? RbConfig::CONFIG[ 'vendordir' ] + "/sekka.ru" vendordir = RbConfig::CONFIG[ 'vendordir' ] end end # print "vendordir = " + vendordir + "\n" # サーバー起動 Rack::Server.start( :environment => "development", :pid => nil, :Port => SekkaServer::Config.listenPort, :Host => "0.0.0.0", :AccessLog => [], :config => vendordir + "/sekka.ru" ) end main()