2013年7月7日日曜日

TimeMachineのバックアップの信頼性を修復する方法

QNAP TurboNAS TS-421のTimeMachineに突然やってきた悲劇のダイアログ

信頼性を向上するために、新規バックアップを作成する必要があります

提示された選択肢は「後でやる」か「今やる」か
結局どちらも新規バックアップをつくることになる

過去に戻れないTimeMachineなんて
なさけなくて涙があふれそうになりながらぐぐってみたら
修復することができて嬉しかったのでメモっておくことにする

TimeMachineのバックアップはディスクイメージに保存する仕組みになっていて
ディスクイメージ内に構築したHFSファイルシステムが壊れたので
「信頼性が低くなった」と表示したようだ
(fsckしてみたらhard linkの数が合わないって言ってた気がする)

やるべきことは2つ
  1. ファイルシステムを修復すること
  2. TimeMachineの検証状態をリセットすること

面倒だからといって[2]を実施しないと
TimeMachineは新規バックアップ作成を強要してくるので注意

それと、修復作業は時間がかかるのでMacを放置することになる
修復作業中にMacがスリープしないように設定を変更するべきだろう


ファイルシステムを修復する手順

QNAPにadminでログイン

File Stationを開く

共有フォルダの新規作成を開始する

詳細設定をクリックし、手動でパスを入力する
ドロップダウンから.timemachineを選択する
残りのステップはデフォルトのままだったと思う
※普段使っているアカウントでアクセスできるよう権限を設定すること

QNAP(AFP)の「TM」フォルダをクリックしてマウントする

「TM」フォルダがマウントされた様子

「マシン名.sparsebundle」をディスクユーティリティで開く
(ここから次の画像のようになるまで5分くらいかかったかも)

「マシン名.sparsebundle」を開く

「Time Machine Backups」を選択して「ディスクを修復」をクリック

修復している様子

修復完了すると「修復を中止」ボタンが「ディスクを修復」ボタンに変わる
(この画像は作業中のものではないので実際とはことなるかも)

「マシン名.sparsebundle」の中の「com.apple.TimeMachine.MachineID.plist」を書き換える

テキストエディタで開いて

VerificationStateの値を0(ゼロ)に変更する

これで修復作業は完了したので
コンピュータにマウントされている共有フォルダ「TM」を取り出す
QNAPのTM共有フォルダの解除はFile Stationではなくてコントロールパネルで操作するのだが、次回に備えて共有したままにしておいた

メニューバーのTimeMachineで「今すぐバックアップを作成」を始めると...

検証に5分くらいかかったと思う

しばらくしてバックアップが正常に完了

幸運を祈る!

2013年5月27日月曜日

cocos2d-xで画像データを表示する方法

メモリ上で作成したRAWデータの画像を表示したい場合、
CCTexture2Dでテクスチャを作成して、CCSpriteで表示する。

例えばこんな感じ。

CCSprite* createSpriteWithRawData(const void* data, unsigned int width, unsigned int height)
{
    CCTexture2D* texture = new CCTexture2D();
    if (texture && texture->initWithData(data, kCCTexture2DPixelFormat_RGBA8888, width, height, CCSizeMake(width, height))) {
        texture->autorelease();
        return CCSprite::createWithTexture(texture);
    }
    CC_SAFE_DELETE(texture);
    return NULL;
}
※ CCTexture2D::initWithDataは、dataをglTexture2Dに渡してグラフィックスハードウェアに転送している。
従ってdataをメモリ上に確保しておく必要はない。

ネットワーク経由で取得したPNGやJPG画像を表示したい場合などは、
CCImageで画像フォーマットを解析してから、CCTexture2DとCCSpriteで表示する。

例えばこんな感じ。

CCSprite* createSpriteWithPngData(void* data, unsigned long data_length)
{
    CCImage* image = new CCImage();
    if (image && image->initWithImageData(data, data_length, CCImage::kFmtPng)) {
        image->autorelease();
        CCTexture2D* texture = new CCTexture2D();
        if (texture && texture->initWithImage(image)) {
            texture->autorelease();
            return CCSprite::createWithTexture(texture);
        }
        CC_SAFE_DELETE(texture);
        return NULL;
    }
    CC_SAFE_DELETE(image);
    return NULL;
}
※ CCImage::initWithImageDataは、dataを必要に応じてコピーしている。
従ってdataをメモリ上に確保しておく必要はない。

2013年5月19日日曜日

cocos2d-xでハイブリッドプロジェクトを作る方法

cocos2d-xの新規プロジェクト、どうやって作ってる?

ぐぐってみると、

  1. Xcodeのプロジェクトテンプレートを使ってiOS向けの新規プロジェクトを作成する
  2. create-android-project.shを使ってAndroid向けのプロジェクトを作成する
  3. これら2つのディレクトリをマージする
  4. cocos2d-xのソースをマージする
  5. Android向けのビルド関連ファイルを修正する

という手順が紹介されていることが多い。

cocos2d-x.orgのニュースに掲載されている本「Cocos2d-X By Example Beginner's Guide」でも同様の手順が紹介されている。

しかし、この手順でプロジェクトを作ると3つのことが気に入らない。

  1. めんどくさい
  2. ディレクトリ構成がめちゃくちゃ
  3. iOSやAndroid以外のプラットフォームのビルドはどうするんだ?

個人的には(3)は無視できるけれど、(2)は無視できないし、(1)は致命的だ。

この状況を解決してくれるのが project-creator だ。
cocos2d-2.1rc0-x-2.1.3.zipを展開すると、tools/project-creatorディレクトリに"create_project.py"というファイル名のPythonスクリプトがある。

このスクリプトを使うとsamplesと同じ構成のハイブリッドなプロジェクトを、ものすごく簡単に作れるうえに、iOSやAndroidだけでなく、たとえばwin32向けのビルドもできるようになるのだ。

たまたま、Windows8(x64)の環境で遊んでいたので、win32向けのビルドを試してみた。

Microsoft Visual C++ 2010 Express
Windows SDK
Python 2.7.5 Windows X86-64 Installer

これらをインストール(再起動が必要だったし、ついでにMicrosoft Updateしたり)した後、
コマンドプロンプトでcreate_project.pyを実行した。

D:\> cd cocos2d-2.1rc0-x-2.1.3\tools\project-creator
D:\cocos2d-2.1rc0-x-2.1.3\tools\project-creator> create_project.py -project Praise002 -package net.xpraise.praise002 -language cpp

proj.win32のslnファイルをVC++で開いてデバッグ実行した時のキャプチャ。



VC++でデバッグするのはありかもしれないな。

2013年3月2日土曜日

String interpolation in Scala 2.10

小さいけど影響力大きい。
val name = "K"
println(s"hello ${name} !")
参考: String interpolation

2013年3月1日金曜日

最近のお気に入りはIterator.continually

for (line <- Iterator.continually(readLine()).takeWhile(_ != "quit")) {
  println(line)
}