Pages

Monday, November 24, 2014

Azure の Web サイトのメモ

何点か。

  • EntityFramework (*.edmx ファイル) でモデルを組んでて、Azure Website の Deploy のところで接続文字列を書き換えるようにしている場合、なぜか metadata パラメータなどが自動的に入らない。こんなエラーがでるはず。
    Some required information is missing from the connection string. The 'metadata' keyword is always required.
    どうやら、Visual Studio Online (Monaco) でみてみると、
    provider connection string='metadata=res://*/Sample.csdl|res://*/Sample.ssdl|res://*/Sample.msl;provider=System.Data.SqlClient;provider connection string="data source=****.database.windows.net;initial catalog=****;persist security info=True;user id=****;password=****;MultipleActiveResultSets=True;App=EntityFramework"'
    などと、勝手に書き換えられてしまうらしい。若干、迷惑感が漂う... 正しいやり方はなんだろう。今は Monaco で Deploy のたびに直しているが、たぶん正しい解放ではないと思う。Code First モデルの場合、このようなメタデータの指定は不要なので、ひょっとしたら問題ないのかもしれない。
  • ServiceRuntime が触れない件。
    Could not load file or assembly 'Microsoft.WindowsAzure.ServiceRuntime, Version=2.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.
    これはどう転んでも無理らしい。残念。

Wednesday, January 29, 2014

アプリケーションの設定を保存する方法

今日はもう一件。モバイル端末向けのアプリを作っていると、ユーザの情報を保存する必要があるはず。たとえば、ユーザを認証したときのトークンだとか、ちょっとした設定だとか。これを保存するためのクラスをまとめておく。

iPhone
NSUserDefaults クラス。standardUserDefaults クラス メソッドを使って、このクラスのインタスタンスを取得して、それに対して setInteger:forKey: などで書き込み、integerForKey: で読み取り。
Android
SharedPreferences クラス。読み取りはこのクラスでいいけど、設定の編集には SharedPreferences.Editor というネスト クラスを使う必要があるみたい。なんだろうこのアンバランス感。
Windows Phone 系
System.IO.IsolatedStorage.IsolatedStorageSettings クラス。ApplicationSettings という静的プロパティからインスタンスを取得する。もしくは、ClickOnce などのアプリケーションの場合は SiteSettings という静的プロパティから取得するのが吉。いずれにせよ、明示的なファイル パスを使ったアクセスができない場合向けの System.IO.IsolatedStorage 名前空間を使うのが正解。

まあだいたいどれも似ているね。

Azure ストレージへの共有アクセス署名 URI

Azure ストレージへ何らかのファイルをアップロードする状況について。サーバと連携して動くようなクライアント アプリケーション (モバイル端末とか) から、あるファイルをアップロードしたいのだけど、サーバが公開する Web API にファイルを送り付けて、その API がストレージに保存するのでは効率が悪い。なんなら、直接ストレージにアップロードする REST API があれば便利。だけど、ストレージ自体のプライマリ認証キー (いってみれば、ストレージにフルアクセスできちゃうキー) を渡すのは問題。だから、あるストレージ URI 特定に結びついていて、そのファイルをアップロードするためだけに使えるキーを REST API で指定してたたくことはできないだろうか、という疑問。

そしたら、やっぱりちゃんとあった。共有アクセス署名 (Shared Access Signature) を付与した URI。http://msdn.microsoft.com/en-us/library/windowsazure/dn140255.aspx を参照。どうやら、自分で HMAC でシグニチャを作らないといけないらしいけど。またわかったら Gist で公開するか、後日アップデートするかも。

Sunday, January 19, 2014

iOS 7 で飛んでくる Notification のログ

iOS 向けの開発を始めたのだが、いろいろと通知の類で困ったので、リサーチしてみた。書いたコードはこんな感じ。iPhone 4 の実機、iOS 7.0.4 で走らせてみたので、そのログをメモ。

起動

UIWindowDidBecomeVisibleNotification
UIWindowDidBecomeKeyNotification
UIApplicationDidFinishLaunchingNotification
_UIApplicationDidRemoveDeactivationReasonNotification
UIApplicationDidBecomeActiveNotification
UIDeviceOrientationDidChangeNotification
UIApplicationDidEndResumeAnimationNotification
UIDeviceOrientationDidChangeNotification
UIDeviceOrientationDidChangeNotification

タイムゾーン変更

_UIApplicationSignificantTimeChangeNotification
UIApplicationSignificantTimeChangeNotification
kCFTimeZoneSystemTimeZoneDidChangeNotification-4
kCFTimeZoneSystemTimeZoneDidChangeNotification-2
kCFTimeZoneSystemTimeZoneDidChangeNotification

謎なもの

UIStatusBarItemViewShouldEndDisablingRasterizationNotification というのが飛んできたけど、Google で検索してもなにも出てこなかった。謎。

画面向き変更

UIDeviceOrientationDidChangeNotification
_UIApplicationDidBeginIgnoringInteractionEventsNotification
UIWindowWillRotateNotification
UIApplicationWillChangeStatusBarOrientationNotification
UIApplicationWillChangeStatusBarFrameNotification
UIViewAnimationDidCommitNotification
UIApplicationDidChangeStatusBarOrientationNotification
UIApplicationDidChangeStatusBarFrameNotification
UIWindowWillAnimateRotationNotification
UIViewAnimationDidCommitNotification
UIViewAnimationDidStopNotification
_UIApplicationDidEndIgnoringInteractionEventsNotification
UIWindowDidRotateNotification
UIViewAnimationDidStopNotification
UIDeviceOrientationDidChangeNotification

非アクティブ化

ホームボタンで一度閉じてみる。

UIApplicationWillBeginSuspendAnimationNotification
_UIApplicationWillAddDeactivationReasonNotification
UIApplicationWillResignActiveNotification
UIApplicationSuspendedNotification
UIApplicationDidEnterBackgroundNotification
UIStatusBarStyleOverridesDidChangeNotification
UIStatusBarStyleOverridesDidChangeNotification
_UIApplicationDidFinishSuspensionSnapshotNotification
_UIWindowWillDestroyWindowContextNotification
_UIWindowWillDestroyWindowContextNotification

再アクティブ化

ホームからアプリのアイコンをタップして、再度フォアグラウンドに。

_UIWindowDidCreateWindowContextNotification
_UIWindowDidCreateWindowContextNotification
UIApplicationWillEnterForegroundNotification
UIDeviceOrientationDidChangeNotification
_UIApplicationDidRemoveDeactivationReasonNotification
UIApplicationDidBecomeActiveNotification
UIApplicationResumedNotification
UIApplicationDidEndResumeAnimationNotification
UIDeviceOrientationDidChangeNotification

通知バー出してみる

_UIApplicationSystemGestureStateChangedNotification
UIDeviceOrientationDidChangeNotification
_UIApplicationSystemGestureStateChangedNotification
_UIApplicationWillAddDeactivationReasonNotification
UIApplicationWillResignActiveNotification

通知バー閉じて、再度アプリ画面を表示

UIDeviceOrientationDidChangeNotification
_UIApplicationDidRemoveDeactivationReasonNotification
UIApplicationDidBecomeActiveNotification

スクリーンショット

UIApplicationUserDidTakeScreenshotNotification

終了

ホーム ボタン 2 度おしから、アプリを終了。

UIDeviceOrientationDidChangeNotification
_UIApplicationWillAddDeactivationReasonNotification
UIApplicationWillResignActiveNotification
UIDeviceOrientationDidChangeNotification
_UIApplicationWillAddDeactivationReasonNotification
UIApplicationSuspendedNotification
UIApplicationDidEnterBackgroundNotification
UIStatusBarStyleOverridesDidChangeNotification
UIStatusBarStyleOverridesDidChangeNotification
_UIApplicationDidFinishSuspensionSnapshotNotification
_UIWindowWillDestroyWindowContextNotification
_UIWindowWillDestroyWindowContextNotification
UIApplicationSuspendedNotification
UIApplicationDidEnterBackgroundNotification
_UIApplicationDidFinishSuspensionSnapshotNotification
UIApplicationWantsViewsToDisappearNotification
UIApplicationWillTerminateNotification

雑なまとめかたですみません。メモです。というか、たいていの NSNotification は、ふつうに適切なメソッドをオーバーライドして補足するのが正しい気がする... 個人的には、こんなふうに色々メッセージが飛んでくるのを見ると、なんだか Windows API のウインドウ メッセージっぽさを想起しなくもない。たぶん真似したのは歴史的に見て Win32 API 側だと思うけど。

Friday, November 29, 2013

SQL Azure の ID がジャンプする件ほか

最近、ひとに名刺を渡しつつ、申し訳程度に書いているこの Blog の URL なのだが、少しはまともなメモをたまには書かなければと思う今日この頃。そんなわけで、思いつき程度にさきほど気になったことをメモ。というか、むしろ淡々と技術的な備忘録にしちゃえばいいんじゃないかと思ったり。


Windows Azure の SQL サーバー サービスを使っていると、なぜかテーブルの ID たる int の自動生成カラムのシードがジャンプすることがある。

こんな感じ。どうやら、これは仕様らしくて、詳細はここでみつけた: Azure data transfer Identity Column Seed Jumped by 10,000

超要約すると、SQL の運用チームが「このほうが効率いいんじゃね?」って思って導入したということらしいのだが、それも今となっては「やっぱビミョー」だそうで、いつの日にか「やっぱやーめた」となる可能性があるということらしい。はい。


もう一件。Entity Framework を使っている人は、なんだかデータベースに接続するときに接続文字列が昔に比べてややこしいことにお気づきかと。具体的には、たとえば App.config にこんな感じの文字列がはいってらっしゃる:

metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient;provider connection string="hoge fuga piyo"
これの意味を再考せねばならない事態がおこるのが、次のようなとき:
これは、テスト用につくったソリューションだが、あるライブラリにデータベース接続用の EF モデルを作った。それを画面中のソースコードで使おうとしているが、次のような例外が発生している。

An unhandled exception of type 'System.Data.Entity.Core.MetadataException' occurred in EntityFramework.dll

Additional information: Unable to load the specified metadata resource.

どう見てもお怒りである。これは、*.edmx ファイルに書いてある EF モデルがうまく読み込めていない、とのことである。先ほどの接続文字列に戻ってみると、最初に metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl という記述がある。これがミソで、この例外が示すところは、このメタデータが読めてない、ということである。さて、このメタデータなのだが、実は *.edmx ファイルの構成を見てみれば、何をさしているのかわかる。たいてい、以下のような構成になっているはずだ。

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="3.0" xmlns:edmx="http://schemas.microsoft.com/ado/2009/11/edmx">
  <!-- EF Runtime content -->
  <edmx:Runtime>
    <!-- SSDL content -->
    <edmx:StorageModels>
      <Schema Namespace="Model.Store" Alias="Self" Provider="System.Data.SqlClient">
        データベースの物理的構成がここに。
      </Schema>
    </edmx:StorageModels>
    <!-- CSDL content -->
    <edmx:ConceptualModels>
      <Schema Namespace="Model" Alias="Self">
        データベースの論理的構成がここに。
      </Schema>
    </edmx:ConceptualModels>
    <!-- C-S mapping content -->
    <edmx:Mappings>
      <Mapping Space="C-S">
        物理構成と論理構成の間のマッピングがここに。
      </Mapping>
    </edmx:Mappings>
  </edmx:Runtime>
  <!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
  <edmx:Designer>
    細かいオプションとか、デザイナでの表示とかがここに。
  </edmx:Designer>
</edmx:Edmx>

細かいことはさておき、*.edmx ファイルのこの 3 つのコンポーネントが、コンパイル時にアセンブリ内にデフォルトでリソースとして埋め込まれる。それらがそれぞれ、Model.csdl, Model.ssdl, Model.msl という名前であり、さきほどの接続文字列はそれをさしていたのである。なお、細かいことが気になる人はこの記事が大変良く参考になる。

ではなぜ今回うごかなかったのかというと、Library のアセンブリを見てみるとき、良く見るとモデルが DB というフォルダ内に入っている。この場合、必ずしもアセンブリに埋め込まれるリソース名が上記のようにはならないのだ。

このとおり。そんなわけで、そういう場合には接続文字列を直してやる必要がある。ちなみに、res://*/ の * は、現在のアプリケーション ドメイン内で読み込まれているアセンブリすべてから当該名称を持つリソースを探すよ、という意味である。アセンブリ名が分かっているなら、当然指定したほうが早いらしい。参考まで。

Sunday, June 16, 2013

巨大なファイルをコピーするときの話

仕事でメンテナンスしているサーバが落ちたとの連絡があった。聞くところによると、本来うごいているべきサーバと通信が出来ないとのことらしい。このメモは、完全復旧 (+ 再構築) に 3 日かかったそのトラブルの顛末 (特に、大きなファイルをコピーして死にかけるという問題とその対策) をまとめておいた。

くだんのサーバは仮想構成になっていて、ホストもゲストも共に Windows Server 2008 という構成。ゲストには OS が入った VHD ファイル (50GB) と、データが入った VHD (3GB) がマウントされていて、それらはホストに接続されたソフトウェア ミラー構成の 2 枚の物理 HDD においてある。

6/13 朝9時すぎ。緊急の連絡があって業務データにアクセスできないということらしい。リモートでのアクセスには成功したので、物理サーバは起動している。だが、Hyper-V でゲスト OS の起動をかけようとすると、「ファイルシステム制限のため要求された操作を完了できませんでした」というエラーが出る。Google 先生で調べてみたところ、VHD の最適化を試みるとその問題が起こるケースが多いようで、ゲスト側の VSS (ボリューム シャドー コピー サービス) が有効になっているせい、という見解が多い。だが、(VHD 最適化でなく) VM 開始時にこれで落ちるという情報は見当たらない。イベント ログを見てみたら、前回の電源遮断は Windows Update があった 6/13 の午前 3 時過ぎ。なんてことはない、通常の再起動のはずである。異常な電源遮断ではなく、物理 HDD のミラーリングに不整合は生じていないので、再同期も必要なかった。

朝 10 時。とりあえずファイル システムの損傷を疑って、ディスクの完全なエラー チェックを実施。数年来そのまま使っていて過去にはハードウェア的な問題による異常な電源遮断も何度かあったので、問題があれば修復するようにした。これがまためちゃくちゃ時間がかかる。

午後 4 時。スキャン ディスクの結果は問題なし。ファイルシステムにも損傷はない。すると問題は何だ? VHD ファイルは正常なのに、Hyper-V から起動できないし、VHD の最適化にも失敗する。仕方がないので、Explorer 上で VHD ファイルを複製して、VM からは複製後のファイルをマウントさせることに。ファイル システムの制限、というからには自然な判断である。ここからが問題である

午後 8 時。リモート デスクトップでセッションに再接続したのだが、様子がおかしい。

  1. VHD ファイルのコピーは残り 10GB の表示のまま、まったく変化する様子がない。残り時間は減らないし、プログレス バーも当然すすまない。
  2. それから、Ctrl + Shift + Esc でタスク マネージャが上がらない。
  3. さらに、ゲスト OS は走ってないのに、メモリ使用量は 8G 積んだ物理メモリの 98% まで (!) 逼迫している模様。
  4. しまいには、管理コンソールでディスク情報を見ようとしても「取得中」のまま一時停止。
  5. 挙句 diskpart コマンドも起動してバージョン情報をはいたらそのまま応答がなくなる。

仕方ないので、この時点で現場急行を判断。過剰なページングによるスタベーションか、ディスク アクセスの異常を疑った。

午後 10 時。予想以上にひどかった。直接の対話型コンソール ログインができないのである。いわゆる「ようこそ」の画面のままクルクルしてて、ぜんぜんデスクトップが表示されない。さらにリモート管理で接続できないことも判明。打つ手なしになり、やむなく強制的な電源遮断を決断。当然ながら再起動するとミラーの整合性が失われるので、再同期が開始された。こうすると、HDD アクセスは全部もっていかれてしまうので、夜間に再同期を待つことに。この時点で現場での作業は終了、結局なにもできなかったに等しい。なお後日談だが、これはやってはいけなかった。この時点で安全のためにディスクの物理障害と論理障害を疑っていれば、ミラーになったディスクを分離し、代わりに予備のディスクを接続するなどの措置が必要だった。

翌朝 9時。ミラーの状態は正常。昨晩の症状は原因不明だし、他に無策だったので、今度は現場で確認しながら、ファイル コピーを試みることに。なお、上記の理由から予備ディスクにコピーすることにした。とりあえず業務に必要なデータだけは可及的速やかに抽出しなければならなかったので、データ (SQL Server の mdf ファイルなど) が入った小さい方の VHD ファイルだけ先に複製。ちなみにこれで、先の「ファイルシステム制限」のエラーは回避でき、別の VM へはマウントできるようになった。やはり、物理ディスクのファイル システムの問題なのだろうか。ともかく復旧にかかる懸念は、ファイル コピーできるかのほうに移ってきた。

ところで、ここである重要なことに気付いた。対話ログインで、リソース モニタで現状を追いかけていると、コピー中になぜかメモリ使用量が上がっていくのである。どうも調べたら、この問題らしい。そして同じように困っている人がいた。そんなわけで、上の KB 中に公開されている Dynamic Cache サービスをダウンロードして展開。

午前 11 時。業務データを救出して、予備サーバで続行するための作業と並行しつつ、ゲスト OS が入った巨大なほうの VHD ファイルを複製することに。さきのサービスも適切に展開したから、今度こそコピーに成功するはず・・・。なのだがやはり様子がおかしい。最初はメモリ使用量が増加せずに好調なのだが、やはり途中から増加して食い尽くしていくのである。そして、resmon で監視しながらわかったこととして、複製元の HDD の読み出し速度が書き込み側を上回る状態が続くと、メモリ使用量が増えるらしい。当然と言えば当然の結果なのだが、Dynamic Cache サービスを有効にしてても起こるらしい。最終的にどうしたかというと、読み出し側が速い状況が続いて、メモリが限界まで増えてきたときに、ソースとなるディスク側に高負荷の IO を行わせる (= 具体的には、小さいファイルがたくさんあるディレクトリを無意味に複製させるなど) ことで、書き込み側が追いつくのを待つ。50GB のファイルをコピーする中、2 時間ずっとリソース使用状況を監視していた。(メモリが逼迫したら、無駄な IO でキャッシュをフォールトさせる方向に調整。平衡を保つようににらめっことは、なんかの化学実験をやってるかのようであった。おちおちトイレにもいけない)

午後 2 時。VHD ファイルの無事を確認し、それぞれ複製後のファイルをマウントしたら VM も正しく起動するようになったことを確認。これで復旧としても良かったのだが、次、いつ同じようなトラブルがあるかわからないので、ディスクを新しくしてホスト OS も新たにインストールしたサーバを用意することにした。ハードウェアの寿命だったのかもしれない。

そんなわけで、新しいサーバを用意して、そちらにデータを元通りにして、ドメインに参加させてネットワークの設定を行ったり、業務端末からの通信テストをしたりしていたら、僕の 3 日間は消えたのでした。ちゃんちゃん。

Friday, September 28, 2012

BYOD

巷で最近よく見かける単語 BYOD が Bring Your Own Device の略であることを今更ながら知った。なんて読むの、ビョーディー? バイオデー?