cygwin で nice

nice / renice を使うと起動するプロセスや起動済のプロセスの優先度を変更することができます。
 
nice の書式:

nice [-n 数値 ] 実行するコマンド [引数] ..

例:

$ nice -n 10 sleep 100 # nice 10 sleep 100 は間違い

 
renice: の書式:

renice 数値 [ [-p] PID ] [ [-g] pgrps] [ [-u] ユーザ]

指定した PID (またはプロセスグループ(PGID)、ユーザ)のプロセスの優先度を指定した数値に基づいて変更します。
Cygwin で実行する場合、PID にはWindows 上の実 PID (WINPID)ではなく、Cygwin で ps すると見られる仮想 PID を指定します。
 
例1: PID で指定

$ sleep 50 &
[1] 1448
$ renice 10 -p 1448

例2: PGID で指定

$ ps
      PID PPID PGID WINPID TTY UID STIME COMMAND
     2264 2248 2264 316 con 11363 13:31:29 /usr/bin/sleep
     2168 2248 2168 2168 con 11363 13:31:33 /usr/bin/bash
     2948 2168 2168 2920 con 11363 13:31:33 /usr/bin/sleep
$ renice 19 -g 2168 # PGID が 2168 の全てのプロセスが対象

例3: ユーザ名で指定( cygwin 経由で起動しているプロセスのうち実行ユーザが john のプロセス全ての優先度を -10 (通常以上)にする)

$ renice -10 -u john

 
Windows XP で実行した場合のプロセス優先度の対応表:

nice -n

プロセス優先度

12以上

4 〜 11

通常以下

-4 〜 3

通常

-12 〜 -5

通常以上

-19 〜-13

-20 以下

リアルタイム

参考:
起動するプログラムの優先度を変更する方法(@IT)
タスクマネージャを使った変更方法と、cmd.exe の start コマンドを使った優先度指定方法についてかかれています。

文字列への文字単位のアクセスで波括弧が非推奨にかわった

ふと PHP のドキュメントを眺めていたら、次のように書かれていました
PHP: 文字列(English)

注意: $str{42} のように波括弧を使用してアクセスすることも可能です。 しかし、角括弧を使用する方法のほうが推奨されます。 なぜなら、{波括弧} 形式は PHP 6 で廃止される予定だからです。
 
Note: They may also be accessed using braces like $str{42} for the same purpose. However, using square array-brackets is preferred because the {braces} style is deprecated as of PHP 6.

PHP5 リリース前は

$str = “foo”; echo $str[0];

が非推奨で

$str = “foo”; echo $str{0};

が推奨されていましたが、方針転換をしたようです。
 
参考:
2004 年 3 月のマニュアル同項(English)(archive.org)

波括弧の後に任意の文字をゼロから始まるオフセットで指定することに より、文字列内の文字にアクセスすることが可能です。
 
    注意: 過去の互換性のため、配列括弧を使用することが可能です。しかし、 この構文はPHP 4に依存しています。
    
 Characters within strings may be accessed and modified by specifying the zero-based offset of the desired character after the string in curly braces.
  
    Note: For backwards compatibility, you can still use array-braces for the same purpose. However, this syntax is deprecated as of PHP 4.

以前はこうなっていました。

最新版の ffmpeg をダウンロードするには

ffmpeg とは、高機能な動画編集ツールです。

以前、この ffmpeg アプリのWindows版を探し回った事があったため、配布サイトをまとめてみました。
 
ffmpeg.org
公式サイト。
 
Windows用のffmpegコンパイル済バイナリは以下のサイトで配布されています。

ffmpeg 公式 Windows バイナリダウンロードページ:

https://ffmpeg.zeranoe.com/builds/

ダウンロードは、リンク先のボタンを押すだけです。

バージョンが古い可能性があるのであまりおすすめはしませんが、他にもフリーソフトに付属しているものを使うこともできます。
お気に入りの動画を携帯で見よう
SVN の HEAD を追いかけて Windows 用にビルドしたバイナリを配布しているサイト。
MingW での ffmpeg のビルド方法や依存するライブラリについても書かれています。
 
ImageMagick
ImageMagick は一部のビデオフォーマットを扱うために ffmpeg を使っているため、ffmpeg.exe をバンドルしています。
Windowsユーザでインストーラが不要な方はImageMagickのFTPサーバから、実行ファイルだけのダウンロードもできます。ファイル名が”ImageMagick-(バージョン番号)-Q16-windows.zip”のものがインストーラなし版です。
 
携帯動画変換君
ffmpegのインターフェイスとして動作するソフトです。ffmpeg が同梱されていますが、2010年9月現在、何年も更新されていないためバージョンは古めの様子。
 


Linux用 RPM は http://packages.sw.be/ffmpeg/ で最新版が順次配布されているようです。

バグパターン – switch のデータ型は複数種類にすると予期しない結果になる

まずはサンプルコードを見て、結果を予想してみてください。

<?php
$result = true;
switch($result){
  case “error”: // エラー
    echo “failure”;
    exit;
  case “ok”: // 成功
  case true: //
    echo “success”;
    exit;
  default:
    echo “unexpected”;
    exit;
}
?>

一見、このコードを実行すると success が出力されるように思いますが、実際に実行してみると意外なことに failure が出力されてしまいます。
PHP の switch 文は、switch の引数と case で指定した値とを= ではなく) でチェックしているため、switch 引数が複数の種類の型になる場合は型変換などにより予想外の値と一致することになってしまうのが原因です。
 
実際どの値が何と一致するかについては以下の検証コードを実行してみると分かります。

// 検証コード:
<?php
// values to test
$targets = array(
   0,
   1,
   true,
   false,
   null,
   “”,
   “0.00e5”,
   “10f”,
   “0f”,
   array(),
   array(1),
   array(“key”=>”foo”),
);
 
// —-
foreach($targets as $target){
  if(is_bool($target))
      $s = $target? “true”: “false”;
  elseif(is_null($target))
      $s = “null”;
  elseif(is_string($target))
      $s = “‘{$target}'”;
  else
      $s = $target;
  echo $s .”(“.gettype($target).”)”.”:\t”;
  switch($target){ //”0.00e5″
    case ‘a’: echo “case a”; break;
    case ‘b’: echo “case b”; break;
    case ‘0’: echo “case zero”; break;
    case 10: echo “case int 10”; break;
    case 0: echo “case int 0”; break;
    default: echo “default”; break;
  }
  echo “\n”;
}

php 4.4.6 および php 5.2.3 で試したところ、実行結果次のようになりました。

0(integer): case a
1(integer): default
true(boolean): case a
false(boolean): case zero
null(NULL): case int 0
”(string): case int 0
‘0.00e5′(string): case zero
’10f'(string): case int 10
‘0f'(string): case int 0
Array(array): default
Array(array): default
Array(array): default

同じ empty 値でも 0, null, false, “” で結果が全く異なってしまいました。
また、 == について挙げられる数値文字列の比較時の問題(“0.00e5” == “0” が真になる,など)の影響も受けてしまっています。
 
この問題は、型チェックを厳密にしたり、strval(), intval() などで明示的に文字列,数値キャストを行い、switch 文の引数の型が一種類になることを保証することである程度回避できます。
しかし依然として数値として有効な文字列同士の比較の問題があるため、数値を含む文字列について正確さが必要な場合や、本当に複数型を判別させたい場合は= 演算子を使い if – elseif – else を使うほうが賢明でしょう。

if($result = true || $result= “ok”){
  echo “success”;
}elseif(empty($result) || $result
= “error”){
  // empty($result) は以下の式と等価。
  // ( !isset($result) || ($result= false || $result = null ||
  // $result= “” || $result = 0 )
  echo “failure”;
}else{
  echo “unexpected”;
}

 
参考:
switch 構文(php.net)
比較演算子(php.net)
strval()(php.net)

SQL の JOIN の種類と違いまとめ — INNER/LEFT/RIGHT/FULL/CROSS

(2026年7月、内容を全面的に更新)

SQL でテーブルを結合する JOIN には、INNER JOIN・LEFT OUTER JOIN・RIGHT OUTER JOIN・FULL OUTER JOIN・CROSS JOIN の5種類があります。違いは一言でいえば「結合相手が見つからなかった行をどう扱うか」です。INNER は捨てます。LEFT/RIGHT/FULL は残して NULL で埋めます。CROSS はそもそも条件を付けず、全組み合わせを作ります。

答えとしてはこれで全部です。ただ、この一言だけを頼りに書いた SQL は、たいてい「思ったより行が少ない」「NULL の行はどこへ消えた」という形でつまずきます。そこでこの記事では、結合相手のいない行をわざと混ぜたサンプルデータに5種類の JOIN を順にかけて、結果がどう変わるかを目で確認していきます。あわせて結合条件の書き方(ON/USING/NATURAL)の違い、複数 JOIN の評価順、データベースごとの対応差(MySQL に FULL OUTER JOIN がない、など)もまとめます。

続きを読む SQL の JOIN の種類と違いまとめ — INNER/LEFT/RIGHT/FULL/CROSS

テーブルのディスク使用量を取得する

SELECT relname, relfilenode, relpages FROM pg_class;

relname がテーブル名、relfilenode が実体ファイル名、 relpages が利用しているページ数概算。1ページは通常 8KB です。
 

SELECT c2.relname, c2.relpages
    FROM pg_class c, pg_class c2, pg_index i
    WHERE c.oid = i.indrelid
        AND c2.oid = i.indexrelid
    ORDER BY relpages DESC;

同様にインデックスの利用しているページ数を取得します。
 
参考:
ディスク使用量の監視(PostgreSQL 8.2.5 公式マニュアル)
pg_class(同上)

アクセス中のファイルに対する他のプロセスでのファイル読み書き禁止を制御する

.NET, C++ ともに FileStream 等でのファイルアクセス時に FileShare という列挙体のメンバを追加で指定することでロック制御することができます。
 
http://msdn2.microsoft.com/ja-jp/library/system.io.fileshare(VS.80).aspx より引用:

FileShare 列挙体のメンバ
 
Delete:
  後続のファイルの削除を許可します。
Inheritable:
  ファイル ハンドルを子プロセスで継承できるようにします。Win32 では、直接サポートされません。
None:
  現在のファイルの共有を解除します。ファイルを閉じるまで、このプロセスまたは別のプロセスがファイルを開く要求をしても失敗します。
Read:
  後続の読み取り用のファイルを開くことを許可します。このフラグが指定されていない場合は、ファイルを閉じるまで、このプロセスまたは別のプロセスが読み取り用のファイルを開く要求をしても失敗します。ただし、このフラグが指定されていても、ファイルにアクセスするために追加のアクセス許可が必要になることがあります。
ReadWrite:
  後続の読み取り用または書き込み用のファイルを開くことを許可します。このフラグが指定されていない場合は、ファイルを閉じるまで、このプロセスまたは別のプロセスが読み取り用または書き込み用のファイルを開く要求をしても失敗します。ただし、このフラグが指定されていても、ファイルにアクセスするために追加のアクセス許可が必要になることがあります。
Write:
  後続の書き込み用のファイルを開くことを許可します。このフラグが指定されていない場合は、ファイルを閉じるまで、このプロセスまたは別のプロセスが書き込み用のファイルを開く要求をしても失敗します。ただし、このフラグが指定されていても、ファイルにアクセスするために追加のアクセス許可が必要になることがあります。

参考:
FileShare 列挙体(System.IO)
開くファイルへの他のプロセスからのアクセスを制限する(dobon.net)

ひこにゃんに学ぶ著作権

今朝ニュースを見ていたら、第二のおふくろさん騒動ともいえるニュースが流れていました。
 
ひこにゃんピンチ!…作者、彦根市に使用中止求める(YOMIURI ONLINE) より引用:

もへろんさん(22)が「適正なキャラクター管理を怠った」などとして、市と同祭実行委員会に祭終了後の使用中止を求める調停を彦根簡裁に申し立てたが、市は9日、ひこにゃんを今後も市のマスコットとして使用すると発表した。
 
 実行委は祭のキャラクターとして2006年1月、もへろんさんが応募したネコをモチーフにした3種類の図柄を採用。実行委が許可した団体の出版物などへの利用を許可してきた。
 
 しかし、申立書によると、実行委は「お肉が好物」「特技はひこにゃんじゃんけん」など作者の意図しないひこにゃんの性格づけをしたと主張。粗悪品が出回りかねないのに無制限に使用を承認しているなどとしている。

 
財産権である著作権を持つ彦根市に対して、作者のもへろん氏が著作者人格権のうちの同一性保持権を行使している形ですね。
 
著作権は譲渡可能ですが、著作者人格権は Wikipedia の言葉を借りると「一身専属性を有する権利であるため他人に譲渡できない」権利であるとされているため、勝手な性質の追加に対して異義を唱える事は妥当である、と思います。
 
しかし、前述の記事のように「祭終了後の使用中止を求め」たり、スポニチアネックスの記事にあるように、営利目的の利用や対して「相当額の支払いを求め」たりということまで要求できるかは、祭以外の利用や営利目的の利用が、著作者の名誉声望を害するかは微妙なところではないでしょうか。
 
今回の事例が教えてくれることは、クリエイター、デザイナー、エンジニアなど個人と企業の間での契約では、個人が作成した成果物の著作権は企業が所有する、という契約が多いと思いますが、この契約上でも個人が著作物に対して著作者人格権を行使することができるということです。
 
 ちなみに、プログラムについては「特定のコンピュータで利用できるようにしたり、より効果的に利用し得るようにするために必要な改変(Wikipedia)」であれば同一性保持権でいう改変にはあたりません。
 
とりあえず彦根市の問題については、ひこにゃんは個人的にも好きなキャラクターですし、町興し成功の好例なので、当事者間でうまく話がまとまるといいなと思っています。
参考:
著作権法(Wikipedia)
著作者人格権

サンプルコード – Cache_Lite のファクトリメソッド(マルチユーザ対応)

Cache_Lite は大変便利なのですが、Linux/BSD などで、複数実行ユーザが同じ cacheDir (たとえば /tmp/ )を使った場合に、他ユーザが作ったキャッシュへのアクセス権限が得られないため正しく動作しません。
Cache_Lite の hashedDirectoryUmask オプションと umask() 関数で 0777 を指定すれば十分な権限が得られますが、キャッシュの盗聴やかいざんの可能性が出てくるためセキュリティ的によろしくありません。
 
簡単な対応として思い付くのは

‘cacheDir’ => ‘~/tmp’,

のようにユーザのホームディレクトリにフォルダを分けてやることですが、
今回はより汎用的にするため、ファクトリメソッド内部でユーザ判別をしてフォルダを分けることでマルチユーザ対応させてみました。
 
# 暫定的な実装なので、不備があるかもしれません。

// This source is made available under the terms of the BSD license.
 
/**
 * Cache_Lite 用汎用ファクトリメソッド。
 * (PHP 4, 5 対応)
 * @version 2007-11-08
 */
class CacheLiteFactory {
  /**
   * @access private
   */
  function CacheLiteFactory(){
      // no-op
  }
  /**
   * static.
   * @access private
   * @param array $newOptions
   * @return options
   */
  function _defaultOptions($newOptions = null){
     // 初期デフォルト設定
     static $defaultOptions = array(
         // 必要なら設定可。
      );
      if(!empty($newOptions)){
          $defaultOptions = $newOptions;
      }
      return $defaultOptions;
  }
  
   /**
    * インスタンス化に使うデフォルトのオプションを設定します。
    * 過去に設定していたオプションは全て消去されます。
    * 一部のオプションのみ追加、変更したい場合は getDefaultOption() で現在のデフォルトオプションを取得して再設定してください。
    *
    * static
    * @access public
    * @param array $newOptions 置き換えるオプション
    * @return void
    */
   function setDefaultOptions($newOptions){
      CacheLiteFactory::_defaultOptions($newOptions);
   }
   
   /**
    * インスタンス化に使われるデフォルトのオプションを取得します。
    * static
    * @access public
    * @return array 現在設定されているデフォルトのオプション
    */
   function getDefaultOptions(){
      return CacheLiteFactory::_defaultOptions();
   }
  
  /**
   * Cache_Lite インスタンスを取得する。
   * 引数を指定した場合、デフォルトオプションをベースに引数のオプションを追加,変更します。
   *
   * static
   * @access public
   * @param array $overrideOptions 上書きするオプションの連想配列
   * @return Cache_Lite
   */
   function factory($overrideOptions = array()){
       require_once “Cache/Lite.php”;
       // デフォルト値。
       $options = CacheLiteFactory::getDefaultOptions();
       
       if($overrideOptions && is_array($overrideOptions)){
            $options = array_merge($options, $overrideOptions);
       }
       if(empty($options[‘cacheDir’])){
           $options[‘cacheDir’] = “/tmp/”;
       }
        
       // 他ユーザのキャッシュはアクセス権限が十分にない(umask 0777 にしても削除はできない)ので
       // posix_getuid() で uid が取得できる場合はユーザごとにフォルダを分けるようにしておく。
      // ※ Windows 環境または –disable-posix オプション付きでビルドした場合は取得できないことに留意
       if(function_exists(“posix_getuid”)){
           if(@mkdir($options[‘cacheDir’], 0777)){ // PHP4 互換のため recursive なし
               @chmod($options[‘cacheDir’], 0777);
           }
           $options[‘cacheDir’].=”cache_uid_”.posix_getuid().DIRECTORY_SEPARATOR;
       }
       @mkdir($options[‘cacheDir’]); // PHP4 互換のため recursive はなし
       return new Cache_Lite($options);
    }
}

 

// 用例
/* —
  // デフォルトを与えるかは任意
CacheLiteFactory::setDefaultOptions(array(
    // ‘cacheDir’=>’/path/to/tmp/’,
    ‘lifeTime’ => 24 * 60 * 60, // set 1 day by default
    ‘hashedDirectoryLevel’ => 1,
    ‘automaticCleaningFactor’=>100,
  ));
— */
 
$cache = CacheLiteFactory::factory();
$value = $cache->get(“foo”);
if($value === false){
  $value = date(‘Y/m/d H:i:s’);
  $cache->save($value);
}
echo $value . “\n”;