#include "dbalnimage.h"

int bdb_compare_int(Db *dbp, const Dbt *a, const Dbt *b);
int bdb_getiteration(Db *sdbp, const Dbt *pkey, const Dbt *pdata, Dbt *skey);
int bdb_image_getid(Db *sdbp, const Dbt *pkey, const Dbt *pdata, Dbt *skey);
int bdb_image_getchannel(Db *sdbp, const Dbt *pkey, const Dbt *pdata, Dbt *skey);

///custome int compare
int bdb_compare_int(Db *dbp, const Dbt *a, const Dbt *b)
{
  dbp = NULL;
  int ai, bi;
  // Returns: 
  // < 0 if a < b 
  // = 0 if a = b 
  // > 0 if a > b 
  memcpy(&ai, a->get_data(), sizeof(int)); 
  memcpy(&bi, b->get_data(), sizeof(int)); 
  return (ai - bi); 
}

int bdb_getiteration(Db *sdbp, const Dbt *pkey,
                     const Dbt *pdata, Dbt *skey)
{
  int *d;
  d = (int*)(pdata->get_data());
  skey->set_data( d );
  skey->set_size( sizeof(int) );
  sdbp = NULL;
  pkey = NULL;
  return 0;
}

int bdb_image_getid(Db *sdbp, const Dbt *pkey,
                    const Dbt *pdata, Dbt *skey)
{
  dbalnimage::alignimg_key *d;
  d = (dbalnimage::alignimg_key*)(pkey->get_data());
  skey->set_data( &(d->id) );
  skey->set_size( sizeof(int) );
  sdbp = NULL;
  pdata = NULL;
  return 0;
}

int bdb_image_getchannel(Db *sdbp, const Dbt *pkey,
                         const Dbt *pdata, Dbt *skey)
{
  dbalnimage::alignimg_key *d;
  d = (dbalnimage::alignimg_key*)(pkey->get_data());
  skey->set_data( &(d->channel) );
  skey->set_size( sizeof(short int) );
  sdbp = NULL;
  pdata = NULL;
  return 0;
}

dbalnimage::dbalnimage()
{
  mydb = mydb_image = mydb_iter_idx = NULL;
  dbname = "imagealn_set.db";
  dbfiles.clear();
  dbfiles.push_back( dbname );
  dbfiles.push_back( "imagealn_mask.db" );
  dbfiles.push_back( "imagealn_image.db" );
  dbfiles.push_back( "imagealn_conn.db" );
  dbfiles.push_back( "imagealn_set_iter_idx.db" );
  dbfiles.push_back( "imagealn_image_id_idx.db" );
  dbfiles.push_back( "imagealn_image_channel_idx.db" );
}

dbalnimage::~dbalnimage()
{
  close();
}

int dbalnimage::close()
{
  if( mydb != NULL )
    {
      mydb->sync(0);
      mydb_image->sync(0);
      mydb_iter_idx->sync(0);
      mydb_image_id_idx->sync(0);
      mydb_image_channel_idx->sync(0);
      mydb_image_mask->sync(0);
      mydb_image_conn->sync(0);

      mydb_image_id_idx->close(0);
      mydb_image_channel_idx->close(0);
      mydb_iter_idx->close(0);
      mydb_image->close(0);
      mydb_image_mask->close(0);
      mydb_image_conn->close(0);
      mydb->close(0);

      delete mydb;
      delete mydb_image_conn;
      delete mydb_image;
      delete mydb_image_mask;
      delete mydb_image_id_idx;
      delete mydb_image_channel_idx;
      delete mydb_iter_idx;

    }
  mydb = mydb_image_conn = mydb_image = mydb_image_mask =
    mydb_image_id_idx = mydb_image_channel_idx =
    mydb_iter_idx = NULL;
  return 0;
}

int dbalnimage::init( DbEnv *env )
{
  close();
  dbenvp = env;
  lsn_reset();
  mydb = new Db(dbenvp, 0);
  mydb_image = new Db(dbenvp, 0);
  mydb_iter_idx = new Db(dbenvp, 0);
  mydb_image_id_idx = new Db(dbenvp, 0);
  mydb_image_channel_idx = new Db(dbenvp, 0);
  mydb_image_mask = new Db(dbenvp, 0 );
  mydb_image_conn = new Db(dbenvp, 0);

  mydb->set_bt_compare(bdb_compare_int);
  mydb_iter_idx->set_flags(DB_DUP);
  mydb_iter_idx->set_bt_compare(bdb_compare_int);
  mydb_image_id_idx->set_flags(DB_DUP);
  mydb_image_channel_idx->set_flags(DB_DUP);
  int ret;
  //  mydb->set_pagesize( 1024*16 );

  unsigned int openflag, myopenflag, myassflag;
  env->get_open_flags( &openflag );
  if( (openflag & DB_INIT_TXN) == 0 )
    {
      myopenflag = DB_CREATE | DB_THREAD;
      myassflag = DB_CREATE;
    }
  else
    {
      myopenflag = DB_CREATE | DB_AUTO_COMMIT | DB_THREAD;
      myassflag = DB_CREATE | DB_AUTO_COMMIT;
    }

  ret = mydb->open( NULL, dbname.c_str(), NULL,
                    DB_BTREE, myopenflag, 384);
  if (ret != 0 )
    {
      std::cout << "ERROR in dbaln open\n";
      exit(0);
    }

  ret = mydb_iter_idx->open( NULL, "imagealn_set_iter_idx.db", NULL, DB_BTREE,
                             myopenflag, 384);
  if (ret != 0 )
    {
      std::cout << "ERROR in dbaln open\n";
      exit(0);
    }

  mydb->associate( NULL, mydb_iter_idx,
                   bdb_getiteration, myassflag);
  
  ret = mydb_image->open( NULL, "imagealn_image.db", NULL,
                          DB_BTREE, myopenflag, 384);
  if (ret != 0 )
    {
      std::cout << "ERROR in dbaln open\n";
      exit(0);
    }
  
  ret = mydb_image_id_idx->open( NULL, "imagealn_image_id_idx.db", NULL,
                                 DB_BTREE, myopenflag, 384);
  if (ret != 0 )
    {
      std::cout << "ERROR in dbaln open\n";
      exit(0);
    }
  ret = mydb_image_channel_idx->open( NULL, "imagealn_image_channel_idx.db",
                                      NULL, DB_BTREE, myopenflag, 384);
  if (ret != 0 )
    {
      std::cout << "ERROR in dbaln open\n";
      exit(0);
    }
  mydb_image->associate( NULL, mydb_image_id_idx,
                         bdb_image_getid, myassflag);
  mydb_image->associate( NULL, mydb_image_channel_idx,
                         bdb_image_getchannel, myassflag);
  
  ret = mydb_image_mask->open( NULL, "imagealn_mask.db", NULL, 
                               DB_BTREE, myopenflag, 384);
  if (ret != 0 )
    {
      std::cout << "ERROR in dbaln open\n";
      exit(0);
    }
  ret = mydb_image_conn->open( NULL, "imagealn_conn.db", NULL,
                               DB_BTREE, myopenflag, 384);
  if (ret != 0 )
    {
      std::cout << "ERROR in dbaln open\n";
      exit(0);
    }
  return 0;
}

int dbalnimage::create_firstaln_set( std::vector< int > &row,
                                     std::vector< int > &col,
                                     std::vector< int > &x,
                                     std::vector< int > &y)
{
  std::vector< int > ids;
  for( unsigned i = 0; i < row.size(); i++ )
    {
      ids.push_back( encodeto1d( row[i], col[i] ) );
    }
  int ret;
  ret = create_align( 0, ids, x, y );
  return ret;
}

int dbalnimage::create_alignset_data( int iteration,
                                      std::vector< int > &ids,
                                      std::vector< int > &xtrans,
                                      std::vector< int > &ytrans,
                                      char **data, int &len )
{
  int numitems;
  numitems = (int)ids.size();
  len = numitems*(3*sizeof(int))+2*sizeof(int);
  char *out;
  out = new char[len];
  memcpy( out, &iteration, sizeof(int) );
  memcpy( out+sizeof(int), &numitems, sizeof(int));

  char *d;
  d = out+(2*sizeof(int));
  for( unsigned i = 0; i < ids.size(); i++ )
    {
      memcpy( d, &(ids[i]), sizeof(int) );
      memcpy( d+sizeof(int), &(xtrans[i]), sizeof(int) );
      memcpy( d+(2*sizeof(int)), &(ytrans[i]), sizeof(int) );
      d = d + (3*sizeof(int));
    }
  *data = out;
  return 0;
}

int dbalnimage::get_aligned_image( int aid, int slice,
                                   int channel, image2d *image )
{
  wavelet wlt;
  wltcompress wltc;
  Dbt rec;
  //  Dbt key;
  alignimg_key ak, ak1;
  char *buffer;
  int buflen = 1024*1024*4;
  buffer = new char[buflen];

  rec.set_data( buffer );
  rec.set_flags( DB_DBT_USERMEM );
  rec.set_ulen( buflen );

  ak.id = aid;
  ak.slice = slice;
  ak.channel = channel;
  ak1 = ak;
  Dbt key( &ak, sizeof(alignimg_key) );
  /*
  key.set_data( &ak );
  key.set_flags( DB_DBT_USERMEM );
  key.set_size( sizeof(alignimg_key) );
  key.set_ulen( sizeof(alignimg_key) );
  */
  int ret;
  int flag;
  flag = 1;
  while( flag == 1 )
    {
      try
        {
          ret = mydb_image->get(NULL, &key, &rec, 0);
          flag = 0;
        }
      catch( DbException &e) 
        {   
          if(e.get_errno() == DB_BUFFER_SMALL )
            {
              delete [] buffer;
              buflen = ( (rec.get_size()/1024)+2 )*1024;
              buffer = new char[buflen];
              rec.set_ulen(buflen);
              rec.set_data(buffer);
              flag = 1;
            }
          else
            {
              std::cout << "DB EXCEPTION: " << e.what() << "\n";
              exit(0);
            }
        }
    }
  
  if(ret != 0)
    {
      delete [] buffer;
      std::cout << "failed to get aligned image\n";
      std::cout << ak.id << " slice: " << ak.slice 
                << " channel: " << ak.channel << "\n";
      std::cout << "ret: " << ret << "\n";
      return ret;
    }
  if( rec.get_size() == 0 )
    {
      std::cout << "ERROR record size = 0\n";
      exit(0);
    }
  wltc.decompress( wlt, buffer, rec.get_size() );
  wlt.istrans( *image, 1 );
#ifdef __DEBUG__
  std::cout << "read image of size: " << image->getheight() << " "
            << image->getwidth() << "\n";
#endif
  image->dividefactor( QUANTIZEFACTOR );
  delete [] buffer;
  return ret;
}

int dbalnimage::add_aligned_image( int aid, int slice,
                                   int channel, image2d *image )
{
  image2d myim;
  wavelet wlt;
  wltcompress wltc;
  Dbt rec;
  Dbt key;
  alignimg_key ak;
  int cs;

  myim.load( image );
  
  myim.multquantize( QUANTIZEFACTOR );
  myim.checkint();
  wlt.analyze( myim, 1 );
  wltc.compress(wlt);
  cs = wltc.compresssize();
  rec.set_data( wltc.compressdata() );
  rec.set_size( cs );
  ak.id = aid;
  ak.slice = slice;
  ak.channel = channel;
  key.set_data( &ak );
  key.set_size( sizeof(alignimg_key) );
  int ret;
  std::cout << "adding aligned image: " << aid << " slice " 
            << slice << " channel " << channel << " " 
            << image->getheight() << "x" 
            << image->getwidth() << " " << cs << " bytes\n";
  try
    {
      ret = mydb_image->put(NULL, &key, &rec, 0);
    }
  catch( DbException &e) 
    {
      std::cout << "DB EXCEPTION: " << e.what() << "\n";
      exit(0);
    }
  
  /// try to retrieve the file again
  char *buffer;
  buffer = new char[cs];
  rec.set_data( buffer );
  rec.set_ulen(cs);
  rec.set_flags( DB_DBT_USERMEM );
  
  try
    {
      ret = mydb_image->get(NULL, &key, &rec, 0);
    }
  catch( DbException &e) 
    {
      std::cout << "DB EXCEPTION: " << e.what() << "\n";
      exit(0);
    }
  if( ret != 0 )
    {
      std::cout << "SET FAILED!!!\n";
      exit(0);
    }
  delete [] buffer;
  alignimg_key *nak;
  nak = (alignimg_key*)key.get_data();
  std::cout << "SET: " << nak->id << " " << nak->slice << " " << nak->channel << "\n";

  return 0;
}

int dbalnimage::get_aligned_mask( int aid, image2d *image )
{
  wavelet wlt;
  wltcompress wltc;
  Dbt rec;

  char *buffer;
  int buflen = 1024*1024*4;
  buffer = new char[buflen];

  rec.set_data( buffer );
  rec.set_flags( DB_DBT_USERMEM );
  rec.set_ulen( buflen );

  int kk;
  kk = aid;
  Dbt key(&kk, sizeof(int));

  int ret;
  int flag;
  flag = 1;
  while( flag == 1 )
    {
      try
        {
          ret = mydb_image_mask->get(NULL, &key, &rec, 0);
          flag = 0;
        }
      catch( DbException &e) 
        {   
          if(e.get_errno() == DB_BUFFER_SMALL )
            {
              std::cout << "buffer too small\n";
              delete [] buffer;
              buflen = ( (rec.get_size()/1024)+2 )*1024;
              buffer = new char[buflen];
              rec.set_ulen(buflen);
              rec.set_data(buffer);
              flag = 1;
            }
          else
            {
              std::cout << "DB EXCEPTION: " << e.what() << "\n";
              exit(0);
            }
        }
    }

  if(ret != 0)
    {
      delete [] buffer;
      std::cout << "failed to get aligned map\n";
      std::cout << aid << "\n";
      if( ret == DB_NOTFOUND )
        std::cout << "ERROR: key not found\n"
                  << sizeof(int) << "\n";
      std::cout << "ret: " << ret << "\n";
      exit(0);
    }
  std::cout << "got record of size: " << rec.get_size() << "\n";
  if( rec.get_size() == 0 )
    {
      std::cout << "ERROR got record of size 0\n";
      exit(0);
    }
  wltc.decompress( wlt, buffer, rec.get_size() );
  wlt.istrans( *image, 1 );
  std::cout << "imagesz: " << image->getheight() << " "
            << image->getwidth() << "\n";
  delete [] buffer;
  image->dividefactor( QUANTIZEFACTOR );
  return ret;
}

int dbalnimage::set_aligned_mask( int aid, image2d *image )
{
  image2d myim;
  wavelet wlt;
  wltcompress wltc;
  Dbt rec;
  Dbt key;
  int cs;

  myim.load( image );
  myim.multquantize( QUANTIZEFACTOR );
  wlt.analyze( myim, 1 );
  wltc.compress(wlt);
  cs = wltc.compresssize();
  rec.set_data( wltc.compressdata() );
  rec.set_size( cs );
  std::cout << "adding mask image: " << aid << " " 
            << image->getheight() << "x" 
            << image->getwidth() << " " << cs << " bytes\n";
  key.set_data( &aid );
  key.set_size( sizeof(int) );
  int ret;
  try
    {
      ret = mydb_image_mask->put(NULL, &key, &rec, 0);
    }
  catch( DbException &e) 
    {   
      std::cout << "DB EXCEPTION: " << e.what() << "\n";
      exit(0);
    }
  return 0;
}

int dbalnimage::get_imconnection( int iteration,
                                  std::vector< image_conn > &connections )
{
  image_conn *data;
  int bsz = 32;
  Dbt rec, key;
  key.set_data( &iteration );
  key.set_size( sizeof(int) );
  data = new image_conn[bsz];
  rec.set_data( data );
  rec.set_ulen( sizeof( image_conn )*bsz );
  rec.set_flags( DB_DBT_USERMEM );
  int flag = 1;
  int ret;
  while( flag == 1)
    {
      try
        {
          ret = mydb_image_conn->get( NULL, &key, &rec, 0 );
          flag = 0;
        }
      catch( DbException &e )
        {
          if(e.get_errno() == DB_BUFFER_SMALL )
            {
              delete [] data;
              bsz = ( ( rec.get_size()/sizeof(image_conn) ) +2 );
              data = new image_conn[bsz];
              rec.set_ulen(sizeof(image_conn)*bsz);
              rec.set_data(data);
              flag = 1;
            }
          else
            {
              std::cout << "DB GET ERROR" << "\n";
              std::cout << e.what() << "\n";
              exit(0);
            }
        }
    }
  bsz =  rec.get_size()/sizeof( image_conn );
#ifdef __DEBUG__
  std::cout << "got " << bsz << " image links\n";
#endif

  connections.clear();
  for( int i = 0; i < bsz; i++ )
    connections.push_back( data[i] );
    
  delete [] data;
  return ret;
}

int dbalnimage::set_imconnection( int iteration,
                                  std::vector< image_conn > &connections )
{
  image_conn *data;
  if( connections.size() > 0 )
    data = new image_conn [connections.size()];
  else
    data = NULL;
  
  for( unsigned i = 0; i < connections.size(); i++ )
    data[i] = connections[i];
  int dummy;
  dummy = 0;
  Dbt rec, key;
  key.set_data( &iteration );
  key.set_size( sizeof(int) );
  if( data == NULL )
    {
      rec.set_data( &dummy ); 
      rec.set_size( sizeof(int) );
    }
  else
    {
      rec.set_data( data );
      rec.set_size( sizeof(image_conn)*connections.size() );
    }
  int ret;
  try
    {
      ret = mydb_image_conn->put(NULL, &key, &rec, 0 );
    }
  catch( DbException &e )
    {
      std::cout << "DB EXCEPTION: " << e.what() << "\n";
      exit(0);
    }

  if( data != NULL )
    delete [] data;
  
  return 0;
}

int dbalnimage::deleteconnection( int iter )
{
  Dbt k;
  int i;
  i = iter;
  k.set_data( &i );
  k.set_size( sizeof(int) );
  int ret;
  ret = mydb_image_conn->del(NULL, &k, 0 );
  return ret;
}

int dbalnimage::get_alignedset_data( int aid,
                                     int &iteration,
                                     std::vector< int > &ids,
                                     std::vector< int > &xtrans,
                                     std::vector< int > &ytrans )
{
  Dbt k( &aid, sizeof(int) );
  Dbt v;
  char *buffer;
  buffer = new char[1024];
  
  k.set_flags(DB_DBT_USERMEM);
  k.set_data( &aid );
  k.set_size( sizeof(int) );
  k.set_ulen( sizeof(int) );
  
  v.set_flags(DB_DBT_USERMEM);
  v.set_data(buffer);
  v.set_ulen( 1024 );
  int ret;
  int flag;
  int buflen;
  std::cout << "reading aligned set data " << aid << "\n";
  flag = 1;
  while( flag == 1 )
    {
      try
        {
          ret = mydb->get(NULL, &k, &v, 0);
          flag = 0;
        }
      catch( DbException &e) 
        {   
          if(e.get_errno() == DB_BUFFER_SMALL )
            {
              delete [] buffer;
              buflen = v.get_size()*2;
              buffer = new char[buflen];
              v.set_ulen(buflen);
              v.set_data(buffer);
              flag = 1;
              std::cout << "reallocating " << buflen << "\n";
            }
          else
            {
              std::cout << "DB EXCEPTION: " << e.what() << "\n";
              exit(0);
            }
        }
    }
  if( ret != 0 )
    {
      std::cout << "aid not found: " << aid << "\n";
      exit(0);
    }
  std::cout << "read " << v.get_size() << " bytes\n";
  read_alignset_data( buffer, v.get_size(), iteration, ids, xtrans, ytrans );
  delete [] buffer;
  return 0;
}

int dbalnimage::read_alignset_data( char *data, int len,
                                    int &iteration,
                                    std::vector< int > &ids,
                                    std::vector< int > &xtrans,
                                    std::vector< int > &ytrans )
{
  int numitems;
  memcpy( &iteration, data, sizeof(int) );
  memcpy( &numitems, data+sizeof(int), sizeof(int) );

  if( (int)(numitems*(3*sizeof(int))+2*sizeof(int)) != len )
    {
      std::cout << "read align data len error\n";
      exit(0);
    }
  int *vec;
  vec = (int*)(data+(2*sizeof(int)));
  ids.clear();
  xtrans.clear();
  ytrans.clear();
  for( int i = 0; i < numitems; i++ )
    {
      ids.push_back( vec[i*3] );
      xtrans.push_back( vec[i*3+1] );
      ytrans.push_back( vec[i*3+2] );
    }
  return 0;
}

int dbalnimage::create_align( int iteration, 
                              std::vector< int > &ids,
                              std::vector< int > &x,
                              std::vector< int > &y )
{
  Dbt k, v;
  Dbc *cur;
  cur = NULL;
  int myid;
  k.set_data( &myid );
  k.set_flags(DB_DBT_USERMEM);
  k.set_ulen( sizeof( int ) );
  char *buffer;
  buffer = new char[1024];
  v.set_data( buffer );
  v.set_flags(DB_DBT_USERMEM | DB_DBT_PARTIAL );
  v.set_ulen( 1024 );
  v.set_doff(0);
  v.set_dlen(0);
  try
    {
      int ret;
      ret = mydb->cursor(NULL, &cur, 0 );
      ret = cur->get( &k, &v, DB_LAST );
      if(ret != 0 )
        {
          std::cout << "inserting first item\n";
          myid = 0;
        }
      else
        {
          std::cout << "inserting " << myid << "\n";
          myid = myid + 1;
        }
    }
  catch(DbException &e)
    {
      std::cout << "fail in dbalnimage create set, getid\n";
      std::cout << e.what() << "\n";
      exit(0);
    }
  cur->close();
  delete [] buffer;
  int dlen;
  create_alignset_data( iteration, ids, x, y, &buffer, dlen);
  v.set_data( buffer );
  v.set_flags(DB_DBT_USERMEM );
  v.set_size( dlen );

  std::cout << "inserting data of length " << dlen << "\n";

  Dbt k1( &myid, sizeof(int) );

  try
    {
      std::cout << "inserting " << myid << "\n";
      mydb->put( NULL, &k1, &v, 0 );
      std::cout << "inserted new setid " << myid << "\n";
    }
  catch(DbException &e)
    {
      std::cout << "fail in dbalnimage create set put\n";
      std::cout << e.what() << "\n";
      exit(0);
    }
  delete [] buffer;
  return myid;
}

int dbalnimage::getslices(int aid, std::vector< int > &sli )
{
  std::set< int > ts;
  get_slices( aid, ts );
  for( std::set<int>::iterator it = ts.begin(); it != ts.end(); it++ )
    sli.push_back( *it );
  return 0;
}

int dbalnimage::get_slices( int aid, std::set< int > &sli )
{
  sli.clear();
  Dbc *cur;
  Dbt key;
  Dbt rec;
  Dbt pkey;
  alignimg_key id;
  mydb_image_id_idx->cursor( NULL, &cur, 0 );
  rec.set_data( NULL );
  rec.set_ulen(0);
  rec.set_dlen(0);
  rec.set_doff(0);
  rec.set_flags( DB_DBT_USERMEM | DB_DBT_PARTIAL );

  pkey.set_data( &id );
  pkey.set_flags( DB_DBT_USERMEM );
  pkey.set_ulen( sizeof(alignimg_key) );

  key.set_data( &aid );
  key.set_ulen( sizeof(int) );
  key.set_flags( DB_DBT_USERMEM );
  key.set_size( sizeof(int) );

  int ret;

  ret = cur->pget( &key, &pkey, &rec, DB_SET );
  while( ret == 0 )
    {
      sli.insert( id.slice );
      ret = cur->pget( &key, &pkey, &rec, DB_NEXT_DUP );
    }

  cur->close();
  return 0;
}

int dbalnimage::getchannels(int aid, std::vector< int > &chs )
{
  std::set< int > ts;
  get_channels( aid, ts );
  for( std::set<int>::iterator it = ts.begin(); it != ts.end(); it++ )
    chs.push_back( *it );
  return 0;
}

int dbalnimage::get_channels( int aid, std::set< int > &chs )
{
  chs.clear();
  Dbc *cur;
  Dbt key;
  Dbt rec;
  Dbt pkey;
  alignimg_key id;
  mydb_image_id_idx->cursor( NULL, &cur, 0 );
  char buf[1024];
  rec.set_data( buf );
  rec.set_ulen(1024);
  rec.set_dlen(0);
  rec.set_doff(0);
  rec.set_flags( DB_DBT_USERMEM | DB_DBT_PARTIAL );

  pkey.set_data( &id );
  pkey.set_flags( DB_DBT_USERMEM );
  pkey.set_ulen( sizeof(alignimg_key) );
  
  key.set_data( &aid );
  key.set_ulen( sizeof(int) );
  key.set_flags( DB_DBT_USERMEM );
  key.set_size( sizeof(int) );
  std::cout << "trying to find aid: " << aid << "\n";
  int ret;
  try
    {
      ret = cur->pget( &key, &pkey, &rec, DB_SET );
      while( ret == 0 )
        {
          chs.insert( id.channel );
          ret = cur->pget( &key, &pkey, &rec, DB_NEXT_DUP );
        }
    }
  catch (DbException &e )
    {
      std::cout << e.what() << "\n";
      std::cout << "need " <<  key.get_size() << "bytes\n";
      std::cout << "allocated " << sizeof( alignimg_key );
      exit(0);
    }

  cur->close();
  return 0;
}

int dbalnimage::checkaid( int aid )
{
  Dbt k, v;
  char buffer[1024];
  v.set_data( buffer );
  v.set_ulen( sizeof(int)*1024 );
  v.set_flags(DB_DBT_USERMEM | DB_DBT_PARTIAL );
  v.set_doff(0);
  v.set_dlen(0);
  int a;
  a = aid;
  k.set_data( &a);
  k.set_flags(DB_DBT_USERMEM);
  k.set_size( sizeof(int) );
  k.set_ulen( sizeof(int) );
  int ret;
  try
    {
      ret = mydb->get( NULL, &k, &v, 0 );
    }
  catch (DbException &e )
    {
      std::cout << e.what() << "\n";
      exit(0);
    }
  if( ret == 0 )
    return 1;
  return 0;
}

int dbalnimage::deleteaid( int daid )
{
  Dbt k, v;
  v.set_data( NULL );
  v.set_ulen( 0 );
  v.set_flags(DB_DBT_USERMEM | DB_DBT_PARTIAL );
  v.set_doff(0);
  v.set_dlen(0);
  int a;
  a = daid;
  k.set_data( &a);
  k.set_flags(DB_DBT_USERMEM);
  k.set_size( sizeof(int) );
  k.set_ulen( sizeof(int) );
  Dbc *cur;
  DbTxn *txn;
  dbenvp->txn_begin(NULL, &txn, 0 );
  mydb_image_id_idx->cursor( txn, &cur, 0 );
  int ret;
  ret = cur->get( &k, &v, DB_SET );
  int dc;
  dc = 0;
  // delete the images
  while( ret == 0 )
    {
      dc++;
      cur->del(0);
      ret = cur->get( &k, &v, DB_SET );
    }
  std::cout << "deleted " << dc << " images\n";
  cur->close();
  a = daid;
  // delete the meta data
  mydb->del(txn, &k, 0 );
  txn->commit( 0 );
  return 0;
}

int dbalnimage::get_align_sets( int iteration,
                                std::vector<int> &ids)
{
  ids.clear();
  int *buffer;
  buffer = new int[1024];
  Dbc *cur;
  Dbt k, v, pk;
  int aid, ret;
  pk.set_data( &aid );
  pk.set_ulen( sizeof(int) );
  pk.set_flags(DB_DBT_USERMEM);

  k.set_data( &iteration );
  k.set_ulen( sizeof(int) );
  k.set_flags(DB_DBT_USERMEM);

  v.set_data( buffer );
  v.set_ulen( sizeof(int)*1024 );
  v.set_flags(DB_DBT_USERMEM | DB_DBT_PARTIAL);
  v.set_doff(0);
  v.set_dlen(0);

  mydb_iter_idx->cursor( NULL, &cur, 0 );
  ret = cur->pget( &k, &pk, &v, DB_SET );
  while( ret == 0 )
    {
      ids.push_back( aid );
      ret = cur->pget( &k, &pk, &v, DB_NEXT_DUP );
    }
  cur->close();

  delete [] buffer;

  return 0;
}

