[PHP-users 10953] Re: Flockについて

Yoshi php-users@php.gr.jp
Sat, 19 Oct 2002 01:34:26 -0700


すみません。
$modeを書きわすれました。
$modeは"w"をつかってます。
これはもんだいなんでしょうか?


wlockout()の方は実際の書き込みには関係ないので
説明しませんでした。すみませんでした。
wlockout()はあまりに消えるので、困り果てたあげくに
制作した自作のFunctionで、基本的には操作中の(書き込み中の)
ファイル名を「操作中ファイル」として別のDrictoryに書き込み、
別の書き込み命令が操作中のファイルに来たときに、
そのファイルが操作中の場合操作を待機するためのものです。
一応下につけておきますが、基本的には関係ないと思います。


//実際は下のfile_write()を書き込みに使ってます。
//書き込みの時にflockの補助としてwlockin ()を一応適応してます。(下を参照)

  function file_write( $FileName , $DATA , $mode ){

   if( $lockid = wlockin ( $FileName ) ){ //ファイルロック(自作)

    if($fp = @fopen ( $FileName , "$mode")){

     if(flock( $fp , LOCK_EX )){ //flock

      fputs ($fp , $DATA );

      fflush ( $fp );

      flock ( $fp , LOCK_UN ); //flock

      fclose ($fp);

     }

    }

    wlockout( $lockid );//ファイルロック開放(自作)

    return 1;

   }

  }





<?



/*
  //使用例
  $PATH_TO_LOCK_FILE = "./lockdir"; //ロックファイルを書きこむデイレクトリー

  $LockTarget = "log file"; //ロックをかけたいログファイル名

  $lockid = wlockin ( $LockTarget );//ファイルのロック

  wlockout( $lockid );//ロック開放
*/





 // wlockin ( $LOCK_DIR_PATH , $LockTarget )
 //ファイルをロックする関数。Lockに成功した場合Lock IDを返します。

//==========================================================================
======================
  function wlockin ( $LockTarget ){

   $PATH_TO_LOCK_ROOT_LAYER = "/home/wlock_root"; //ここでPathを指定

   $timestamp = time(); //Get timestamp for lock file

   $NewLockID = md5 ( uniqid (rand())); // Make uniq id for lock file

   exec ( "echo $LockTarget > $PATH_TO_LOCK_ROOT_LAYER/$NewLockID" );
//Traget filename をいれたLock fileを制作

   touch ( "$PATH_TO_LOCK_ROOT_LAYER/$NewLockID" , $timestamp );//Lock file
のタイムスタンプを合わせる

   while( !$lockid = _wlockin( "$PATH_TO_LOCK_ROOT_LAYER" , $NewLockID ,
$timestamp , $LockTarget ) ){ //ファイルLock

    srand((double)microtime()*1000000);

    $rand = rand( 0 , 1000 );

    usleep( $rand );

    if( !file_exists ("$PATH_TO_LOCK_ROOT_LAYER/$NewLockID" ) ){
     return 0;
    }


   }

   return $lockid;

  }

//==========================================================================
======================



 // _wlockin ( $PATH_TO_LOCK_ROOT_LAYER , $NewLockID , $NewFileTime ,
$LockTarget )
 //ファイルロックを実際に行う関数。先に作られたファイルをチェックする。

//==========================================================================
======================
  function _wlockin ( $PATH_TO_LOCK_ROOT_LAYER , $NewLockID , $NewFileTime ,
$LockTarget ){

   $handle = opendir($PATH_TO_LOCK_ROOT_LAYER);

   $OrderArray[0] = $NewLockID;

   while ( $LockedFile = readdir( $handle ) ) {

    if( "." != trim($LockedFile) && ".." != trim($LockedFile) ) { //[.][..]
を排除

     $LockedFileTime = filemtime ( "$PATH_TO_LOCK_ROOT_LAYER/$LockedFile" );
//Get file time

     if( $LockedFileTime <= $NewFileTime ){ //NewLockIDと同じかより前のFile
があれば比較

      if( trim( exec("cat $PATH_TO_LOCK_ROOT_LAYER/$LockedFile") ) ==
$LockTarget ) {

       if( $LockedFileTime == $NewFileTime ){

        $OrderArray[1] = $LockedFile;

        sort ($OrderArray); //FileTimeが同じ場合sortして一つ返す

        return $rtn =  ( $NewLockID == $OrderArray[0] ) ? $NewLockID : 0;

       }else{

        return 0; //NewLockIDより小さいFileTimeあれば偽を返す

       }

      }

     }

    }

   }
   closedir($handle);
   return $NewLockID;
  }

//==========================================================================
======================



 //wlockout( $PATH_TO_LOCK_ROOT_LAYER , $lockid )
 //ファイルロックを開放する関数

//==========================================================================
======================
  function wlockout( $lockid ){

   $PATH_TO_LOCK_ROOT_LAYER = "/home/wlock_root"; //ここでPathを指定

   unlink ( "$PATH_TO_LOCK_ROOT_LAYER/$lockid");

  }

//==========================================================================
======================



 //wlock_clean( $PATH_TO_LOCK_ROOT_LAYER , 30 )
 //ゴーストロックファイル消去関数(クローンから呼び出し)

//==========================================================================
======================
  function wlock_clean( $LockTimeLimit){

   $PATH_TO_LOCK_ROOT_LAYER = "/home/wlock_root"; //ここでPathを指定

   $handle = opendir($PATH_TO_LOCK_ROOT_LAYER);

   $timestamp = time();

   while ( $LockFile = readdir( $handle ) ) {

    if( "." != trim($LockFile) && ".." != trim($LockFile) ) { //[.][..]を排
除

     $LockFileTime = filemtime ( "$PATH_TO_LOCK_ROOT_LAYER/$LockFile" );
//Get file time

     if( $LockFileTime <= $timestamp - $LockTimeLimit ){ //$LockTimeLimit秒
前のファイルは全て消去

      unlink ( "$PATH_TO_LOCK_ROOT_LAYER/$LockFile");

     }

    }

   }

   closedir($handle);

  }

//==========================================================================
======================





?>


----- Original Message -----
From: "WADA Masashi" <wada@hh.iij4u.or.jp>
To: <php-users@php.gr.jp>
Sent: Friday, October 18, 2002 8:28 PM
Subject: [PHP-users 10950] Re: Flockについて


>
>  和田です。
>
>  私も以前 flock() について、本 ML に質問させてもらったことがあ
> ります。
>
> Yoshi wrote:
> >問題のファイル参照時はこんな感じのFUNCTIONを使ってます。
> >あと、wlockinはあまりに消えるんで、自分でもう一つファイルを
> >作ってLOCKをする関数を作って適応してます。
> >(これは実際の書き込みはしないので、気にしないで下さい)
>
>  肝心のwlockin()とwlockout()の中身が紹介されていないので、根本
> 的な原因は推測しかできませんけど・・・。
>
> >    if($fp = @fopen ( $FileName , "$mode")){
> >
> >     if(flock( $fp , LOCK_EX )){ //flock
>
>  $mode には何を指定していますか? "w"だったりすると、まずいこ
> とが起きる可能性があります。
>
>  [PHP-jp 10324] flockの不具合?
>
> から始まるスレッドを参照してください。
>
>  まずは、ファイルロックが競合する状況を起こりやすくさせるテスト
> スクリプトを書いて、確実な検証を行っておいた方がいいですね。
>
>
> ----
> 和田雅志 (WADA Masashi)
> wada@hh.iij4u.or.jp
> _______________________________________________
> PHP-users mailing list
> PHP-users@php.gr.jp
> http://ns1.php.gr.jp/mailman/listinfo/php-users