start

P4で「Client 'foo' can only be used from host 'bar'」と言われた時の対処方法

Perforceのワークスペースは基本的にマシンと紐付いているため、複数マシン間で使い回すことができない。

普通は使い回しはしないので問題はないのだが、故障などでマシンを交換した時にちょっと面倒なことになる。利用可能なワークスペース一覧に表示されず、たとえ無理やり選択しても「Client 'WORKSPACE' can only be used from host 'OLD-HOSTNAME'」と怒られて使えないのだ。

ちなみに新旧マシンのホスト名を一緒にしておけば問題は起きず、まぁ新マシンで新たにワークスペースを作ってしまうのが正攻法なんだろうけど、巨大なデポだと再取得するのも嫌じゃん? そんな時はp4 clientコマンドでワークスペースが持っているホスト名を変更すれば良い。手順は下記の通り。

  1. p4コマンドが使える状態にする。
  2. p4 client を実行。
  3. ワークスペースの情報がテキストエディタで表示されるので、Host: OLD-HOSTNAME となっているところを Host: 新マシンのホスト名 に変更して保存。
  4. テキストエディタを終了すると、Client WORKSPACE saved.と表示されワークスペース情報が更新される。
  5. 念のためp4 infoで「Client host:」が書き換わってるか確認。

以上で新マシンから既存のワークスペースが使えるようになるハズ。

C#のジェネリックで特殊化っぽいことをする

新年明けましておめでとうございます(遅。開設14年目となるクソゲ~製作所を本年もよろしくお願い致します。

Cのテンプレートには特殊化という、特定の型パラメータの時にテンプレートの実体を別に定義する機能がある。だが、C#版テンプレートとも言えるジェネリックでは、なんということでしょう、特殊化が使えないではありませんか!それをどうにかしてジェネリック特殊化っぽい事をしてみたっていうお話。 こんなコードがあったとする。 <code csharp> public class Node { // 子ノード public List<Node> Children; // 特定の子ノードを取得 public List<T> FindChildren<T>() : where Node { List<T> list = new List<T>(); Type type = typeof(T); foreach (Node e in Children) { if (type == e.GetType()) { list.Add(e); } list.AddRange(e.FindChildren<T>()); } return list; } } public class DocumentNode : Node {} public class PageNode : Node {} public class TitleNode : Node { public string Title; public TitleNode(string title) { Title = title; } } public class SectionNode : Node { public TitleNode Title; } static void Main() { DocumentNode doc = new DocumentNode(); PageNode page = new PageNode(); doc.Children.Add(page); SectionNode section1 = new SectionNode(); section1.Title = new TitleNode("はじめに"); page.Children.Add(section1); SectionNode section2 = new SectionNode(); section2.Title = new TitleNode("つぎに") page.Children.Add(section2); // 全セクションを取得 List<SectionNode> allSections = doc.FindChildren<SectionNode>(); //正しく取得できる // 全タイトルを取得 List<TitleNode> allTitles = doc.FindChildren<TitleNode>(); //★正しく取得できない!! ... } </code> <code> ◆データ構造 [DocumentNode] -Children -[PageNode] -Children -[SectionNode] -Title -Children -[SectionNode] -Title -Children </code> 文章を模したデータ構造を作り、''FindChildren''メソッドで型をパラメータに子ノードを取得しているが、 ''doc.FindChildren<SectionNode>()''は正しい挙動をするものの、''doc.FindChildren<TitleNode>()''の方は空のリストが帰ってくる。''FindChildren()''は''Node.Children''しか見てないので、独立したメンバ''SectionNode.Title''が入るはずはなく当然の挙動である。 こんな時、C++なら特殊化で''FindChildren<TitleNode>''専用の処理が書け同一のインタフェースを提供できるのだが、前述の通りジェネリックは特殊化が使えないの。C#的には''FindChildTitleNodes()''的な別メソッドで提供するのが正しいのかもしれないが、やっぱり統一感に欠けて美しくない(そもそもこんな糞いデータ構造にすんなって話だが例ってことで許してね。) で、知恵を振り絞って''FindChildren''を以下のようにした。 <code csharp> public List<T> FindChildren<T>() : where Node { List<T> list = new List<T>(); Type type = typeof(T); if (type == typeof(TitleNode)) // (1) { List<T> titles = new List<T>(); // (2)-a var sections = FindChildrenInternal<SectionNode>(); section.ForEach(e => { titles.Add(e.Title as T); }); // (3) return titles; // (2)-b } return FindChildrenInternal<T>(); } List<T> FindChildrenInternal<T>() : where Node { List<T> list = new List<T>(); Type type = typeof(T); foreach (Node e in Children) { if (type == e.GetType()) { list.Add(e); } list.AddRange(e.FindChildren<T>()); } return list; } </code> 元の''FindChildren()''を''FindChildrenInternal()''とし、''FindChildren()''には型パラメータ''T''に応じた処理を書くようにした。C++でコンパイラが自動で行ってくれる特殊化による処理の振り分けを、実行時に手動で行うような感じかしら。原理上、実行時コストは増えるが、この程度なら大した影響はないだろう。JIT様もあることだし。 型が増えると''if''と特殊化処理の嵐になるが、型ごとに処理デリゲートを作って''Type''とデリゲート辞書でも作ればすっきりするので大した問題ではない。そもそも、そんな状況は最早「特殊化」の本質から外れてるので設計から見直すべきだろう。 このコードのミソは(1)~(3)の部分。 (1)で処理すべき''T''の型が明確になったものの、(2)-aで''List<T>''としているのはコンパイルを通すため。''List<TitleNode>''でも良さそうに見えるが、''T == TitleNode''になるとは限らないので(2)-bで型不一致エラーになる。''List<TitleNode>''とした場合に''T = SectionNode''で呼び出した時にどうなるかを考えれば、すぐにおかしさに気づいて頂けるかなと。 (3)も一見''titles.Add(e.Title)''で良さそうだが、これまた''TitleNode''が必ずしも''T''に変換可能とは限らないのでCS1503エラーとなる。よって、ちょっとアホくさいが''TitleNode''を自身の型''T''にキャストしてやらなければならない。 メソッドの引数に型パラメータを持てる場面では、[[https://arbel.net/2007/11/22/c-partial-specialization-with-extension-methods/ にも軽量な型情報システムがあればいいのになぁ…。

永遠に讃えよ我が芋煮

PCのHDD整理していたら表題の歌詞が出てきた。確かtwitterで見かけて素晴らしいクオリティに感動しコピペしたものだった気がする。

今軽くググってみたらヒットしなかったので、ここにコピペして保存する。なくすには惜しい出来なので。

永遠に讃えよ我が芋煮
(山形神聖醤油帝国 国歌)

気高きは 醤油の意志
示せ あまねく宇宙に
理想貫く 味
芋の加護は 我らと共に
あり続けん
ガーレ=イモニン
誇りある 鋼の大鍋

2015年最後の日記がこれってどうなのよ。

インク商法で儲けてるプリンタメーカーは滅びればいいよね

写真コンテスト応募のため、気合いを入れてA4の高級写真用紙&純正インクを購入し最高品質で印刷してところ、たった25枚ほど印刷しただけでインク残量警告が出やがった!

プリンタはHP Photosmart 6520で購入したインクはHP178 4色マルチパック(CR281AA)。ビックカメラ店頭で3700円程だったと思う。

インク残量表示から計算すると、HP178マルチパックのカラーインクで印刷できる写真の枚数は、A4換算で多くても40枚程度と見られ1枚あたりのインク代は92.5円となる。この数値だけを見ると一概に高いとは言えないかもしれない(個人的には十分高いと思う)が、実際にはテストプリントや失敗の分、加えて紙代に超微々たるものだが電気代も掛かるわけで、かなり高コストだと言わざるを得ない。当然、プリンタ本体の代金だって掛かってるわけで…1万円で1000枚印刷したとしても10円/枚もベースコストが掛かる計算なわけで……。

ネットの激安写真プリントだとA4 1枚100円前後からやってくれる所があるし、L判なら更に安い。まだ使ったことがないので印刷品質は分からんが、家庭用インクジェットより劣るとは考え辛い。もう写真プリントは全部外注で良いかなって気がしてくる。おうちプリントは「その場で印刷できる」って事が最大のメリットだが、それすらも店頭にあるセルフプリントマシンや、最悪コンビニのマルチコピー機を使えば薄らいでしまう。

大体さー、家庭用インクジェットプリンタのインクが高いのって、本体を安く売ってインクで稼ぐという大義名分があったわけだけど、最近のプリンタは明らかに造りが安っぽくなってるよね。

2年程前かな、実家で使ってたCanon MP560が年賀状シーズン中に突然故障し、やむなくMG5530を購入する羽目になったが、兎に角造りが安っぽい。グレード的には下がった事になるが、それを差し引いても安っぽい。背面給紙はできなくなるわ(これはMG5530だけではなく最近の機種は須く非対応。普段使いのA4普通紙は底面トレイ、年賀状や本気写真印刷などその場の給紙は背面と使い分けられて超便利だったのに)、動作音は半端なく煩くなるわ(激安Photosmart 6520よりも煩い!)、肝心の印刷品質も粒状感が目立って落ちてるわ、良いところがまるでないという。当然、MP560用のインクストックは無駄になったし…。

こんなクソみたいな造りでは、本体価格の1/4〜1/2もする高価な純正インクを買おうなんて気は全く起きなくなるね。「非純正インクのせいでプリンタ本体に金を掛けられなくなった」という言い分もあるだろうが、だったら最初からインク商法なんざするなよとしか言えない。割安なインクが出てくる事なんて目に見えてるんだし、そもそも純正インクの価格設定が高すぎると思うんだよね。多くの人が高いと思っているから非純正インクの市場が成り立ってるんでしょ?

自分も昔は上位ラインの機種と律義に純正インク使ってたけど、使用頻度の割にトラブルが多過ぎて、その度に労力と金を掛けるのがバカバカしくなったため、もう格安プリンタに格安非純正インクで良いという結論に達した。ちなみに、決定打となったのはPIXUS iP7500の印刷がかすれるようになったので修理に出したら、修理の保証期限が切れた直後に症状が再発した事件があったから。その間、印刷したのは多く見積もっても10枚程度。流石にゴルァ電したけどどうにもならなかったので、金輪際キヤノン製品は買わないと心に誓った(笑)

実際に非純正インクを使ってみても、質的には何の問題もないしねー。今使ってるHP178の互換品は純正よりも発色が良かったりするし…ただし黄色は非純正の方が明らかにくすんでいたので、冒頭に書いた通り本気印刷用に純正品を買ってみたら、減るの早過ぎてこの記事を書くに至った次第。

zfs destroyしても空き容量はすぐには増えない?

ここに16TiBのRAID-Z2プールがあるじゃろ。

$ zpool list
NAME    SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
zdata  16.2T  5.63T  10.5T    34%  1.00x  ONLINE  -

$ zfs list
NAME              USED  AVAIL  REFER  MOUNTPOINT
zdata            5.63T  5.02T   304K  /mnt/zdata
zdata/ROOT       5.63T  2.37T   304K  /mnt/zdata/ROOT
zdata/ROOT/data  5.63T  2.37T  5.63T  /mnt/zdata/ROOT/data

それを消したんじゃ。

$ sudo zfs destroy -R zdata/ROOT

そして再度ファイルシステムを確認すると…

$ zfs list
NAME    USED  AVAIL  REFER  MOUNTPOINT
zdata  5.61T  5.04T   288K  /mnt/zdata

なんと、空き容量が増えておらんのじゃ!

もう少し詳しく見てみる。

$ zpool iostat zdata 1
               capacity     operations    bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
zdata       8.20T  8.05T    403    161  2.35M   659K
zdata       8.20T  8.05T    445      0  1.86M      0
zdata       8.20T  8.05T    359      0  1.64M      0
zdata       8.20T  8.05T    494      0  2.65M      0
zdata       8.20T  8.05T    446      0  1.75M      0
zdata       8.20T  8.05T    309      0  1.42M      0
zdata       8.19T  8.06T    416    266  2.17M  1.62M
zdata       8.19T  8.06T    415      0  1.88M      0
zdata       8.19T  8.06T    438      0  2.47M      0
zdata       8.19T  8.06T    328      0  1.49M      0
zdata       8.19T  8.06T    379      0  1.82M      0
zdata       8.19T  8.06T    494      0  2.65M      0
zdata       8.19T  8.06T    314    158  1.46M   647K
zdata       8.18T  8.07T    349      8  1.40M  36.0K
zdata       8.18T  8.07T    549      0  2.71M      0
zdata       8.18T  8.07T    444      0  1.85M      0
zdata       8.18T  8.07T    660      0  3.09M      0
zdata       8.18T  8.07T    408      0  1.72M      0
zdata       8.18T  8.07T    310      0  1.83M      0
zdata       8.16T  8.09T    303    161  1.28M   659K
zdata       8.16T  8.09T    469      0  2.61M      0
zdata       8.16T  8.09T    350      0  1.89M      0
zdata       8.16T  8.09T    269      0  1.86M      0
zdata       8.16T  8.09T    272      0  1.72M      0
zdata       8.16T  8.09T    264      0  1.76M      0
zdata       8.15T  8.10T    196    170  1.29M   695K
^C
$ zfs list
NAME    USED  AVAIL  REFER  MOUNTPOINT
zdata  5.39T  5.27T   288K  /mnt/zdata

$ df -h
Filesystem                     Size    Used   Avail Capacity  Mounted on
zdata                          6.6T    287k    6.6T     0%    /mnt/zdata

なんか頑張って回収しとるのぉ…。この状態でファイルを作るとどうなるんじゃろ?iostatを見ながらddしてみる。

$ sudo zfs create zdata/ROOT
$ dd if=/dev/zero of=/mnt/zdata/ROOT/zero.tmp bs=8m
^C
601+0 records in
600+0 records out
5033164800 bytes transferred in 24.909500 secs (202058043 bytes/sec)

----------

$ zpool iostat zdata 1
zdata       3.92T  12.3T    231  1.43K  1.71M   141M
zdata       3.92T  12.3T    274      0  1.48M      0
zdata       3.90T  12.3T    102  1.36K   464K   141M
zdata       3.88T  12.4T    202    720   811K  59.7M
zdata       3.88T  12.4T    548    667  2.63M  81.2M
zdata       3.88T  12.4T    117  1.75K   472K   192M
zdata       3.88T  12.4T    212    208   872K   856K
zdata       3.88T  12.4T    197  2.36K  1.06M   293M
zdata       3.88T  12.4T    203    796   827K  68.5M
zdata       3.88T  12.4T    242  1.78K   979K   225M
zdata       3.88T  12.4T    159  1.39K   647K   146M
zdata       3.88T  12.4T    134  1.51K   539K   191M
zdata       3.87T  12.4T    120  1.33K   484K   143M
zdata       3.87T  12.4T    380  1.80K  2.12M   224M
zdata       3.87T  12.4T    504    953  1.97M  83.2M
zdata       3.87T  12.4T    350  2.42K  1.37M   304M
zdata       3.86T  12.4T    674    913  3.13M  80.2M
zdata       3.86T  12.4T    338  2.50K  1.33M   314M
zdata       3.86T  12.4T   1005    606  4.41M  47.1M
zdata       3.86T  12.4T    289  2.86K  1.13M   360M
zdata       3.86T  12.4T    704    184  2.75M   749K
zdata       3.86T  12.4T    103  3.36K   415K   418M
zdata       3.86T  12.4T    867    191  3.88M   779K
zdata       3.86T  12.4T     63  3.17K   255K   396M
zdata       3.86T  12.4T    954    149  4.22M   611K
zdata       3.86T  12.4T     38  3.46K   156K   432M
zdata       3.86T  12.4T    797     66  3.11M   276K
zdata       3.86T  12.4T      0  3.07K      0   375M
zdata       3.86T  12.4T    761    532  3.47M  62.6M
zdata       3.86T  12.4T    651    263  2.54M  7.09M ★ここでddを終了
zdata       3.86T  12.4T  1.02K    182  4.55M   743K 
zdata       3.86T  12.4T  1.01K      0  4.55M      0
zdata       3.86T  12.4T  1.24K      0  5.46M      0
zdata       3.86T  12.4T  1.09K      0  4.87M      0
zdata       3.86T  12.4T  1.37K      0  5.99M      0
zdata       3.86T  12.4T  1.45K      0  6.27M      0
zdata       3.86T  12.4T  1.04K    167  4.68M   683K
^C

当然じゃが普通に動くようじゃ。dd終了後は、また領域の回収?に戻っておるの。

暫く放置したら回収?作業が終わったようじゃ。

$ zfs list
NAME    USED  AVAIL  REFER  MOUNTPOINT
zdata  90.2M  10.7T   288K  /mnt/zdata

$ df -h
Filesystem                     Size    Used   Avail Capacity  Mounted on
zdata                           10T    288k     10T     0%    /mnt/zdata

じゃがしかし!AVAILが10.7T止まりなのは何故じゃ!?や、RAID-Z2であるからして、パリティ2台分の容量を考慮すると妥当な値なんじゃが、プール作成直後は16Tになってた気がするんだがのぉ……こっちの値が不正確と言われればそれまでなんじゃが、気になる………。

  • start.txt
  • 最終更新: 2022-07-27 15:26
  • by Decomo