« 万能インポート | ホーム | JavaScript でのクラス定義の一例 »

2010年2月10日

懐かしの CGI カウンターとか

とても久しぶりに Perl で CGI カウンターを書いてみた。

申し訳程度にファイルの排他処理も組み込んでみたけど、完璧とはいえない排他処理ならなくてもいいんじゃないかという気がしないでもない。

#!/usr/bin/perl
# カウンターのサンプル

use strict;
use warnings;

use Time::HiRes qw(sleep);

my $count_file = './count.dat';

main();

sub lock_file {
    my $fname = shift;
    my $lock_dir = "$fname.lock";

    # ロックが 10 秒以上前なら強制解除
    if (-e $lock_dir && (stat _)[9] + 10 < time()) {
        # 削除失敗でロックディレクトリが残ってたら失敗
        (! rmdir $lock_dir or ! -e $lock_dir) or die "Cannot remove dir $lock_dir: $!";
    }

    # 3 回リトライする
    my $cnt = 0;
    while ($cnt++ < 3) {
        mkdir $lock_dir, 700 and return 1;
        sleep(0.1);
    }

    return;
}

sub unlock_file {
    my $fname = shift;
    my $lock_dir = "$fname.lock";

    if (! rmdir $lock_dir && -e $lock_dir) {
        die "Cannot remove dir $lock_dir: $!";
    }
    return;
}

sub main {
    # ファイルのロックを試みる
    lock_file($count_file) or die "Cannot lock file $count_file";

    my $fh;
    my $val;
    if (open $fh, '+<', $count_file) {
        $val = do { local $/; <$fh> };
        ++$val;
        seek $fh, 0, 0;
    }
    else {
        # ファイルがなければ新規作成
        open $fh, '>', $count_file
            or die "Cannot open file $count_file: $!";
        $val = 1;
    }

    print {$fh} $val;
    close $fh;

    # JSON 形式で返す
    print qq/"{"result":"OK","count":$val}"/;

    unlock_file($count_file);
}

トラックバック(0)

トラックバックURL: http://archive.guma.jp/mt/mt-tb.cgi/15

コメントする

OpenID対応しています OpenIDについて

このブログ記事について

このページは、Mocelが2010年2月10日 23:27に書いたブログ記事です。

ひとつ前のブログ記事は「万能インポート」です。

次のブログ記事は「JavaScript でのクラス定義の一例」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。