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の上限サイズかなにかから来る値なのだろうか?

所感

そもそもなんでfetchDataのサイズに上限が設定されてるんだろう?一度に読めるサイズが限定されていても、繰り返して読めば全部読み出せるわけなので、あまり意味がないような。。。内部構造的な制約があったとしても、APIで隠蔽する事は簡単だろうし。

まあ、google的には、Blobstoreからの読み出しを推奨していない、ということなのかな。