月曜日, 11月 07, 2011

CentOSのSubversionを1.4から1.6にアップグレード

現在使っているSubversionのリポジトリサーバがCentOS 5.2でSubversionは1.4.2-2(r22196)がインストールされている。これまではサーバ側のバージョンとクライアント側のバージョンをなるべく1.4に統一してやっていた。最近はGitを使うことが増えてきて、既存のsvnリポジトリと連携したいケースも出てきたが、git-svnを使うには1.6が必要。いま(2011年11月)はCentOS 5.2上でyum updateを実行しようとするとSubversion 1.6.11-7がインストールされるようだが、1.4.xと1.6.xでは互換性がどうなっているのかよくわからないので、いろいろ試してからアップグレードすることにした。

  • 現在の環境
  • Subversion 1.4でリポジトリ作成
  • 1.4のリポジトリに1.6.x系のクライアントでアクセス
  • yumでSubversion 1.6をインストール
  • 1.4で作成されたリポジトリに1.4と1.6でアクセス
  • 1.4でチェックアウトした作業コピーを1.6で操作
  • 1.6で作成されたリポジトリに1.4からアクセス
  • まとめ

現在の環境


  • OS: CentOS release 5.2 (Final)
  • Subversion: バージョン 1.4.2 (r22196)
  • mod_dav_svn: 1.4.2

※いきなり本番環境のSubversionをアップデートするわけにもいかないのでVMを構築しようと思ったら、いま(2011年11月)CentOS 5.2を入手してSubversionとmod_dav_svnをyumインストールしようとすると1.6系しかインストールできない。昔のVMを引っ張り出してなんとかSubversionとmod_dav_svnが両方1.4.2の環境を用意した。

Subversion 1.4でリポジトリ作成


リポジトリは以下のように作成。

# cd /var/www/svn
# svnadmin create project1 --fs-type fsfs
# chown -R apache.apache project1

ブラウザから http://[ip]/svn/project1 にアクセスして「Revision 0」と表示されればリポジトリの作成は成功。この状態で/var/www/svn/project1/db/formatを確認すると「2」と書いてあり、formatタイプが2であることが分かる。

ここに適当にファイルをコミットしておく。

$ mkdir project1
$ ethna add-project sample
$ cd ..
$ svn import -m "New Import" project1 http://[ip]/svn/project1/trunk/project1
$ rm -fr project1
$ svn checkout http://[ip]/svn/project1/trunk/project1 ./project1

1.4のリポジトリに1.6.x系のクライアントでアクセス


CentOS 5.6にインストールされているsvn 1.6.11(r934486)でプロジェクトをチェックアウトし、ファイルを変更する。その後svn 1.4.2からも問題なくリポジトリの操作が行えたため、この操作によって1.4のリポジトリのフォーマットが変わっていないことが分かる。
(db/formatも2のまま)

同様にTortoiseSVN 1.6.11でプロジェクトをチェックアウトし、ファイルを変更したが結果はsvnコマンドと同じだった。

yumでSubversion 1.6をインストール


CentOS 5.2でyumを使ってSubversion 1.6をインストールする。

# yum update subversion
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirror.khlug.org
 * updates: mirror.khlug.org
 * extras: ftp.daum.net
Setting up Update Process
Resolving Dependencies
--> Running transaction check
---> Package subversion.i386 0:1.6.11-7.el5_6.4 set to be updated
--> Processing Dependency: subversion = 1.4.2-4.el5_3.1 for package: mod_dav_svn
--> Running transaction check
---> Package mod_dav_svn.i386 0:1.6.11-7.el5_6.4 set to be updated
--> Finished Dependency Resolution

Dependencies Resolved

=======================================================================================================================================================
 Package                               Arch                           Version                                     Repository                      Size
=======================================================================================================================================================
Updating:
 mod_dav_svn                           i386                           1.6.11-7.el5_6.4                            base                            78 k
 subversion                            i386                           1.6.11-7.el5_6.4                            base                           3.1 M

Transaction Summary
=======================================================================================================================================================
Install      0 Package(s)         
Update       2 Package(s)         
Remove       0 Package(s)         

Total download size: 3.2 M
Is this ok [y/N]: y
Downloading Packages:
(1/2): mod_dav_svn-1.6.11-7.el5_6.4.i386.rpm                                                                                    |  78 kB     00:00     
(2/2): subversion-1.6.11-7.el5_6.4.i386.rpm               (13%) 11% [=====                                           ]  0.0 B/s | 360 kB     --:-- ETA 
(2/2): subversion-1.6.11-7.el5_6.4.i386.rpm               (27%) 25% [============                                    ] 738 kB/s | 816 kB     00:03 ETA 
(2/2): subversion-1.6.11-7.el5_6.4.i386.rpm               (35%) 33% [================                                ] 744 kB/s | 1.1 MB     00:02 ETA 
(2/2): subversion-1.6.11-7.el5_6.4.i386.rpm               (60%) 60% [============================-                   ] 868 kB/s | 1.9 MB     00:01 ETA 
(2/2): subversion-1.6.11-7.el5_6.4.i386.rpm               (71%) 70% [=================================-              ] 883 kB/s | 2.2 MB     00:01 ETA 
(2/2): subversion-1.6.11-7.el5_6.4.i386.rpm               (76%) 75% [====================================            ] 862 kB/s | 2.4 MB     00:00 ETA 
(2/2): subversion-1.6.11-7.el5_6.4.i386.rpm               (81%) 81% [======================================-         ] 843 kB/s | 2.5 MB     00:00 ETA 
(2/2): subversion-1.6.11-7.el5_6.4.i386.rpm               (86%) 86% [=========================================       ] 822 kB/s | 2.7 MB     00:00 ETA 
(2/2): subversion-1.6.11-7.el5_6.4.i386.rpm               (91%) 91% [===========================================-    ] 807 kB/s | 2.9 MB     00:00 ETA 
(2/2): subversion-1.6.11-7.el5_6.4.i386.rpm               (95%) 95% [=============================================-  ] 784 kB/s | 3.0 MB     00:00 ETA 
(2/2): subversion-1.6.11-7.el5_6.4.i386.rpm               (99%) 99% [===============================================-] 762 kB/s | 3.1 MB     00:00 ETA 
(2/2): subversion-1.6.11-7.el5_6.4.i386.rpm                                                                                     | 3.1 MB     00:03     
-------------------------------------------------------------------------------------------------------------------------------------------------------
Total                                                                                                                  764 kB/s | 3.2 MB     00:04     
Running rpm_check_debug
Running Transaction Test
Finished Transaction Test
Transaction Test Succeeded
Running Transaction
  Updating       : subversion                                        [1/4] 
  Updating       : mod_dav_svn                                       [2/4] 
  Cleanup        : subversion                                        [3/4] 
  Cleanup        : mod_dav_svn                                       [4/4] 

Updated: mod_dav_svn.i386 0:1.6.11-7.el5_6.4 subversion.i386 0:1.6.11-7.el5_6.4
Complete!

mod_dav_svnもアップデートされたのでhttpdを再起動する。

# /etc/init.d/httpd restart

アップデートしただけでは/var/www/svn/project1以下のファイルには変化はないようだ。

1.4で作成されたリポジトリに1.4と1.6でアクセス


ここへんからが一番知りたいところ。現状/var/www/svn以下には1.4で作成されたformat=2のリポジトリがある。ローカルにインストールされたsvnは1.6.11(r934486)になったので、チェックアウトしてみる。

$ cd /tmp
$ svn checkout http://[ip]/svn/project1/trunk/project1 ./project1
$ cd project1
$ vim sample/www/index.php
$ svn commit -m "index.phpの変更"

さらに別のLinuxに入っているsvn 1.4.2でチェックアウトやコミットを試してみるが...なんともない。db/formatも2のまま。むむ。

1.4でチェックアウトした作業コピーを1.6で操作


上記の例ではSubversionを1.6に上げたが、1.4で作られたformat=2のリポジトリをチェックアウトして作業する想定だった。今度は1.4の時点で取得した作業コピーをsvn 1.6.11で操作するとどうなるのか試す。サーバのSubversionも1.6.11に上がっている。作業コピーだけが1.4という状況。

$ cd /path/to/project1
$ vim sample/www/index.php
$ svn commit -m "index.phpの変更"

1.6で操作後別のマシンから1.4で操作してみたが問題なし...db/formatも2のまま。フォーマットは変わっていない。むむむ。うまく操作できなくなると予想していたけど予想はハズレ。

1.6で作成されたリポジトリに1.4からアクセス


以下のコマンドで新たにリポジトリを作成する。1.6にバージョンが上がっているのでformat=4のリポジトリが作成される。

# cd /var/www/svn
# svnadmin create project2 --fs-type fsfs
# chown -R apache.apache project2

このリポジトリに1.4と1.6の両方でアクセスしたが、1.4からでも問題なく操作できた。

まとめ


ここから分かったことを(多くないけど)とりあえずまとめてみる。

  • yum updateによるSubversion 1.4.2 -> 1.6.11のアップデートではリポジトリのフォーマットは変更されない
  • 1.4.2で作成されたリポジトリにsvn 1.4とsvn 1.6の両方でアクセスしても問題ない
  • 1.6.11で作成されたリポジトリにsvn 1.4とsvn 1.6の両方でアクセスしても問題ない

ただし、今回試したのはcheckoutして編集してcommitするという非常に単純な作業だったし、ファイル数も多くない。
Subversion 1.5で追加されたshardingという機能はリビジョンが1000を超えると影響がありそうだが、それもテストできていない。

だが互換性は1.1系から1.4系に上げるときより格段に高いようなので、本番環境ではsvnadmin dumpでリポジトリのダンプを取得した状態でアップグレードを実施してみようと思う。

金曜日, 9月 16, 2011

PHPでセッション情報をDBに格納するときの注意点

最後の更新から1年以上経ってる...orz

session_set_save_handlerを使ってDBにセッション情報を保存するのは以前からやっていたけど、Ethnaに組み込んだ時にたまに以下のようなエラーが出ていた。

Fatal error: session_start(): Failed to initialize storage module: user (path: /tmp) in ...(以下略)

たまにではなく、DBにセッション情報がない状態でアクセスすると初回のみ毎回エラーが出る。これはまずい。調べた結果PHPのバグだったらしい。先人に感謝。


具体的にはEthnaのカスタムのセッションクラスに以下のような変更を追加。

//以下をコンストラクタに追加
        ini_set('session.save_handler', 'user');

        session_set_save_handler(
            array($this, "_open"),
            array($this, "_close"),
            array($this, "_read"),
            array($this, "_write"),
            array($this, "_destroy"),
            array($this, "_gc")
        );

//クラスに_open, _close, _read, _write, _destroy, _gc関数を作成

//isValid関数をオーバーライド
    function isValid()
    {
        if (!$this->session_start) {
            if (!empty($_COOKIE[$this->session_name]) || session_id() != null) {
                setcookie($this->session_name, "", 0, "/");
            }
            return false;
        }

        // check remote address
        if (!isset($_SESSION['REMOTE_ADDR'])
            || $this->_validateRemoteAddr($_SESSION['REMOTE_ADDR'],
                                          $_SERVER['REMOTE_ADDR']) == false) {
            // we do not allow this
            setcookie($this->session_name, "", 0, "/");
            session_destroy();
            
            //session_destroy直後にsession_set_save_handlerを再呼び出し
            session_set_save_handler(
                array($this, "_open"),
                array($this, "_close"),
                array($this, "_read"),
                array($this, "_write"),
                array($this, "_destroy"),
                array($this, "_gc")
            );
            
            $this->session_start = false;
            return false;
        }

        return true;
    }

//destroy関数をオーバーライド
    function destroy() {
        if (!$this->session_start) {
            return true;
        }
        
        session_destroy();

        //session_destroy直後にsession_set_save_handlerを再呼び出し
        session_set_save_handler(
            array($this, "_open"),
            array($this, "_close"),
            array($this, "_read"),
            array($this, "_write"),
            array($this, "_destroy"),
            array($this, "_gc")
        );

        $this->session_start = false;
        setcookie($this->session_name, "", 0, "/");
        
        return true;
    }


Ethnaを使わないで作成していた頃は上記のエラーは出ていなかったので、たぶんEthnaのセッションのクラスとの相性が悪いんだと予想。open,close,read,write,destroy,gcの呼び出しの順番とかが影響しているんだと思われる。今度時間があったらログつけてどういう順番なのか調べてみると理解が深まるかもしれない。

月曜日, 7月 19, 2010

動画変換のあいまに

久しぶりにブログなど書いてみるなう。

8mmビデオテープあらわる

先日実家に帰ったときに8mmビデオのテープの話題に。小学校の時に撮ったテープはすでに20年近く前のものだが、テレビの脇に無造作に積まれたままで保存状態が悪く、いつ再生できなくなるかわからない。しかもアダプターみたいなものを使ってVHSのデッキに入れないと見られないので、そもそも再生する機械がなくなってしまう。そんなわけでたまの親孝行にDVDに変換してみることにした。

8mmをDVDに変換

8mmからDVDへの変換はそういう作業を専門で行っている業者にお願いした。これは後で分かったことだが、テープにカビが生えていたためカビ取りの費用が余分にかかった。変換自体はVHSを再生できるデッキと入力した映像を録画できるDVDデッキさえあれば自分でできないこともないが、カビ取りはさすがに素人はムリだ。心配な人は専門業者にお願いしたほうがよい。

DVDからvob形式に取り込み

計12本の8mmを送付して待つこと数週間、DVD12本とオリジナルの8mmが帰ってきた。代金は2万を超えてしまったが、半分のテープでカビ取りが必要だったのでまぁ仕方がない。実家に持っていく前にMacTheRipperでHDDにデータをコピーしておいた。

ビデオの編集

ビデオの中身は親戚が集まった時のものや家族旅行だったが、1本あたり30分程度で、8mmを2,3本に分けて撮ってあった。これを親戚にも配りたいわけだが、せっかくだからちょっと編集してDVD1本に全部収められるとスマートだ。

ただしここで問題があって、iDVDではvob形式の動画形式は扱うことができないのでまた変換が必要になる。iSquintというフリーソフトを使用してvob形式のファイルをmp4形式に変換してやればよい。まとめて複数のファイルを変換できるが、同じファイル名のファイルを変換しようとするとちょっと動作がおかしいようだ。

DVDの作成

mp4形式になったらiDVDで編集できるようになるので、数本の動画をまとめてチャプターに分けてDVDを作成完了。mp4を結合するなら事前にiMovieで編集しておくとよい。

火曜日, 6月 08, 2010

特に設定を変えていないのにORA-12154またはORA-12560が発生した

Oracle 11gにsqlplusから接続しようとしたら急に接続できなくなった。 ウェブアプリやOracle SQL Developerからは接続できるのにsqlplusだけダメ。 変更したことと言えばOSのパスワード変えたぐらいか?と思ってたら重要なことを忘れてた。 Oracle Data Access Components(ODAC)インストールしてた!

ODACをインストールすることで、今までsqlplus.exeがC:\app\Administrator\product\11.1.0\db_1\BINにだけあったのに、 C:\app\Administrator\product\11.1.0\client_1にもsqlplus.exeが追加され環境変数Pathが書き換わっていた。 ということで環境変数PathからC:\app\Administrator\product\11.1.0\client_1を除いて無事接続できるようになりましたとさ。

水曜日, 2月 17, 2010

iMacrosで時間も操作

FirefoxのプラグインiMacrosを使えばFirefoxの操作を記録できるが、 記録した操作はPlayボタンで即時実行することしかできない。 さいわいJavaScriptも併用できるので、何時になったらスクリプト実行、みたいなことが実現できる。

実行するJavaScriptは「遅延実行.js」として以下のように作成する。

iimDisplay ("実行開始")

var run_time = new Date(2010, 1, 17, 19, 0, 0);
var timer_id;

timer_id = setInterval(
 function(){
  ret = iimDisplay ("現在時刻:" + new Date());
  
  if (run_time.getTime() < new Date().getTime())
  {
   ret = iimPlay("本体");
   
   clearInterval(timer_id);
  }
 },
 1000
);

実行されるiimファイルは「本体.iim」として以下のように作成する。 サンプルなので中身はどんな処理でも問題ない。

VERSION BUILD=6500125 RECORDER=FX
TAB T=1
URL GOTO=http://www.yahoo.co.jp/
TAG POS=1 TYPE=INPUT:TEXT FORM=NAME:sf1 ATTR=ID:srchtxt CONTENT=ラーメン
TAG POS=1 TYPE=INPUT:SUBMIT FORM=NAME:sf1 ATTR=ID:srchbtn

以上の2つをiMacrosのマクロが保存されているフォルダ以下にutf-8で保存して、 Editタブの「Refresh Macro List」をクリックして「遅延実行.js」をPlayで実行すれば、 2010年2月17日の夕ごはん時にYahoo! JAPANに移動してラーメンを検索してくれる、というわけ。 深夜にどこかに記事をポストしたいとかいうときに使えそう。

金曜日, 9月 04, 2009

PHPでMIMEタイプを取得する方法(画像限定)

mime_content_type関数が使えない環境で別の関数がなんだったか思い出せなくなるのでメモ。 ただしMIMEタイプを取得できるのは画像限定。

<?php
$array = getimagesize("Winter.jpg");
var_export($array);
$ php get_mime_type.php
Content-type: text/html
X-Powered-By: PHP/4.3.9

array (
  0 => 800,
  1 => 600,
  2 => 2,
  3 => 'width="800" height="600"',
  'bits' => 8,
  'channels' => 3,
  'mime' => 'image/jpeg',
)

木曜日, 9月 03, 2009

bashのプロンプトにIPアドレスを表示

sshでマシンを行ったり来たりしていると自分がどのマシンを操作しているのか分からなくなるので、 bashのプロンプトにIPアドレスを設定することにした。 IPアドレスはifconfigで取得し、環境変数に設定してからPS1に設定。

export IPADDR=`/sbin/ifconfig | /bin/grep 172.16 | /usr/bin/perl -nle '/172\.16\.\d+.\d+/ && print $&;'`
export PS1='[\u@$IPADDR \W]\$ '

NICが2つある場合は考慮していない。 IPアドレスは172.16.x.xに固定。