0 display() ; if(i = 40 Ⅱ i return false ; = 39 Ⅱ i = 38 Ⅱ i = 37 ) { document . onkeypress = keypress ; function keycode (event) for(i=0;i く lines;i + + ){ function display(){ 0 var firstline var selected = 0 for(i=0; i く data. length; i + + ) { matched[i] matched return event . which if(a ! = 0 ) { return a } a = event . keyCode if (navigator. appName . indexOf ( "Netscape " ) ! = return window. event . keyCode ; if (navigator ・ appName . indexOf ("Microsoft") ! = d = data[matched[firstline + i] ] t = document . getEIementById("1ist" + i) ; for(i=O; firstline + 土く matched. length & & i く lines ; i + + ) { document . getEIementById( "list " + i) . innerHTML t = document . getEIementById("desc") '#ccccff' t . style . backgroundCoIor selected){ if(i t . style . width = 600 t . innerHTML = d[l] else { t . style . backgroundC010r for()i く lines;i + + ){ '#ffffcO' t = document . getEIementById("Iist" + i) ; t . innerHTML '   ; t . style . backgroundC010r '#ffffc0' display() ; く /script> EOF cgi ・ out { cgi . 五 tml { cgi . head { cgi ・ title { 'EPG 検索 , } + cgi. meta( 'http-equiv' = > "Content—Type" cgi . b0dy { b0dy 176 content ' = > "text/html ; charset=euc-jp") UNIX MAGAZINE 2005 . 9
図 13 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 連載 / 旧 v6 の実装ー 0 mip6-prefix 」 ist-find-withhaddr() 関数によるプレフィックス情報の検索 struct mip6—prefix * mip6—prefix—Iist—find—withhaddr(mpfx—Iist, haddr) if (IN6_ARE_ADDR_EQUAL (haddr , &mpfx—>mpfx_haddr) ) { mpfx = LIST—NEXT(mpfx, mpfx-entry) ) { for (mpfx = LIST-FIRST(mpfx_1ist) ; mpfx; struct mip6—prefix *mpfx; struct in6_addr *haddr ; struct mip6—prefix—1ist *mpfx—list ; return (NULL) ; / * not found . * / return (mpfx) ; / * found . * / すべての mip6-prefix 構造体は mip6-prefix 」 ist に f 尉寺 されるので本来第 1 引数は不要 ( つねに同じ値が指定され る ) ですが、開発初期のコードのままになっています。 図 13 の 455 ~ 461 行目で mip6-prefix 」 ist の各工ント リを調べ、 mpfx-haddr に常内されているホームアドレス と、引数で渡されたアドレスが等しいエントリのポインタ を返します。 mip6-ha 構造体との関連づけ mip6-prefix 構造体は、プレフィックス情報をアナウン スしているルータへのポインタ情報を保持しています。ポ インタ情報は mip6-prefix-ha 構造体で表され、 mip6- prefix 構造体の mpfx-prefix-ha-list メンバー変数にリ ストとしてイ尉寺されます。 467 struct mip6_prefix—ha * 468 mip6—prefix—ha—1ist—insert(mpfxha—Iist , 478 479 480 481 482 483 486 487 if (mpfxha ! = NULL) return (mpfxha) ; MALLOC(mpfxha, struct mip6—prefix—ha * , sizeof (struct mip6—prefix—ha) , M_TEMP , M_NOWA 工 T) ; if (mpfxha = = NULL) { return (NULL) ; 477 ~ 479 行目では、指定された mip6-ha 構造体への ポインタがリストに登録されていないかどうかを調べます。 登録済みなら、そのエントリへのポインタを返して終了し ます。未登録であれば、 481 ~ 487 行目で新しく作成する mip6-prefix-ha 構造体のメモリを確保します。 488 489 490 491 } mpfxha—>mpfxha—mha = mha ; LIST_INSERT_HEAD (mpfxha_list , mpfxha , mpfxha—entry) ; return (mpfxha) ; 469 470 471 { mha) struct mip6—prefix—ha—1ist *mpfxha—list ; struct mip6—ha *mha ; 488 行目で mpfxha-mha に引数で渡された mip6-ha 構造体のポインタを設疋し、 mip6-prefix 構造体の mpfx- ha 」 ist にエントリを挿入します。 mip6-prefix-ha 」 ist-insert() は mip6-prefix-ha 構 造体をリストに追加します。 mpfxha 」 ist は追加するリス トへのポインタ、 mha は関連する mip6-ha 構造体へのポ インタです。 472 struct mip6—prefix—ha *mpfxha ; 477 mpfxha = mip6—prefix—ha—1ist—find—withmha( mpfxha—list , mha) ; 80 493 494 495 496 497 498 499 VOid mip6—pref ix—ha—list—remove (mpfxha—list , mpfxha) struct mip6—prefix—ha—1ist *mpfxha—list ; struct mip6—prefix—ha *mpfxha ; LIST_REMOVE (mpfxha , mpfxha-entry) ; FREE (mpfxha , M_TEMP) ; UNIX MAGAZINE 2005 . 9
図 14 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 図 15 520 521 522 523 524 525 526 527 528 529 530 531 532 533 500 連載 / 旧 v6 の実装ー 0 mip6-prefix-ha 」 ist-find-withaddr() 関数び里 struct mip6—prefix—ha * mip6—prefix—ha—Iist—find—withaddr (mpfxha_list , addr) struct mip6—prefix—ha—1ist *mpfxha—list ; struct in6_addr *addr ; struct mip6—prefix—ha *mpfxha ; for (mpfxha = LIST—FIRST (mpfxha-list) ; mpfxha; mpfxha = LIST—NEXT (mpfxha , mpfxha_entry) ) { if (mpfxha—>mpfxha-mha = = NULL) C011ti11Ue ; if (IN6_ARE_ADDR_EQUAL (&mpfxha—>mpfxha_mha—>mha—addr , addr) ) return (mpfxha) ; mip6-prefix-ha-list-find-withmha() 関数のタ里 struct mip6—prefix—ha * mip6—prefix—ha—Iist—find—withmha(mpfxha list , mha) struct mip6—prefix—ha—Iist *mpfxha—list ; struct mip6—ha *mha ; return (NULL) ; struct mip6—prefix—ha *mpfxha; for (mpfxha = LIST-FIRST(mpfxha_1ist) ; mpfxha; mpfxha = LIST-NEXT (mpfxha , mpfxha_entry) ) { if (mpfxha—>mpfxha mha & & (mpfxha->mpfxha mha return (mpfxha) ; return (NULL) ; = mha) ) mip6-prefix-ha 」 ist-remove() は mip6-prefix-ha 構 造体のエントリを mip6-prefix 構造体の mpfxha 」 ist か ら削除します。この構造体は mip6-ha 構造体へのポイン タをオ内しているだけなので、単純に LIST-REMOVE() でリストから取り除いたあと、 mip6_prefix-ha 構造体用 に確保されていたメモリ領域を解放するだけです。 mip6-prefix-ha 」 ist-find-withaddr() は、第 2 引数 addr で指定したアドレスをもつ mip6 ー ha 構造体を、第 1 引数 (mpfxha 」 ist) で指定した mip6-prefix-ha 構造体 のリストから検索する関数です。図 14 の 509 ~ 516 行目 で、 mpfxha 」 ist で指定された mip6-prefix-ha 構造体リ ストのエントリをたどり、それぞれのエントリが示してい る mip6-ha 構造体のアドレスを調べます。 addr で指定さ れたアドレスをもつ mip6-ha 構造体がみつかれば、その UNIX MAGAZ 工 NE 2005.9 時点での mip6-prefix-ha 構造体のポインタを返します。 mip6-prefix-ha 」 ist-find-withmha() は、第 2 引数 mha で指定した mip6-ha 構造体へのポインタをもつ mip6-prefix-ha 構造体を、第 1 引数 mpfxha 」 ist で指定 したリストから検索します。図 15 の 527 ~ 531 行目で、リ ストに含まれる mip6-prefix-ha 構造体をたどり、構造体 に保持されている mip6-ha 構造体へのポインタが、 mha で指定されたアドレスと同じものを探します。該当するも のがあれば、その時点での mip6-prefix-ha 構造体へのポ します。 インタが返されます。 81 ( しま・けいいち IIJ) 次回も引き続き移動ノードのプレフィックス管理を解説 ☆
図 11 415 416 417 418 419 図 12 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 連載 / 旧 v6 の実装ー 0 mip6-ha 構冒本への参照を肖畭するタ里 / * remove a11 refernces t0 advertising routers . * / while ( !L 工 ST-EMPTY(&mpfx->mpfx—ha-1ist) ) { mpfxha = LIST-FIRST(&mpfx—>mpfx-ha—1ist) ; mip6-prefix-ha-1ist-remove(&mpfx->mpfx—ha—1ist , mpfxha) ; mip6-prefix 」 ist-find-withprefix() によるプレフィックス・情報の本 struct mip6—prefix * mip6—prefix—Iist—find—withprefix(prefix, prefixlen) mpfx—>mpfx-prefixlen) ) { & & (prefixlen if (in6—are—prefix—equa1 (prefix , &mpfx—>mpfx—prefix , prefixlen) mpfx = LIST—NEXT (mpfx , mpfx-entry) ) { for (mpfx = LIST—FIRST(&mip6_prefix—Iist) ; mpfx; struct mip6-prefix *mpfx ; int prefixlen ; struct in6—addr *prefix; return (NULL) ; / * not found. * / return (mpfx) ; / * found. * / す。実際にエントリを削除する前に、ほかの構造体との参 照情報を削除します。 図 10 の 405 ~ 413 行目は、 hif-softc 構造体から mip6- prefix 構造体への参照を削除する処理です。 hif-softc 構 造体は、 hif-prefix 」 ist-home と hif-prefix 」 ist-foreign 変数にそれぞれ、ホーム・プレフィックスと出先プレフィ ックスの情報を内しています。これらの変数に保持され ているプレフィックス情報が mip6-prefix 構造体を参照し ているので、 hif-prefix-list-remove() 関数を用いて参昭 を削除します。 図 11 の 416 ~ 419 行目は、 mip6-ha 構造体への参照 を削除する処理です。 mip6-prefix 構造体が参照している mip6-ha 構造体は、 mpfx-ha 」 ist に保持されています。 mpfx-ha 」 ist をたどりながら、 mip6-prefix-ha 」 ist-re- move() で mip6-ha 構造体への参照を削除します。 421 422 423 424 425 426 } LIST_REMOVE (mpfx , mpfx_entry) ; mip6—prefix—settimer(mpfx, ー 1 ) ; FREE (mpfx , M_TEMP) ; return ( 0 ) ; すべての参照清報を削除したら、 LIST-REMOVE() で UNIX MAGAZINE 2005.9 工ントリをリストから外し、 FREE ( ) でメモリ領域を解放 します ( 421 ~ 423 行目 ) 。 プレフィックス情報の検索 mip6-prefix 構造体は 2 種類の方法で検索できます。 1 つはプレフィックスとプレフィックス長の情報をもとに検 索する方法で、 mip6-prefix 」 ist-find-withprefix() で実 装されています。もう 1 つはホームアドレスをもとに検索 する方法で、 mip6-prefix 」 ist-find-withhaddr() で実装 されています。 mip6-prefix 」 ist-find-withprefix() はプレフィックス を表す in6-addr 構造体へのポインタ (prefix) とプレフィ ックス長 (prefixlen) を引数にとります。 すべてのプレフィックス情報は mip6-prefix 」 ist に保 持されているので、リストをたどりながら、引数で渡され たプレフィックス情報をもつ mip6-prefix 構造体を検索し ます。該当するエントリがあればそのポインタを返し、な ければ NULL を返します ( 図 12 の 435 ~ 445 行目 ) 。 mip6-prefix-list-find-withhaddr() の引数は 2 つで す ( 図 13 ) 。 mpfx 」 ist は mip6-prefix 」 ist へのポイン 夕、 haddr は検索対象のホームアドレスへのポインタです。 79
図 10 400 401 402 403 404 405 406 407 408 409 410 411 412 413 連載 / 旧 v6 の実装ー 0 hif-softc 構本からの参照を肖郎余する処理 if ( (mpfx-list = NULL) Ⅱ (mpfx return (EINVAL) ; = NULL) ) { / * remove a11 references from hif interfaces . * / for (hif = LIST—FIRST(&hif_softc_1ist) ; hif ; LIST_NEXT(hif , hif_entry)) { hif hif-prefix—list—remove(&hif->hif-prefix-list-home, hif—prefix—list—find—withmpfx(&hif—>hif—prefix—list—home , mpfx) ) ; hif—prefix—list—remove(&hif—>hif—prefix—list—foreign, hif—prefix—list—find—withmpfx(&hif—>hif—prefix—list—foreign, mpfx) ) ; ックス情報を取得するまで、繰り返しモバイル・プレフィ ックス要求メッセージを送信します。 まず、図 9 の 351 ~ 354 行目で有効時間が切れる時刻 (mpfx-vlexpire) を過ぎていないかどうかを確認します。 有効時間が切れていたら、 mip6-prefix 」 ist-remove() で mip6-prefix 構造体のエントリを削除します。 続いて、 356 行目で mip6-prefix-send-mps() を呼び 出し、モバイル・プレフィックス要求メッセージを送信し ます。 363 ~ 370 行目では、次のタイマー呼出しを予約します。 MIP6-MOBILE-PREFIX-SOL-INTERVAL 時間後 にまだ有効時間カ長っていれば、 MIP6-MOBILE-PRE- FIX-SOL-INTERVAL 時間後にタイマー関数の呼出し を予約し、そうでなければ有効時間が切れる時刻に最後の 呼出しを予約します。 mip6-prefix 構造体の月た態は EXPIRING のままです。 この : 犬態は、ルータ通知やモノヾイル・プレフィックス応答 メッセージを受信することで PREFERRED : 犬態に戻り ます。 プレフィックス情報の追加と削除 mip6-prefix 構造体は mip6-prefix 」 ist を先頭とする リスト構造として管理されています。移動ノードが入手し たプレフィックス情報は、すべて mip6-prefix 」 ist にイ寺 されます。 mip6-prefix 構造体をリストに追加 / 削除するための関 数が、 mip6-prefix 」 ist-insert() と mip6-prefix 」 ist-re- move ( ) です。 378 int 78 379 380 381 382 383 384 385 386 387 388 389 390 mip6—prefix—Iist—insert(mpfx—Iist , mpfx) return ( 0 ) ; mpfx-entry) ; LIST_INSERT_HEAD (mpfx_list , mpfx , return (EINVAL) ; (mpfx = = NULL) ) { = NULL ) Ⅱ if ( (mpfx—list struct mip6—prefix *mpfx; struct mip6—prefix—1ist *mpfx-list ; mip6-prefix 」 istänsert() は 2 つの引数をもちます。 mpfx 」 ist はリスト構造体 (mip6-prefix 」 ist) へのポイン 夕、 mpfx はリストに追加する mip6-prefix 構造体へのポ インタです。関数内は、たんに LIST-INSERT-HEAD() マクロでエントリを追加するだけの単純な内容となってい ます。 392 393 394 395 396 int mip6—prefix—1ist—remove (mpfx—list , mpfx) struct mip6—prefix—1ist *mpfx—list ; struct mip6—prefix *mpfx ; mip6-prefix 」 ist-remove() は 2 つの引数をもちます。 mpfx 」 ist はリスト構造体 (mip6-prefix 」 ist) へのポイン 夕、 mpfx はリストから削除する mip6-prefix 構造体への ポインタです。 追加時とは異なり、 mip6-prefix 構造体の削除は注意が 必要です。 mip6-prefix 構造体は、 hif-softc 構造体から ポインタ参照されている可能性があります。また、 mip6- prefix 構造体は mip6-ha 構造体への参照をイ尉寺していま UNIX MAGAZINE 2005.9
連載 / v6 の実装ー 0 図 5 ホームアドレスの生成 183 184 185 186 187 200 201 202 203 204 205 206 207 208 209 210 211 212 int mip6-prefix—haddr-assign(mpfx, sc) error = get—ifid( (struct ifnet * ) sc, struct hif_softc *sc ; struct mip6—prefix *mpfx ; return (error) ; if (error) NULL , &ifid) ; mpfx—>mpfx—haddr mpfx—>mpfx— return ( 0 ) ; mpfx—>mpfx—prefix ; haddr . s6_addr32 [ 2 ] ifid. s6—addr32 [ 2 ] ; ifid. s6—addr32 [ 3 ] ; mpfx—>mpfx—haddr. s6—addr32 [ 3 ] て、 mpfx-vltime が無期限に設疋されていなければ、効 時間 (mpfx-vltime) が切れる前にタイマー呼出しを設定 します。 mpfx-pltime 、 mpfx-vltime ともに無期限の場 合、タイマー呼出しは設定されません。 ホームアドレスの計算 mip6-prefix-haddr-assign() は mip6-prefix 構造体 に設疋されているプレフィックス情報をもとにホームアド レスを生成します。 mip6-prefix-haddr-assign() は 2 つの引数をもちま す ( 図 5 ) 。 mpfx はホームアドレスを生成するプレフィッ クス情報が内された mip6-prefix 構造体へのポインタ、 sc はそのプレフィックスが割り当てられているホームネッ トワーク・インターフェイス (hif-softc 構造体 ) へのポイ ンタです。 図 5 の 201 ~ 204 行目で get-ifid() を呼び出し、イン ターフェイス識別子を取得します。 get-ifid() は第 1 引数 と第 2 引数にインターフェイスへのポインタをとり、それ らのインターフェイスに設疋されているインターフェイス 識別子を第 3 引数に十翻村します。取得する識別子は第 1 引 数で指定したインターフェイスの情報が優先されます。ど ちらのインターフェイスからも識別子を取得できなければ、 ノードが保持しているほかのインターフェイスから識別子 を取得します。それも不可能な場合には、乱数で生成され た識別子となります。乱数を使った場合、一意性は保証さ れません。 UNIX MAGAZINE 2005 . 9 ホームアドレスの情報は mpfx-haddr に内されます。 上位 64 ビットをプレフィックス情報からコピーし、下位 64 ビットを get 」 fid ( ) で取得したインターフェイス識別 子からコピーします ( 207 ~ 209 行目 ) 。 タイマー関数呼出し時刻の言 mip6-prefix-settimer() は mip6-prefix 構造体のタイ マー関乎出し時刻を誌定します。 237 void 238 mip6—prefix—settimer(mpfx, tick) 239 240 241 { struct mip6—prefix *mpfx; 10 Ⅱ g tick; mip6-prefix-settimer() の引数は 2 つです。 mpfx は タイマー呼出しを設疋する mip6-prefix 構造体へのポイン 夕、 tick は呼出しまでの時間を示します。 257 if (tick く 0 ) { 258 259 261 mpfx—>mpfx—timeout = 0 ; mpfx->mpfx-ntick = 0 ; callout—stop(&mpfx—> mpfx—timer—ch) ; 257 ~ 261 行目はタイマー呼出しのキャンセル処理です。 tick に負数を指定された場合、タイマー関連の変数を初期 化し、 callout-stop() でタイマーを停止します。 図 6 の 268 行目で、タイマーが起動する時刻を mpfx- timeout に設疋します。 269 ~ 289 行目では、指定された 75
連載 / v6 の実装ー 0 図 2 mip6-prefix 構〕本の生成 105 106 107 111 112 113 114 115 116 117 118 119 120 121 122 124 131 132 133 134 135 } MALLOC(mpfx, struct mip6-prefix * , M_TEMP , M_NOWAIT) ; if (mpfx = = NULL) { return (NULL) ; bzero(mpfx, sizeof (*mpfx) ) ; sizeof (struct mip6_prefix) , in6—prefix1en2mask (&mask , prefixlen) ; LIST_INIT(&mpfx—>mpfx-ha-1ist) ; / * XXX mpfx->mpfx-haddr ; * / mpfx—>mpfx—prefixlen = prefixlen ; mpfx->mpfx—prefix. s6—addr32 [ 3 ] & = mask. s6-addr32 [ 3 ] ; mpfx->mpfx—prefix. s6—addr32 [ 2 ] & = mask. s6—addr32 [ 2 ] ; mpfx->mpfx-prefix. s6—addr32 [ 1 ] & = mask. s6-addr32 [ 1 ] ; mpfx->mpfx-prefix. s6—addr32 [ 0 ] & = mask. s6-addr32 [ 0 ] ; mpfx—>mpfx—prefix *prefix; callout—init (&mpfx—>mpfx—timer—ch, NULL) ; / * set initial timeout . * / mip6—prefix—update—Iifetime (mpfx , vltime , return (mpfx) ; 構造体に関連づけられている mip6-prefix-ha 構造体を 検索する。 ・ mip6-prefix-ha 」 ist-find-withmha() 才帛した mip6-ha 構造体に関連づけられた mip6-pre- fix-ha 構造体を検索する。 以下、それぞれの関数を解説します。引用するコードは fix-ha 構造体が定義されています。 カ夏数の mip6-ha 橢告体の情報をもてるよう、 mip6-pre- から広告されている場合もあるので、 mip6-prefix 構造体 ス情報を広告したり、あるプレフィックスカ夏数のルータ けて保持しています。 1 つのルータが複数のプレフィック 構造体 ) と、その情報を広告したルータのあいだを関連づ 移動ノードでは、各プレフィックス情報 (mip6-prefix 連しています。図 1 に、これらの構造体の関係を示します。 構造体は、ルータ情報を表す mip6-ha 構造体と密接に関 移動ノードでプレフィックス情報を表す mip6-prefix mip6-prefix 構造体の生成 mip6-prefix. c のものです。 UNIX MAGAZINE 2005.9 れます。 mip6-prefix 構造体は mip6-prefix-create() で作成さ 95 96 97 98 99 100 101 pltime) ; struct mip6—prefix * mip6—prefix-create(prefix, prefixlen, u—int32—t pltime ; u_int32_t vltime ; u—int8—t prefixlen; struct in6—addr *prefix ; vltime , pltime) mip6-prefix-create() の引数は 4 つです。 prefix と prefixlen は作成する mip6-prefix 構造体に本内されるプ レフィックスとプレフィックス長、 vltime と pltime はプ レフィックスの有効時間と推奨有効時間です。 図 2 の 105 ~ 112 行目で mip6-prefix 構造体を十内す るためのメモリ領域を確保し、 113 ~ 120 行目でプレフィ ックス情報 (prefix と prefixlen) を設定します。メモリ 確保に失敗した場合は NULL カります ( 111 行目 ) 。 122 行目で、 mip6-prefix-ha 構造体を保持するための リスト構造体を初期化します。図 1 に示したとおり、 mip6 -prefix 構造体はプレフィックス情報を広告しているルー タへのポインタを mip6-prefix-ha 構造イ釜由で保持しま す。 124 行目でこの mip6-prefix 構造体のタイマーを初期 化し、 132 行目の mip6-prefix-update 」 ifetime() で有 効時間を設定するとともに、次のタイマー呼出しを設定し 73
図 2 プロファイラの結果 Each sample counts as 0.01 % cumulative self 0 . 00 0 . 00 0 . 00 0 . 00 (c)t = 5.0 secondS . ca11s 2561 1 2560 2561 self Ks/ca11 time 99 . 98 0 .09 0 . 01 0 . 01 seconds seconds 2681 . 51 2681.51 2683.81 2684. 14 2684.43 2 . 30 0 . 33 0 . 29 tota1 Ks/caII 0 . 00 0 . 00 0 . 00 0 .00 連載 / 天文学と UN Ⅸ name calc_force leap—frog calc-pot initialize—acc—and—pot リスト 1 重力計算と関数 #define SQR(x) ((x)*(x)) calc—force(int Ⅱ , double double double double double int i , j , k ; double xij [ 3 ] ; m ロ , x ロ [ 3 ] , a ロ [ 3 ] , pot ロ , eps2) double rij2, riJ , riJinv, / * 粒子数 * / / * 粒子の位置 * / / * 粒子の質量 * / ソフトニング・パラメータ * / / * 粒子の重力ポテンシャル * / / * 粒子の加速度 ( 粒子が受ける重力 ) * / riJ3inv; / * a and pot should be initialized as zero before * / for(i=O; i く n; i + + ) { for(j=0;j く n;j + + ){ if (i==J ) continue ; for(k=0;k く 3;k + + )xij [k] x[i] Ck] ; rij2 rl 」 1 Ⅱ V riJ3inv SQR(xij [ 0 ] ) + SQR(xij [ 1 ] ) + SQR(xij [ 2 ] ) + eps2; rIJinV*rijinV*rijiIlV; 1 . O/rij ; sqrt(rij2) ; for(k=0;k く 3;k + + )aCi] Ck] + = (m[j] *rij3inv*xij [k] ) ; 図 3 シミュレーションでみられる粒子系の空間分布の変化 return(O) ; m[j] *rij inv; pot [i] (a)t = 0 み 1 0 0 1 0 1 は翻 ) を小さくしていったときに誤差がより速く小さくな ります。 UNIX MAGAZINE 2005.9 0 147 みます。シミュレーションでは、初期に速度分散の小さい こでは、 cold collapse 問題をシミュレーションして 1
連載 / 旧 v6 の実装ー 0 図 6 タイマー乎出し時刻の言聢 267 268 269 270 272 2 73 279 280 282 283 289 290 291 292 293 } } else { mpfx—>mpfx—timeout = mono—time. tv—sec 十 tick / hz; if (tick > INT—MAX) { else mpfx—>mpfx—ntick = tick ー INT—MAX ; callout—reset(&mpfx—>mpfx—timer—ch, mip6—prefix—timer, mpfx) ; mpfx—>mpfx—ntick = 0 ; callout—reset(&mpfx—>mpfx—timer—ch, mip6-prefix—timer, mpfx) ; INT_MAX , tick, SPIX(S) ; 図 7 mip6-prefix-settimer() で INT-MAX を超える日か指定されていた場合のタ里 316 mpfx = (struct mip6-prefix *)arg; 317 318 if (mpfx—>mpfx—ntick > 0 ) { 319 320 321 322 323 324 325 326 327 328 } if (mpfx->mpfx—ntick > INT-MAX) { } else { SPIX(S) ; return ; INT_MAX ; mpfx—>mpfx—ntick mip6—prefix—settimer(mpfx, INT—MAX) ; mpfx—>mpfx—ntick = 0 ; mip6—prefix—settimer (mpfx , mpfx—>mpfx—ntick) ; タイムアウトまでの時間 (tick) が、整数変数 (int 型 ) の上 er() で実装されます。 実際のタイマー処理は次に解説する mip6-prefix-tim- 間後にタイマーを起動するように設定します。 イ寺しておきます。そうでない場合は、 282 行目で tick 時 定し、 tick から INT-MAX を引いた値を mpfx-ntick に 行目で INT-MAX 時間後にタイマーを起動するように設 の値が int 型の上限値 (INT-MAX) を超えていたら、 272 上限が int 型変数の上限に制限されているからです。 tick を調整しています。 callout-reset() で指定できる時間の 限値を超えているかどうかに応じてタイマー呼出しの時間 295 296 297 298 76 #def ine MIP6_MOBILE_PREFIX_SOL_INTERVAL VOid mip6-prefix-timer(arg) static void 10 / * XXX * / 299 { mip6-prefix-timer() は void 型のポインタを引数にも ちます。実際には、ポインタに mip6-prefix 構造体へのポ インタカス疋されています。 図 7 の 318 ~ 328 行目は、 mip6-prefix-settimer() で INT-MAX を超える時間を指定されていた場合の処理で す。 mpfx-ntick に 0 以上の値か轂定されている場合、ま だ実際にタイマー関数を呼び出す時刻にはなっていないこ とを未します。ふたたび mip6-prefix-settimer() を呼 び出し、次のタイマー呼出しを予約します。 mip6-prefix- timer() が呼ばれるたびに mpfx-ntick の数は減ってい き、最終的に INT-MAX より小さくなったときに mpfx- ntick が 0 に設疋されます。 mip6-prefix 構造体は 2 種類の状態 (PREFERRED UNIX MAGAZ 工 NE 2005 . 9
特集 makemetafile. py P2P 技術の基礎知識 [ 1 ] 図 12 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 図 13 } 列 def make-meta-file(path, url, piece-len-exp, f1ag=Event() , progress=dummy, f inf0 = makeinfo(path, piece—length, flag, progress, target else : f else: OS ・ path ・ join(), b + ' . torrent') f = a + ' . torrent if b if not target : a, b = os . path. split(path) piece—length = 2 * * piece—len—exp comment=None , target=None , encoding= ' ascii ' ) : encoding) if flag. isSet() : return check—info (info) 五 = f ile ( f , ' wb ' ) data = {'info' : infO , ) announce if comment : data [ ' comment ' ] = comment h . write (bencode(data)) h . close() Python 2.3 . 5 ( # 1 , Apr 28 2005 , 13 : 35 : 15 ) $ python Ⅱ rl. strip() , creation date : int(time())} [GCC 3.3 . 5 ー 20050130 (Gentoo Linux 3.3.5.20050130 ー rl , ssp ー 3.3 . 5 .20050130 ー 1 , pie-on 1inux2 Type "help" , 'copyright " credits't or for more information . > > > import BitTorrent . makemetafile > > > BitTorrent . makemetafile . make_meta-fi1e("BitTorrent-4.0.2. tar. g 髫 "http : / / 127 . 0.0.1 : 8080 / " 1024 , target="size1024. torrent") 力しています ( 107 ~ 112 行目 ) 。 bencode する内容は辞 書形式で、断片化したファイルの情報 (info) 、トラッカー の URL (announce) 、作成日時 (creation date) です。 ファイルを断片化してメタ情報を作成する makeinfo 関 数では、与えられた path がディレクトリかファイルかに よって処理を変えます。 ファイルであれば、そのファイルを piece 」 ength の サイズごとに読み込んで SHAI アルゴリズムで断片の ハッシュ値を生成します。断片ごとにハッシュ値を取得 したあと、そのファイルのメタ情報として、断片の長さ (piece 」 ength) 、 UTF-8 でエンコードしたファイル名 (name) 、各断片のハッシュ値を連結したもの (piece) を 返しています。 一方、与えられたパスがディレクトリの場合は、最初にデ ィレクトリを再帰的に検索します。そして、そのディレク トリ内に置かれているファイルについて piece 」 ength の サイズごとに SHAI アルゴリズムでハッシュ値を生成し、 ファイル名とサイズからなる配列にディレクトリ内のファ UN 工 X MAGAZINE 2005.9 イルをすべて追加します。最後に 内したものを返します。 これらの情報を辞書に これらの操作を体験してみましよう。操作は、 Python のインタラクテイプ・モードでおこないます ( 図 13 ) 。 この例では、 import BitTorrent. makemetafile でモ ジュールをメモリ上にロードし、 BitTorrent. makemeta- file. make-meta-file で BitTorrent の配布用ソースコー ドから torrent ファイルを出力しています。また、実験用 のトラッカーをローカルで稼動させているため、 http:// 127.0.0.1 : 8080 / を指定しています。そして、ファイルを 1 , 024bit ごとに断片化するように指定しています。出力 ファイル名は、最後の、、 target " で指定している size1024. torrent です。 出力されたファイルの内容を図 14 に示します。 クライアントとトラッカーによるブートストラップ BitTorrent クライアントを起動して torrent ファイル を選択すると、次のような処理がおこなわれます。 93