Blobstore fetchData
App Engine には通常のデータベース的に利用するDatastoreの他に、Blobstore と呼ばれるストレージがある。このストレージに対しては、サーブレットを仲介せずに直接アップロード、ダウンロードができる。
Blobstoreに格納されたデータに対するアクセスは限定されている。導入当初はImageへの変換のみがサポートされており、読み出すことも書き込む事もできなかったのだが、1.3.2で限定的な読み出しメソッドとしてfetchDataが追加された。
このメソッドがちょっと変だ、というのが今日のお題。
fetchData メソッド
fetchData メソッドはBlobstoreServiceのメソッドで、 次のように定義されている。
byte[] fetchData(BlobKey blobKey, long startIndex, long endIndex)
開始インデックスと終了インデックスを指定して読み出すとデータを byte の配列として読み出せる。このサイズに制限があり、制限を越えたサイズを指定すると、IllegalArgumentException が発生する。
変なところ1:endIndex がexclusiveになっていない
startIndexに0,endIndexに10を指定すると、普通だと0-9の10個のアイテムが取れる。つまりendIndex に指定した10は取れない。これをstartIndexはinclusive でendIndexはexclusiveと表現する。計算機の世界ではこれが普通で、fetchDataのドキュメントにもそのように書いてある。
Parameters: blobKey - Blob-key from which to fetch data. startIndex - Start index of data to fetch. endIndex - End index (exclusive) of data to fetch.
にもかかわらず、実際に使ってみると、0-10までの11個が取れてくる。実害はないけどバグと言っていいだろう。
変なところ2: 制限サイズが変
制限サイズはドキュメントで実にアバウトな書かれ方をしている。
An app can read a Blobstore value a portion at a time using an API call. The size of the portion can be up to the maximum size of an API return value. This size is a little less than 1 megabyte, represented by the constant com.google.appengine.api.blobstore.BlobstoreService.MAX_BLOB_FETCH_SIZE in Java.
'a little less than 1 megabyte' (1M byte弱)って...
で調べてみたところ、1015808 バイトらしい。ちなみに1megabyte は1024 * 1024 で 1048576 なので、ちょうど32Kb足りない。内部的に使っているRPCの上限サイズかなにかから来る値なのだろうか?