カスタム分類のrewrite

私的備忘録。

カスタム分類(Taxonomy)を登録する際、rewrite 引数をtrueにしたとき、has_archiveをtrueにしているにも関わらず、一覧が表示されないことがあった。あれこれ設定を調べてみても原因らしきものが分からなかった。

1日ほど、あれやこれや試した結果、どうやら、設定 => パーマリンク設定で、「変更を保存」を行わないとカスタム分類のrewriteが有効にならないことが判明。

もっと、厳密に調べてみると、wordpress api、flush_rewrite_rules関数をrewriteルールを変更した場合に最低一回コールしなければならない、らしい。

毎回コールする必要がないらしい?(実際のところ、面倒なのでソースを追ってないので理屈は分かりません) ので、設定・パーマリンク設定の変更を保存ボタンをクリックすることで、flush_rewrite_rules関数がコールされるのと同じことがされるみたい。

開発段階で、rewrite関係でおかしくなったら、パーマリンク設定で「変更を保存」で回避。

なんか、やっぱり本一冊買ってイチから勉強しなおした方が効率がいいかもしれない。。。

TortoiseSVN 1.8.0 でクライアント認証ができず・・・

Subversionが1.8にアップデートしたので、TortoiseSVN 1.8.0を何も考えずクライアントPCにインストールした。作業コピーに変更があったみたいで、作業コピーを片っ端からアップデートアップグレードした。

・・・結果、「TortoiseSVN 1.7.7でクライアント認証が失敗する」の二の舞を踏むことに・・・orz

インストールする時一抹の不安が過ぎったけど、後先考えず、「エイヤ!」ってな感じで。結局、やっぱり失敗。

一応サーバーはCentOS 5でApache 2.2.3 + オレオレ認証局のSSL環境。TortoiseSVN1.7.12を使っていたときはちゃんとクライアント認証のプロセスが通ったが、またしても1.8.0に上げたら今度は固まったまま。subversion自体がダメなのか、それともTortoiseSVNの部分がダメなのか、調べるだけの知識がないので、もうお手上げ。

検索してみたけど、やっぱりリリース直後なのでバージョン1.8の情報が出てこない。

結局、Apacheの設定で、SSLクライアント認証を解除して、ダイジェスト認証に切り替えることで、事なきを得た。

・・・が、Windows7上でTortoiseSVN1.8.0をインストールすると、ダイジェスト認証すらなんか怪しい挙動をする。作業コピーの更新をすると、ユーザー・パースワード入力ダイアログが出るのですが、正しいユーザー名・パスワードを入れてもエラーになる、あきらめてキャンセルすると、今度は違うダイアログ(Windows7の資格情報のダイアログ?)が出てくる。なんかワケ分からない。

ダメもとで何回もユーザー・パスワードの入力をトライしてみると、認証された。

よく分からん。

とにかく、元に戻そうかと・・・思ったけど、十数個ある作業コピーのチェックアウト作業がメンドクサイので、Apacheの設定をこのままにして、バージョンアップを待つことにする。

サーバーがオレオレSSLだからダメなのかなー・・・・とか、CentOS5のApacheのバージョンが低いのが原因なのかなー・・・とか思ったけど、確かめようがない。

この際だから、サーバー上のSubversionのバージョンを1.6系列から1.7系列最新の1.7.10にソースからビルドしてアップデートした。念のため、レポジトリのダンプをとったが、こちらは何ら問題なくバージョンアップ完了。さすがにサーバー上のsubversionを1.8.0にする気がしない。。。

テーマやテンプレートを動的に変更

私的記録です。

WordPressで、サイトの「お知らせ」というカスタム投稿タイプを作成した時のこと。

たとえば他のサイトからインラインフレームで読み込ませるときは、特定のテンプレートに変更したい、という場合、template_includeというフィルターが使える。トリガーとして、URLパラメータになにがしらのパラメータを渡したときに切り替えるようにすれば上手くいきます。

また、ある特定のURLパラメータをつけてアクセスしたときは、別のテーマで表示したい! という、それって何の意味があるの?的なこともしたかったので、纏めてプラグインにした。

チョー簡単(^^; WordPressってホントよく出来てますね~。

<?php
/*
Plugin Name: Switcher for Theme or Template
*/

/************************************************************
 動的にテーマやテンプレートを変える
 すっごい手抜きサンプル
************************************************************/
add_filter('template_include','DynaChange::Template');
add_filter('stylesheet', 'DynaChange::Theme');
add_filter('template', 'DynaChange::Theme');

class DynaChange
{
  public static function Template($template)
    {
      //URLパラメータにchtmp=プレフィックス があれば、
      //現在のテンプレートファイル名にプレフィックスを付けた
      //テンプレートファイルに切り替える。
      //適当サンプルのため、子テーマには対応していない。
      if(!empty($_GET['chtmp']))
        {
          $name = str_replace(STYLESHEETPATH . '/', '', $template);
          $template = STYLESHEETPATH . '/' . $_GET['chtmp'] .'-'. $name;
        }

      return $template;
    }

  public static function Theme($stylesheet)
    {
      //URLパラメータに chth=テーマ名 があれば、
      //そのテーマに切り替える。

      if(!empty($_GET['chth']))
        {
          $theme = wp_get_theme($_GET['chth']);
          if($theme->exists())
            $stylesheet = $theme->Template;
        }
      return $stylesheet;
    }
}
?>

説明要らないっすね~。

Vista以降では安易にスレッドを作るな!?

■2021年8月3日
gistにコードを移すとき、コピペした時に文字化けしてたところとか io_completion_port_xp.cpp/io_completion_port_vista.cppを諸々修正


LinuxやBSDなどのUNIX互換のOSと違って、Windowsではスレッドを起こすのは普通に行われてることだと思います。で、スレッドを起こすには、CreateThread API もしくは、Cランタイムライブラリの_beginthreadex関数を使うことになります。

が、一方でスレッドを生成するのではなく、スレッドプールを利用する、というケースもあり、パフォーマンス的な事を考えれば、むしろこちらの方が多いかもしれません。

Windows 2000/XPなどのNT5.x系では、QueueUserWorkItem APIというスレッドプールに関するAPIが使えます。。。けど、はっきりいって、このAPI、よほど簡単なロジックでないと使えません。いったんこのAPIでキューに入れてしまうと、もう手が出ません。外からキャンセルできないし、強制終了させようとしてもTerminateThread APIは使っちゃだめ!ですし・・・。
結局、ちょっと凝ったことさせようと思ったら、自前でI/O完了ポートを駆使してスレッドプールを実装する他なかったと思います。

しかし、Windows Vista以降のNT6.x系のWindowsでは、より進化したスレッドプールAPIが追加されています。もはや、Vista以降のWindowsで、CreateThreadや_beginthreadex関数を使ってスレッドを起こすコーディングはダサイといわざる得ません(^^;;;

というか、CPUがデュアルコアは当たり前、マルチコアがデフォルトってな状況の中で、これからはメニーコアだ! っていう時代なので、アプリケーション開発者側が、コア数のことまで考えて組む・・・とかもう無理!そんなのは限られたスーパープログラマーしかできんわ(笑) ってことです。

だから、CreateThread APIや_beginthreadex関数でスレッドを起こす前提のロジックでコーディングしちゃだめ。ってことに。

ただ・・・スレッドを作ってそこにウィンドウを作成する、というようなケースには向きません。とどのつまり、プロセス開始から終了まで生存するようなスレッドの場合、スレッドプールに処理を投げる意味はありません。あくまで、一つのスレッドの生成・削除が頻繁に行われるケースや、スレッドの生存期間が短いケース等でスレッドプールの恩恵を受けることができると思います。

ま、今更ですが(^^;;; この新たに追加されたスレッドプールなAPI群は、スレッドの生成と管理をすべてWindowsが肩代わりしてマシンに積まれているCPUの数(コア数?)と負荷状態に応じて最適な性能を発揮できるようになっているようです(・・・なっているはずです)。

例えば、ちょっとしたユーティリティアプリなんかで、単純な処理を非同期(並行)処理させる場合、TrySubmitThreadpoolCallbackもしくは、CreateThreadpoolWork/SubmitThreadpoolWorkでほとんど事足りると思います。

CreateThreadや_beginthreadexのあの引数の多さにうんざりすることが無くなり、スレッドハンドルを管理するコード、同期のためにイベントオブジェクトを作成して待機するようなコード諸々を実装する手間が大幅に軽減されます。ヒャッホーーー!

当然ですが、上記はXPでは実行できません。

他にも、タイマーオブジェクトを利用した関数の繰り返し処理、jscriptでいうところのsetTimeout / setIntervalメソッドみたいな、一定時間毎にコールバック関数を実行してくれるCreateThreadpoolTimer APIや、カーネルオブジェクトがシグナル状態になったらコールバック関数を実行してくれる CreateThreadpoolWait API、ReadFile/WriteFileなどのI/O非同期処理に利用できるCreateThreadpoolIo API。

一連のスレッドプールに関するAPIは非常に強力で、使い勝手もいい。デフォルトのスレッドプールの動作が気に入らなければ、カスタマイズしたスレッドプールを利用することもできる。

自分的に便利だと思ったのが、ReadFIle/WriteFileでI/O非同期処理に利用できる、CreateThreadpoolIo/StartThreadpoolIo。
今まではI/O完了ポートで通知を受け取って・・・というようなコードを書いてましたが、Vista以降のOSに限定すれば、これらのスレッドプールAPIを使うことでコード量が減ります。

ReadDirectoryChangesW APIを使ったディレクトリへの変更を監視するコードをスレッドプールを使ったコードに強引にリプレースしてみました。

まずは、昔作った、WindowsXPで動作する、IO完了ポートとワーカースレッドを単純に作って利用したバージョン。

要点は、スレッドを作成して監視が終了するまで待機。ReadDirectoryChangeW APIの非同期処理が完了するとIO完了ポートのキューにI/O完了パケットが追加され、ワーカースレッドのGetQueuedCompletionStatus APIが制御を戻すことでReadDirectoryChangeW APIの処理結果のデータを得て、再びReadDirectoryChangeW APIをコールし非同期処理を継続します。

続いて、上記をVista以降のスレッドプールのAPIを利用したバージョン。

あまり違いがないように思いますが、スレッドを何個作るべき?だとか細々とした調整などが不要になり、何より_beginthread関数などのプリミティブなAPIを使わなくても良くなりました。以前なら、スレッド処理をラップする、なんらかのクラスライブラリが必須だったと思いますが、ちょっとしたツールを書くときはこれらの新しいスレッドプールなAPIを使えば良くなりました。

ま、ちょっとしたツールを作るにはC#を使えば済む話で、わざわざC++を使う必要性があるとは思えませんが・・・。ま、要するに自己満です(^^;;;