2013年5月23日木曜日

android ndk と java から sqlite3 でアクセスするとどうなる?備忘録

 ndk からsqlite3 データベースを読みだしている状態で、android sdk の java が、データベース更新時に、時々例外を発生する事がある。どんなカラクリになっているのか気になって調べてみるとtwo connection to sqlite from java application and from ndkの情報が正確そうだ。Android SDK のJavaコードでは、1000mm sec 待っても応答が無ければ例外を送出する仕様であるらしい。言わせてもらえると、例外が発生するようなケースは、レアケースじゃね〜Ze。こんちくしょう。 自分の ndk でのレコードアクセスでは
#pragma once
#ifndef SQLITE_ACCESS_HPP
#define SQLITE_ACCESS_HPP

#include <sqlite3/sqlite3.h>
#include <functional>
#include <memory> // unique_ptr
#include <log.hpp>
#include <unistd.h>

namespace sio {

  template <class Container, class ReadOpe>
  bool read_rows(
    sqlite3*    db, 
    const char* sql, 
    Container&  container,
    ReadOpe     ope,
    const char* target_name
  ) {
    sqlite3_stmt* stmt = nullptr;
 int res = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr );
 if( SQLITE_OK != res ) {
      __android_log_print(ANDROID_LOG_ERROR, target_name, "Fail to read rows: %d", res );
      return false;
 }
    std::unique_ptr<sqlite3_stmt,std::function<void(sqlite3_stmt*)> > stmt_holder( stmt, sqlite3_finalize );
 while(true) {
      while( res = sqlite3_step(stmt), SQLITE_BUSY == res ) { usleep(10); }
   switch( res ) {
   case SQLITE_ROW:  ope( stmt, container );  break;
   case SQLITE_DONE: return true;
      default:
        __android_log_print(ANDROID_LOG_ERROR, target_name, "Fail to get row: %d", res);
        return false;
   }
 }
  }

} // namespace sio

#endif // SQLITE_ACCESS_HPP
こんな感じで処理していて、他のプロセスやスレッドによって書き込みが阻害されている場合には、何mm sec スリープさせれば良いかわからないけど、とりあえず10mm sec 休ませる事にしているのだが、Android SDK は問答無用で1秒タイムアウト。 詰んだ\(^o^)/ まぁ、1秒にでもしとかないとデッドロック等のケースに対処できないから、しょうがないのかもしれない。  多分、例外が発生したら、もう一回同じ更新をJavaの方でかけに行くのが、いいのかなぁ?

0 件のコメント: