APTのSEGVが瞬時に直された

=== modified file 'apt-pkg/acquire-item.cc'
--- apt-pkg/acquire-item.cc     2011-03-14 15:27:24 +0000
+++ apt-pkg/acquire-item.cc     2011-04-02 19:00:45 +0000
@@ -841,7 +841,7 @@
    if (ShortDesc().find("Translation") != 0)
       msg += "\nFail-Ignore: true";
    struct stat Buf;
-   if (stat(Final.c_str(),&Buf) != 0)
+   if (stat(Final.c_str(),&Buf) == 0)
       msg += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);

    return msg;

まさかIA-64関係なく,全アーキで腐ってたとは思わなかった.Debian testing AMD64のこのPCでは何事もなく動いてるんですが.

// AcqIndex::Custom600Headers - Insert custom request headers		/*{{{*/
// ---------------------------------------------------------------------
/* The only header we use is the last-modified header. */
string pkgAcqIndex::Custom600Headers()
{
   string Final = _config->FindDir("Dir::State::lists");
   Final += URItoFileName(RealURI);
   if (_config->FindB("Acquire::GzipIndexes",false))
      Final += ".gz";
   
   string msg = "\nIndex-File: true";
   // FIXME: this really should use "IndexTarget::IsOptional()" but that
   //        seems to be difficult without breaking ABI
   if (ShortDesc().find("Translation") != 0)
      msg += "\nFail-Ignore: true";
   struct stat Buf;
   if (stat(Final.c_str(),&Buf) == 0)
      msg += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
   return msg;
}
 // TimeRFC1123 - Convert a time_t into RFC1123 format.  .       .       /*{{{*/
 // ---------------------------------------------------------------------
 /* This converts a time_t into a string time representation that is
    year 2000 complient and timezone neutral */
 string TimeRFC1123(time_t Date)
 {
    struct tm Conv = *gmtime(&Date);
    char Buf[300];
 
    const char *Day[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
    const char *Month[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul",
                           "Aug","Sep","Oct","Nov","Dec"};
 
    sprintf(Buf,"%s, %02i %s %i %02i:%02i:%02i GMT",Day[Conv.tm_wday],
            Conv.tm_mday,Month[Conv.tm_mon],Conv.tm_year+1900,Conv.tm_hour,
            Conv.tm_min,Conv.tm_sec);
    return Buf;
 }

うーん, struct stat をstack上に取った後,中身を stat(2) が更新しないままで(stat(2) の成功を調べる条件が逆だった), time_t st_mtime のゴミを参照してた訳だが,だからってSEGVるもんだろうか?
ともあれ,これでしばらく待てばtestingに降りてくるから,普通に aptitude update できるようになる.

DeleGateのパラメタ EXPIRE を完全に誤解してた

... で,肝心の common.conf.txt の設定は

# DeleGate config. file
-P8080
SERVER=http-sp
CACHE=do
EXPIRE=7d
-P80
SERVER=http
CACHE=do
EXPIRE=100d
ADMIN=nodakai@gmail.com
# AUTH="admin::root:root"

とりあえずこれで目的は達成された.

これは EXPIRE が長過ぎる.(APT-HTTP でなく wget(1) 等の単純なクライアント((いや,wget(1) だと -N というオプションで,サーバの応答の Last-Modified と,ダウンロード済みファイルのタイムスタンプを自分で比べてダウンロードを省く機能が一応あるんだけどね... 余り使われてないと思う. http://www.bookshelf.jp/texi/wget/wget-ja_5.html GNU Wget 1.9 Manual: タイムスタンプ))だと) http://ftp.jp.debian.org/debian/dists/testing/InRelease 等の超重要なファイルが数か月前の日付で 200 OK されるという惨事を招いていた.
EXPIRE はこういう役目かな:

  • If-Modified-Sinceトラヒックすらもったいないとき,DeleGateが自分のキャッシュを探して見つかった日付が EXPIRE 以内ならサーバに問い合わせることなく 200 OK する
    • ただし Cache-Control とかが付いてれば尊重するようだ
  • Last-Modified とかを何も返さない超いい加減なサーバ (CGI?) の応答を,強制的にDeleGateにキャッシュさせる際の失効時間
    • DeleGate は超多数のプロトコルに対応しており,HTTPで発達したキャッシュ制御が通じないものも含まれるだろうから,こういうアドホックなものが要るのだろう

私がDeleGateを使うのは「DebianのAPTやFedoraYumのパッケージ取得を手元の(USB接続)HDDにキャッシュして,インストール遊びを何度も繰り返すときに作業効率を上げたい」ためだった.普段Linuxで使ってる実験用鯖に入れるのがLinux等だから,手持ちのまともに動く少ないPCのうち残りはWindows XPなLet'snoteで,だからcaching proxyはWindowsで動いてほしい.よってメジャー度とWindows版の扱いの楽さを勘案してDeleGateに落ち着いた.
この限定された用途だと EXPIRE=1d 位の,そこそこ短い閾値が良い.DeleGateが見つけた手元キャッシュが EXPIRE より古かったとき, ftp.jp.debian.org にはちゃんと If-Modified-Since <キャッシュの日付> を送り, 304 NOT MODIFIED だったらクライアントには(ほぼ透過的に)200 OK で実ファイルが返る.
結局,(仕様でキャッシュされない http-sp の設定も消して)このように変えた:

# DeleGate config. file
-P80
SERVER=http
CACHE=do
EXPIRE=1d
ADMIN=nodakai@gmail.com
# AUTH="admin::root:root"

超単純になった...
それにしても英単語またはローマ字の固有名詞の周囲に半角スペースを置くかどうかいつも悩む