ServerSocket の SO_REUSEADDR ソケットオプションの初期設定は誰が決めているのか
ふと ServerSocket の SO_REUSEADDR ソケットオプションが気になったときのメモ。
Java API 仕様
API 仕様には以下のように記述されている。ということは Java は我関せず?
ServerSocketが作成されるときに、SO_REUSEADDRの初期設定は定義されていません。アプリケーションはgetReuseAddress()を使用して、SO_REUSEADDRの初期設定を確認できます。
http://docs.oracle.com/javase/jp/8/api/java/net/ServerSocket.html#setReuseAddress-boolean-
SO_REUSEADDR ってなに?
SO_REUSEADDR は、サーバに TIME_WAIT 状態のアドレスに bind することを許します。
Programming UNIX Sockets in C - Frequently Asked Questions: サーバアプリケーションの作成 (TCP/SOCK_STREAM)
http://www.kt.rim.or.jp/~ksk/sock-faq/unix-socket-faq-ja-4.html
ちょっと乱暴だが、固定ポートに bind するサーバー以外では気にしなくても大丈夫ぽい*1
SO_REUSEADDR の初期設定
import java.io.IOException; import java.net.ServerSocket; public class PrintReuseAddress { public static void main(String[] args) throws IOException { boolean reuseAddress = new ServerSocket().getReuseAddress(); System.out.printf("SO_REUSEADDR: %s", reuseAddress); } }
これを手近なマシンで試してみた結果が↓これ。
- 普段使いの Windows 機
- 転がってた Windows Server 機
- OS: Windows Server 2008 R2 Sp1
- Java: 1.6.0_45 HotSpot(TM) 64-Bit Server VM
- SO_REUSEADDR: false
- 転がってた Ubuntu
- MBA
- http://www.javarepl.com/console.html
補足
OS X のデフォルトはやっぱり true の模様 http://lists.apple.com/archives/java-dev/2004/Dec/msg00570.html
*1:固定ポートに bind するクライアントもあるらしい
Invoke-WebRequestコマンドレットのエイリアスがcurl, wgetという落とし穴
職場 PC が Windows なのだが UNIX ライクなコマンドが使いたくて Gow を使っている。ところが、最近 PowerShell を 3.0 にアップデート*1したところ curl が上手く動かなくなった。調べたところ、Invoke-WebRequest コマンドレットのエイリアスに curl, wget が割り当てられているのが原因だった。忘れたときのためにメモしておく。
curl がエラーになる
PS >curl --silent http://www.yahoo.co.jp/ Invoke-WebRequest : 引数 'http://www.yahoo.co.jp/' を受け入れる位置指定パラメーターが見つかりません。 発生場所 C:\Users\ebi\bin\download.ps1:100 文字:1 + curl --silent "http://www.yahoo.co.jp/" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidArgument: (:) [Invoke-WebRequest]、ParameterBindingException + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
エラーメッセージを読むと curl を Invoke-WebRequest コマンドレットとして実行しているのだが、まさかと思いつつエイリアスを調べてみるとそのまさかだった。
PS >Get-Alias -Definition Invoke-WebRequest CommandType Name ModuleName ----------- ---- ---------- Alias curl -> Invoke-WebRequest Alias iwr -> Invoke-WebRequest Alias wget -> Invoke-WebRequest
解決
curl, wget のような紛らわしいエイリアスは要らないので削除する。
PS >Remove-Item -Path Alias:curl PS >Remove-Item -Path Alias:wget PS >Get-Alias -Definition Invoke-WebRequest CommandType Name ModuleName ----------- ---- ---------- Alias iwr -> Invoke-WebRequest
これで curl.exe が使われるようになるがエイリアス削除は現在のセッションにしか反映されない。そこで $profile の中でエイリアス削除するようにした。
*1:ハンコが何個必要になったかは書かない
リスクに対処する方法
トム・デマルコの熊とワルツをを読んでいる。
9章「リスク管理のしくみ」ではプロジェクトを開始する前にリスク・リスト*1を作成し、それに対処する方法が書かれている。本文ではデンバー国際空港の自動手荷物処理システムの失敗を例えにしているのだが、読むうちに脳内で RPG 風の例えに変換されてしまった。しかし、なかなか分かりやすいように思えるしそう外れていないように感じたのでメモしておく。
リスクに対処する方法
熊とワルツをではリスクに対処する方法を4つ上げている。
- 避ける
- 抑制する
- 軽減する
- かわす
避ける
そのプロジェクトの中でリスクをともなう部分に手を付けないこと。リスクを避けると当然の結果として、リスクをともなう領域に入ることで得られる利益を見逃すことになる。
抑制する
リスクが実現した場合にかけなければならない時間と資金を準備しておくこと。個々のリスクを抑制してもあまり意味はなく、リスク全体をひとまとめに抑制するべき。
軽減する
リスクが実現する前に、後の抑制コストを軽減するための措置をとっておくこと。
かわす
上記のようなことは何もしなかったが、たまたまリスクの襲来をまぬがれる場合をいう。リスクをかわそうと計画する場合、天に祈るのが通例である。
ぼくがかんがえたさいきょうのたとえ
プロジェクトは、名作ドラゴンクエスト3*2のゲーム開始直後、アリアハンからナジミの塔にいって盗賊の鍵を入手することとする。道中には毒攻撃をしてくるバブルスライムや後列攻撃*3してくるフロッガーがいる。こいつらの出現確率は概して低いが、時として高い確率で出現することがある。
抑制する
毒を受けても大丈夫なように毒消し草を買ったり、フロッガーの後列攻撃をすぐ回復できるように薬草を多めに買っておく。しかし、毒を受けなかった場合は毒消し草の代金が無駄になるし、フロッガーが前列攻撃してきた場合はダメージが小さく済むため薬草の代金が無駄になる。
軽減する
フロッガーの後列攻撃に備えて後列の装備を充実させる。装備を充実させるためのお金がかかるが、後列攻撃を受けてもダメージが小さく済むので用意しておく薬草を減らせる。一度で攻略できず何度もアタックする場合は、抑制するよりも安くあがる。
結論
本文中の定義で十分だしそのほうが分かりやすかった。
Vrapper のインデント動作が変わった
仕事で使っている PC の Vrapper を久しぶりにアップデートしたらインデント動作が変わっていたので、試行錯誤した時のメモ *1
また、ここでのインデント動作というのは、ノーマルモードでの「<<」「>>」やインサートモードでタブキーを押した時の動作を指す。
変わったこと
アップデート前は Eclipse の設定 *2 と同じように動いていた。
そのため、.vrapperrc にはインデント関係の設定は一切書いていなかった。
しかしアップデート後はインサートモードでは Eclipse の設定通りに動いてくれるが、ノーマルモードでの「<<」「>>」が明らかに Eclipse の設定とは違う。
たとえば、Tab policy を Tabs only にしているのに「>>」するとスペースが挿入されるといった動きになる。
したこと
Eclipse と同じ動作になるように .vrapperrc に設定しておく。
例えば、タブ文字でインデントするには以下のようにする。
set noexpandtab
スペース4個でインデント、既存のタブ文字をスペース12個分の幅で表示するなら以下のようにする。
set expandtab set tabstop=12 set shiftwidth=4
Windows で UNIX の find みたいなことをする
背景
forfiles コマンドを使えば Windows でも UNIX の find コマンドみたいなことが出来る。
が、Windows XP だったりすると forfiles なにそれおいしいの?ということは珍しくないと思う*1
解決策
dir コマンドを使って劣化 find コマンドを作る。
@echo off setlocal set target=%1 set exec_cmd=%2 if "%exec_cmd%"=="" ( set exec_cmd=dir /b ) else ( set exec_cmd=%exec_cmd:"=% ) shift shift for /f "usebackq" %%i in (`dir /b /s %target%`) do ( %exec_cmd% %1 %2 %3 %4 %5 %6 %7 %8 %9 %%i )
ここでは wfind.bat としてパスを通しておく。
使う時はこんな感じ。
第一パラメータに処理対象ファイル、第二パラメータに実行コマンドを指定する*2
C:\Users\eb>wfind *.txt
abc.txt
def.txt
C:\Users\eb>wfind *.txt type
C:\Users\eb\abc.txt
C:\Users\eb\def.txt
第二パラメータの実行コマンドになんちゃって sed みたいな VBScript を、そしてこのバッチファイル自体は他のバッチファイルから呼び出す、みたいにして使っていた。
昔を思い出したので書いてみたけど、XP のサポートが終了した今となっては全く価値のないバッチファイル。
本当に今は良い時代になったものだと思う。
Mercurial をホームディレクトリにインストールする
背景
評価用に Mercurial を一般ユーザーのホームディレクトリにインストールしたので、備忘録までに。
状況としてはディストリビューションがものすごく古い、一般ユーザー権限しか持っていない、パッケージ管理コマンドが使えない…といった良くあるもので、条件は以下のような感じ。
- ソースからインストールする
- 一般ユーザーのホームディレクトリにインストールする
- 今回インストールしたマシンは Ubuntu (古い)
- HTML / man 形式のヘルプテキストは不要 (hg help が使えれば良い)
依存関係
SupportedPythonVersions - Mercurial *1
※HTML/man 形式のヘルプテキストが必要な場合は Docutils もインストールする必要がありますが、今回は hg help で賄えるのでインストールしません。
Mercurial
- Python |
ソースアーカイブの取得
- Mercurial: http://selenic.com/hg
- Python: http://www.python.jp/
- zlib: http://www.zlib.net/
- bzip2: http://www.bzip.org/
アーカイブ形式は tar.gz として *2 ~/src にダウンロード。バージョンは以下のとおり *3
- Mercurial: 2.9.2 (3f83fc5cfe71)
- Python: 2.7.6
- zlib: 1.2.8
- bzip2: 1.0.6
インストール
# zlib $ cd ~/src $ tar zxvf zlib-1.2.8.tar.gz $ cd zlib-1.2.8 $ ./configure --prefix=$HOME $ make $ make install # bzip2 $ cd ~/src $ tar zxvf bzip2-1.0.6.tar.gz $ cd bzip2-1.0.6 $ make -f Makefile-libbz2_so $ make $ make install PREFIX=$HOME # make で -fPIC オプションを指定しろ〜と言われた場合には # Makefile-libbz2_so の CFLAGS に追加する。 # (ex.) CFLAGS=-fPIC (省略) # Python $ cd ~/src $ tar zxvf Python-2.7.6.tgz $ cd Python-2.7.6 $ ./configure --prefix=$HOME $ make $ make install
~/bin にパスを通すために ~/.bash_profile を編集。
# ~/.bash_profile export PATH=~/bin:$PATH
続いて Mercurial をインストール。
# Mercurial # HTML / man 形式のヘルプテキストは不要なので make install-home-bin $ cd ~/src $ tar zxvf Mercurial-3f83fc5cfe71.tar.gz $ cd Mercurial-3f83fc5cfe71 $ make install-home-bin
確認
$ hg version Distributed SCM (version 2.9.2) (see http://mercurial.selenic.com for more information) Copyright (C) 2005-2014 Matt Mackall and others This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
まとめ
依存関係の解決等、もっときちんとしたやり方があるはず。
パッケージ管理コマンドは偉大。
謝辞
不正確な記述、冗長な手順について指摘して下さった @flyingfoozy さん、ありがとうございました><
Windows 環境で hg convert で pserver 接続の CVS リポジトリに接続できない
状況
実際にしたこと
> cvs -d:pserver:user@repository.host:/repo/path checkout somemodule
> hg convert somemodule somemodule-hg
hg convert を実行すると早々に「そんなリポジトリはない」と言われてしまいます。
なぜ?
convert extension は変換元リポジトリ (CVS) の変更履歴を取得しようとしますが、この時に接続情報として以下が必要です。
- "BEGIN AUTH REQUEST"
- CVSROOT
- ユーザー名
- パスワード (気休め程度に暗号化されたもの)
- "END AUTH REQUEST"
これらを LF で結合して送信するのですが、実際に送信したデータを見ると CVSROOT の後ろになぜか CR がありました。
これは convert extension が CVSROOT を作業ディレクトリの管理ファイル (Root) から取得するときの処理が原因でした。
self.cvsroot = open(os.path.join(cvs, "Root")).read()[:-1]
WinCVS なので Root ファイルの改行コードも CRLF になっていて、その CR を取りこぼしてしまったようです *1
「これかー」みたいなことを Twitter で呟いていたら @flyingfoozy さんに「リストから取り出すときに strip() すればいいですよ」と教えて頂いたので、早速試してみたところちゃんと接続出来ました *2
他にも落とし穴が
変換元リポジトリには接続できたのですが、その後の変更履歴を取り出す段になって cvs log コマンドの解析に失敗しているのか、変換後のリポジトリでは全てのリビジョンでファイルが "新規追加" になってしまいました。
リビジョン数も明らかに少なく、@flyingfoozy さんに相談しながら色々と試したのですが、原因究明までは至らずギブアップとなりました。
その後
cygwin の cvs コマンドでチェックアウトしたものを hg convert したら一発で出来ました。
どう見ても不注意です。@flyingfoozy さん本当にすみませんでした。