Hatena::ブログ(Diary)

NetPenguinの日記 このページをアンテナに追加 RSSフィード

'アニヲタ' 兼 Perfume ファン 兼 'Scala, C/C++, Java プログラマ'
日々の愚痴をつづる日記です。
FTPソフトの NetPenguin とは何の関係もありません。

2011-10-01

[] ダウンキャスト 01:43  ダウンキャストを含むブックマーク  ダウンキャストのブックマークコメント

Scalaプログラミングしていると型パラメータパターンマッチがあるからか、ダウンキャストが必要になることがあまり無いです。

なのですが、パターンマッチの多用によりインデントが深くなってしまうのが悩ましかったりします。

例えば dispatch.json (sjson で利用している JSON のパーサ等) を利用して、すでに型がわかっているデータ構造をたどっている場合などです。 *1

Js(response) match {
  case JsObject(x) => x.get(JsString("foo")) match {
    case Some(JsString(foo)) => x.get(JsString("bar")) match {
      case Some(JsString(bar)) => Some((foo, bar))
      case _ => None
    }
    case _ => None
  }
  case _ => None
}

読みづらすぎる*2・・・ case _ => None の出現回数が多いのとインデントが深いのとで、なんだかいまいちです。

Scala には for 内包表記という便利なものがあるので、それを使用してなんとかインデントを浅くできないものかと思い、以下のように書いてみました。

for {
  JsObject(x)   <- Some(Js(response))
  JsString(foo) <- x.get(JsString("foo"))
  JsString(bar) <- x.get(JsString("bar"))
} yield (foo, bar)

あぁ、すっきり。

なのですが、JsObject(x) <- ... や JsString(foo) <- ... のようにして受けているため、もし型が違っていた場合は例外がでてしまます

なんとかして想定と違う型の場合はそのデータは無視して処理を続行したいです。

というわけで、以下のような型検査&変換をするメソッドを作ってみました。

implicit def any2Caster[T](value: T): Caster[T] = new Caster[T](value)
class Caster[T](value: T) {
  def as[U<:T:Manifest]: Option[U] =
    if (manifest[U].erasure.isInstance(value)) Some[U](value.asInstanceOf[U])
    else None
}

使用例は以下のような感じになります

val value: Any = "Hello World" // value は Any 型
val text = value.as[String]    // text は Option[String] 型、値は Some("Hello World")
val integer = value.as[Int]    // integer は Option[Int] 型、値は None

この as[T] と JsObject -> MapString -> JsString の暗黙の型変換を定義しておくことで、以下のような記述ができます

for {
  x   <- Js(response).as[JsObject]
  foo <- x.get("foo").flatMap(_.as[JsString])
  bar <- x.get("bar").flatMap(_.as[JsString])
} yield (foo, bar)

あるいは flatMap の記述も排除するならば以下のようにします。。

for {
  x      <- Js(response).as[JsObject]
  foo    <- x.get("foo")
  bar    <- x.get("bar")
  fooStr <- foo.as[JsString]
  barStr <- bar.as[JsString]
} yield (fooStr, barStr)

ちなみに Js* との型変換は以下のような感じで定義しています

implicit def jsObject2Map(js: JsObject): Map[JsString, JsValue] = js.self
implicit def jsString2String(js: JsString): String = js.self
implicit def string2JsString(value: String): JsString = JsString(value)

def as[T]:Option[T] は Scala に標準で用意されていても良さそうな気もするのですが、私が知らないだけなのかも・・・

*1:本来であれば sjson で Protocol 書いて、対応する Scala の型にマップしてしまえば良いです

*2:わざとパターンマッチだけで記述しています

トラックバック - http://d.hatena.ne.jp/NetPenguin/20111001

2011-03-21

[][] PuTTY + screen日本語入力ができない 19:09  PuTTY + screen で日本語入力ができないを含むブックマーク  PuTTY + screen で日本語入力ができないのブックマークコメント

perl の開発環境用として自鯖仮想マシンを追加したのですが、なんだか日本語入力ができない!という現象にでくわしました。

原因は .screenrc に term xterm のように端末の種類名?を指定していなかったからっぽいです。

またはまらないようにメモ・・・と。

ちなみに日本語入力Windows 上の IME を使用しています。

トラックバック - http://d.hatena.ne.jp/NetPenguin/20110321

2011-02-02

[][] リスト操作対応23:27  リスト操作対応表を含むブックマーク  リスト操作対応表のブックマークコメント

おもいつきでだらだら書いたので、足りていない可能性の方が高いです。

ちなみに Perl には Scala の List 見たいなものや、Stream みたいなものは標準では用意されていないため、通常は配列を使います

@ で始まる変数が配列です。でも配列への参照も良く使うので、$で始まってても参照先が配列というのはよくあること。

操作ScalaPerl
mapxs.map { _ + 1 }map { $_ + 1 } @xs
flatMapxs.flatMap { x => x*2-1::x*2::Nil }map { ($_ * 2 - 1, $_ * 2) } @xs
filterxs.filter { _ % 2 == 0 }grep { $_ % 2 == 0 } @xs
reducexs.reduceLeft { _ + _ }List::Util::reduce { $a + $b } @xs
fold(1 /: xs){ _ * _ }List::Util::reduce { $a * $b } (1, @xs)
zipxs.zip(ys)List::MoreUtils::pairwise { [$a, $b] } @xs, @ys
findxs.find { _ % 2 == 0 }List::Util::first { $_ % 2 == 0 } @xs
maxxs.maxList::Util::max @xs
Extractorval y::ys = xsmy ($y, @ys) = @xs

とりあえずいま思いつくところだとこんな感じです。

Perl では配列内に配列をいれても展開されるので、flatten と同じ効果が欲しい場合はそのまま配列を、二次元配列にしたい場合配列への参照を格納する必要があります

なので、flatMap 相当の処理は mapブロックが返す値を配列にすれば実現できます

また、zip 相当の処理は pairwise で配列への参照を返すようにしています。[$a, $b] の部分が $a と $b を要素にもつ配列への参照を表します。

ついこないだまで C#LINQ を使っていたので、遅延リストが無いのは結構つらいです orz

トラックバック - http://d.hatena.ne.jp/NetPenguin/20110202

2011-01-09

[][] NFS クライアント設定 19:23  NFS クライアント設定を含むブックマーク  NFS クライアント設定のブックマークコメント

NFS サーバFreeNAS でさくっと用意できているので問題なし。

FreeNAS で公開しているディレクトリを、CentOS5.5 のサーバ上でマウントした手順。

  1. nfs 等のデーモンを停止してあったので、再開する
    1. chkconfig portmap on
    2. chkconfig nfslock on
    3. chkconfig nfs on
  2. マウントポイントとなるディレクトリを用意する
    1. mkdir /mnt/repositories@chinstrap
  3. マウントしてみる
    1. mount -t nfs chinstrap:/mnt/tank/repositories /mnt/repositories\@chinstrap
  4. fstab に以下を追記して起動時にマウントされるようにする
    1. chinstrap:/mnt/tank/repositories /mnt/repositories@chinstrap nfs defaults 0 0
    2. mount -a で fstab の記述内容を試せる
  5. 再起動して確認
    1. reboot
    2. マウントされていなかったorz
  6. netfs が動いていないのが原因
    1. nfs, cifs, smbfs のファイルシステムは netfs 起動時にマウントされる
    2. ローカルディスクマウントネットワークインタフェースの起動 → ネットワークファイルシステムマウント
  7. chkconfig netfs on
  8. 再起動して確認
    1. マウントされた!!

その他

cifs をマウントするときにホスト名を使用すると失敗する。(CIFS VFS: cifs_mount failed w/return code = -22)

ipアドレスを直接記述すると成功するため、net-bios 名の解決ができないからか?

[][] リバースプロキシ設定 00:49  リバースプロキシ設定を含むブックマーク  リバースプロキシ設定のブックマークコメント

私の環境では外部向けに公開している Apache の入っているホストとは別のホスト上に、SVNリポジトリ作成しました。

このままでは外部から SVN リポジトリアクセスできないため、リバースプロキシを設定して https://svn.〜/ のときに SVN リポジトリの入っているホストリクエスト転送するようにしました。

SVN リポジトリの入っているホストでは、WebDAV プロトコルを使用した SVN との連携を設定済みです。

snares:/etc/httpd/conf.d/vhosts/vhosts.conf

<Location />
  DAV svn
  SVNPath /mnt/repositories@chinstrap/svn

  #<LimitExcept GET PROPFIND OPTIONS REPORT>
    SSLRequireSSL
    AuthType Basic
    AuthName "Authorization Realm"
    AuthUserFile /mnt/repositories@chinstrap/svn/conf/htpasswd
    Require valid-user
  #</LimitExcept>
</Location>

Basic 認証をつかっているため、SSL 以外ではコミットなどの作業をできないように設定しています

このため、リバースプロキシの設定もアクセスされたのが http の場合は http に、https の場合は https に転送するようにしています

http://d.hatena.ne.jp/NetPenguin/20081127#p1 にあるように、ファイルを分割して仮想ホスト+SSLの設定をしていますのでリライトの設定についても SSL の有無に関係なく一か所で済むようにします。編集対象としているファイルの詳細については、http://d.hatena.ne.jp/NetPenguin/20081127#p1エントリを参照してください。

rockhopper:/etc/httpd/conf.d/vhosts/vhosts.conf

外部からSVN リポジトリへのアクセスを受け付ける仮想ホストを用意します。

<VirtualHost *:80>
  Include conf.d/vhosts/svn.netpenguin.org.part

  ErrorLog logs/svn.netpenguin.org.error_log
  CustomLog logs/svn.netpenguin.org.access_log  combined
</VirtualHost>
<VirtualHost *:443>
  Include conf.d/vhosts/ssl.part
  Include conf.d/vhosts/svn.netpenguin.org.part

  ErrorLog logs/svn.netpenguin.org.error_log
  CustomLog logs/svn.netpenguin.org.access_log combined
  CustomLog logs/svn.netpenguin.org.ssl_request_log ssl_request

rockhopper:/etc/httpd/conf.d/vhosts/svn.netpenguin.org.part

外部からSVN アクセスを、実際に SVN リポジトリを公開しているサーバ転送します。

外部向けに登録している SVN サーバホスト名も、内部のホスト名も svn.netpenguin.org なので紛らわしいですが、RewriteRule に記述している https://svn.netpenguin.org/ は内部向けに用意している DNS によって解決され、そのアドレスプライベート IP (SVN リポジトリを公開しているホストIP アドレス)になります

ServerName svn.netpenguin.org

SSLProxyEngine On
RewriteEngine On
ProxyRequests Off

RewriteCond %{HTTPS} on [NC]
RewriteRule ^/(.*) https://svn.netpenguin.org/$1 [P]

RewriteCond %{HTTPS} off [NC]
RewriteRule ^/(.*) http://svn.netpenguin.org/$1 [P]

この設定では、HTTPS によるアクセスを扱うために SSLProxyEngine On を指定し、また http でのアクセスは http のまま、https でのアクセスは https として転送するために、RewriteCond %{HTTPS} on (あるいはoff)の指定によって適用するリライトルールを分けています

実際に外部(e-mobile経由)から試してみましたが、問題なく SVN リポジトリアクセスできました。

ちなみに、単純にリバースプロキシを構築するだけであれば、RewriteRule ではなく ProxyPass の設定だけで十分かと思います

あと、本来であれば ProxyPassReverse も設定した方が良いのですが、SVN リポジトリへのアクセスリダイレクト等は発生しないだろうと思い未設定です。これを設定する場合、同じ記述での http/https 両対応が難しそうなので http アクセス場合は https にリダイレクトさせてしまい、それから ProxyPass によって https://〜 に転送、ProxyPassReverse も https://〜 で設定という流れにするかと思います。(ためしてないけど)

つのグローバルIP自鯖を立てている環境では、仮想ホストリバースプロキシは必須だなぁと実感してたりします。あと、無料の DynamicDNS サービスも。

トラックバック - http://d.hatena.ne.jp/NetPenguin/20110109

2010-12-28

[][] 仮想マシン増殖 22:44  仮想マシン増殖を含むブックマーク  仮想マシン増殖のブックマークコメント

私にとっての最小構成のサーバを作ったので、これをコピーして増殖させます

あと、後々用にスナップショット*1をとっておきます

  1. 仮想マシンシャットダウン
  2. 一応、イベントから削除する
  3. ストレージプールホストしている FreeNASシェルログイン
  4. 目当てのディレクトリコピー
  5. コピーしたvmxファイルデータストアブラウザで選択し、イベントリに追加する
  6. インスタンス名を聞かれるので適切なものに修正する
  7. コピーしたインスタンスを起動する
  8. 初回起動時にコピーされたものかどうか聞かれるので、「I copy it.」を選択
  9. system-config-network を起動し、ホスト名を修正する
  10. tripwire のキーファイル名はホストから付けているので、ファイル名を変更または新たなキーファイル作成する
  11. tripwire --init しておく

*1ZFSなので一瞬でとれる

トラックバック - http://d.hatena.ne.jp/NetPenguin/20101228
2004 | 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 | 12 |
2008 | 01 | 03 | 04 | 06 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 04 | 11 | 12 |
2011 | 01 | 02 | 03 | 10 |
PV:218235