Home modules.gotpike.org
Username: Password: [Create Account]
[Forgot Password?]

Modules

ADT
Database
GTK2
GUI
IP
PiJAX
Public
Sql
Stdio
Subversion
System
Tools
Xosd
lua
v4l2
wx

Recent Changes

Public.Parser.XML2 1.50
Public.ZeroMQ 1.1
Public.Template.Mustache 1.0
Public.Protocols.XMPP 1.4
Sql.Provider.jdbc 1.0

Popular Downloads

Public.Parser.JSON2 1.0
Public.Parser.JSON 0.2
GTK2 2.23
Public.Web.FCGI 1.8
Public.Parser.XML2 1.48


Module Information
Database.EJDB
Viewing contents of Database_EJDB-1.1/ejdb.cmod

/*! @module Database
 */

/*! @module EJDB
 */

#define _GNU_SOURCE

#include "ejdb_config.h"
#include "util.h"

struct EJCOLL { /**> EJDB Collection. */
    char *cname; /**> Collection name. */
    int cnamesz; /**> Collection name length. */
    void *tdb; /**> Collection TCTDB. */
    void *jb; /**> Database handle. */
    void *mmtx; /*> Mutex for method */
};

#if HAVE_TCEJDB_EJDB_H
#include 
#endif /* HAVE_TCEJDB/EJDB_H */

extern struct program * EJDB_program;
struct program * Collection_program;

void lookup_collection_program();
void push_coll(EJCOLL * coll);
void throw_ejdb_error(struct object * db);
EJDB * getdb(struct object * db);

DECLARATIONS

/*! @class LowCollection
 */
PIKECLASS LowCollection
flags ID_PROTECTED;
{
  DECLARATIONS
  CVAR EJCOLL * coll;
  PIKEVAR object db;
  PIKEVAR string name;

#define COLL_DB(X) (EJDB *)(OBJ2_DB(X))
#define OBJ2_COLLECTION(X) ((struct LowCollection_struct *)get_storage(X, LowCollection_program))
#define THISLC ((struct LowCollection_struct *)get_storage(Pike_fp->current_object, LowCollection_program))
  PIKEFUN void create()
  {

  }
  
  PIKEFUN string _sprintf(mixed format, mixed bar)
  {
    push_text("EJDB.Collection(");
    push_string(THISLC->name);
    f_add(2);
    push_text(")");
    f_add(2);
  }

  /*! @decl int delete(string oid)
   */
    PIKEFUN int delete_bson(string oid)
    {
      bson_oid_t _oid;
      int ret;
      
      if(!THISLC->coll)
      {
        pop_n_elems(args);
        Pike_error("Collection not initialized properly.\n");
      }

      if(oid && !oid->len)
      {
        pop_n_elems(args);
        Pike_error("OID cannot be a zero-length string.\n");
      }

      bson_oid_from_string(&_oid, oid->str);

      if((ret = ejdbrmbson(THISLC->coll, &_oid)))
      {
        pop_stack();
        push_int(0);
      }
      else
      {
          int ecode = ejdbecode(getdb(THISLC->db)); 
  //        printf("ecode: %d\n", ecode);
          if (ecode != TCESUCCESS) {
          pop_stack();
    //          printf("throwing error.\n");
              throw_ejdb_error(THISLC->db);
              }
      }
    }

    /*! @decl int set_index(string index, int flags)
     *! Set index for JSON field in EJDB collection.
     */
  PIKEFUN int set_index(string index, int flags)
  {
    int ret;

    if(!THISLC->coll)
    {
        pop_n_elems(args);
        Pike_error("Collection not initialized properly.\n");
    }
  
     ref_push_string(index);
     f_string_to_utf8(1);

     ret = ejdbsetindex(THISLC->coll, (const char *)(Pike_sp[-1].u.string->str), flags);
  
     pop_n_elems(args + 1);
     push_int(ret);
  }

  /*! @decl string load_bson(string oid)
   */
  PIKEFUN string load_bson(string oid)
  {
    bson_oid_t _oid;
    bson * _bson;

    if(!THISLC->coll)
    {
      pop_n_elems(args);
      Pike_error("Collection not initialized properly.\n");
    }

    if(oid && !oid->len)
    {
      pop_n_elems(args);
      Pike_error("OID cannot be a zero-length string.\n");
    }

    bson_oid_from_string(&_oid, oid->str);

    if((_bson = ejdbloadbson(THISLC->coll, &_oid)))
    {
      struct pike_string * bsonStr;
//      bson_print_raw(stdout, bson_data(_bson), 10);
      bsonStr = make_shared_binary_string(bson_data(_bson), bson_size(_bson));
     // bson_destroy(&_bson);
      RETURN bsonStr;
    }
    else
    {
        int ecode = ejdbecode(getdb(THISLC->db)); 
        if (ecode != TCESUCCESS) {
  pop_stack();
            throw_ejdb_error(THISLC->db);
            }
      pop_stack();
      push_int(0);
    }
  }

  /*! @decl string save_bson(string bsonval, string|void oid, int|void merge)
   */
  PIKEFUN string save_bson(string bsonval, string|void oid, int|void merge)
  {
    bson_oid_t _oid;
    bson _bson;
    int _merge = 0;

    if(!THISLC->coll)
    {
      pop_n_elems(args);
      Pike_error("Collection not initialized properly.\n");
    }

    if(oid && !oid->len)
    {
      pop_n_elems(args);
      Pike_error("OID cannot be a zero-length string.\n");
    }
    else if(oid)
    {
      bson_oid_from_string(&_oid, oid->str);
    }

    if(merge->type == T_INT)
    {
      _merge = merge->u.integer;
    }

    bson_init_finished_data(&_bson, bsonval->str);
 //   bson_print_raw(stdout, bson_data(&_bson), 10);
    
    if(ejdbsavebson2(THISLC->coll, &_bson, &_oid, merge))
    {
      struct pike_string * oidStr;
      char c[24];
      bson_oid_to_string((const bson_oid_t *)&_oid, (char *)&c);

      oidStr = make_shared_binary_string(c, strlen(c));
      //bson_destroy(&_bson);
      RETURN oidStr;
    }
    else
    {
          int ecode = ejdbecode(getdb(THISLC->db)); 
          if (ecode != TCESUCCESS) {
            pop_stack();
              throw_ejdb_error(THISLC->db);
              }
    
      RETURN 0;
    }

  }

  /*! @decl array low_find(string bson_query)
   */
  PIKEFUN array low_find(string bson_query, string|void bson_hints, int|void flags)
  {
    int _flags = 0;
    bson _bson;
    bson _hints;
    EJQ *q1;
    uint32_t count;
    TCLIST *res;
    int i;
    int havehints = 0;
    
    if(!THISLC->coll)
    {
      pop_n_elems(args);
      Pike_error("Collection not initialized properly.\n");
    }
    
    if(flags->type == T_INT)
     {
       _flags = flags->u.integer;
     }
    
    bson_init_finished_data(&_bson, bson_query->str);
    if(bson_hints)
    {
      havehints = 1;
      bson_init_finished_data(&_hints, bson_hints->str);
    }    
 //  bson_print_raw(stdout, bson_data(&_bson), 10);
    
    THREADS_ALLOW();
   if(havehints)
      q1 = ejdbcreatequery(getdb(THISLC->db), &_bson, NULL, 0, &_hints);
   else
     q1 = ejdbcreatequery(getdb(THISLC->db), &_bson, NULL, 0, NULL);
   
printf("coll: %p, %p, %p\n", getdb(THISLC->db), q1, THISLC->coll);
      res = ejdbqryexecute(THISLC->coll, q1, &count, _flags, NULL);
 //   fprintf(stderr, "\n\nRecords found: %d\n", count);
   THREADS_DISALLOW();

    pop_stack();

    //Now print the result set records
    for (i = 0; i < TCLISTNUM(res); ++i) {
    struct pike_string * bt;
      char *bsdata = (char *)TCLISTVALPTR(res, i);
      // TODO: find a more efficient approach to this (as in, do we really need the length in order to make the pike_string?)
      bson_init_finished_data(&_bson, bsdata);
//      bson_print_raw(stderr, bsdata, 0);
      
      bt = make_shared_binary_string(bson_data(&_bson), bson_size(&_bson));
      push_string(bt);
      }
    fprintf(stderr, "\n");
    f_aggregate(count);

    //Dispose result set
    tclistdel(res);

    //Dispose query
    ejdbquerydel(q1);
 //   bson_destroy(&_bson);
  }
  
  /*! @decl int begin_transaction()
   *! Begin transaction for EJDB collection.
   */
  PIKEFUN int begin_transaction()
  {
    int ret;
    
    if(!THISLC->coll)
    {
        pop_n_elems(args);
        Pike_error("Collection not initialized properly.\n");
    }
    
    ret = ejdbtranbegin(THISLC->coll);
    
    push_int(ret);
  }

  /*! @decl int abort_transaction()
   *! Abort transaction for EJDB collection.
   */
  PIKEFUN int abort_transaction()
  {
    int ret;
    
    if(!THISLC->coll)
    {
        pop_n_elems(args);
        Pike_error("Collection not initialized properly.\n");
    }
    
    ret = ejdbtranabort(THISLC->coll);
    
    push_int(ret);
  }

  /*! @decl int commit_transaction()
   *! Commit transaction for EJDB collection.
   */
  PIKEFUN int commit_transaction()
  {
    int ret;
    
    if(!THISLC->coll)
    {
        pop_n_elems(args);
        Pike_error("Collection not initialized properly.\n");
    }
    
    ret = ejdbtrancommit(THISLC->coll);
    
    push_int(ret);
  }

  /*! @decl int transaction_status()
   *! Get current transaction status.
   */
  PIKEFUN int transaction_status()
  {
    bool ret;
    bool txstat;
    
    if(!THISLC->coll)
    {
        pop_n_elems(args);
        Pike_error("Collection not initialized properly.\n");
    }
    
    ret = ejdbtranstatus(THISLC->coll, &txstat);
    
    if(ret)
        push_int(txstat);
    else
        Pike_error("Error getting transaction status.\n");
  }
  
  /*! @decl int sync()
   *! Synchronize content of a EJDB collection database with the file on device.
   */
  PIKEFUN int sync()
  {
     if (!ejdbsyncoll(THISLC->coll)) {
         RETURN ejdbecode(getdb(THISLC->db));
     }
     else RETURN 0;
  }
  

  INIT
  {
  }

  EXIT
  {
    if(THIS->db)
      free_object(THIS->db);
  }
}

/*! @endclass
 */

/*! @class Database
 */
PIKECLASS Database
{

DECLARATIONS
CVAR EJDB * jb;

/*! @decl void create(string dbpath, int flags)
 */
PIKEFUN void create(string dbpath, int flags)
{
  static EJDB *jb;
  jb = ejdbnew();
  if (!ejdbopen(jb, dbpath->str, flags)) {
    Pike_error("Unable to open database %s", dbpath->str);
  }
  pop_n_elems(args);
  
  THIS->jb = jb;
  //printf("db: %p\n", THIS->jb);
}

/*! @decl int sync()
 *! Synchronize entire EJDB database and all its collections with storage.
 */ 
PIKEFUN int sync()
{
   if (!ejdbsyncdb(THIS->jb)) {
       RETURN ejdbecode(THIS->jb);
   }
   else RETURN 0;
}

/*! @decl int is_open()
 */
PIKEFUN int is_open()
{
   RETURN (ejdbisopen(THIS->jb));
}

/*! @decl int close()
 */
PIKEFUN int close()
{
   if (!ejdbclose(THIS->jb)) {
       RETURN ejdbecode(THIS->jb);
   }
   else RETURN 0;
}

/*! @decl int delete_collections(string collection, int unlink)
 *! Removes collections specified by 'name'.
 */
PIKEFUN array delete_collection(string name, int unlink)
{
  int ret;
 
  ref_push_string(name);
  f_string_to_utf8(1);

  ret = ejdbrmcoll(THIS->jb, Pike_sp[-1].u.string->str, unlink);
  pop_n_elems(args + 1);
  
  push_int(ret);
} 

/*! @decl array(string) get_collections()
 */
PIKEFUN array get_collections()
{
  TCLIST *colls;
  int i;
  struct pike_string * cn;

  colls = ejdbgetcolls(THIS->jb);
  
  for (i = 0; i < TCLISTNUM(colls); ++i) {
    EJCOLL *coll = (EJCOLL *)TCLISTVALPTR(colls, i);
    cn = make_shared_binary_string(coll->cname, coll->cnamesz);
    push_string(cn);
    f_utf8_to_string(1);
  }
  
  f_aggregate(TCLISTNUM(colls));

  //Dispose result set
  tclistdel(colls);
}

/*! @decl object get_collection(string name)
 */
PIKEFUN object get_collection(string name)
{
  EJCOLL* coll;
  
  ref_push_string(name);
  f_string_to_utf8(1);

  coll = ejdbgetcoll(THIS->jb, (Pike_sp[-1].u.string->str));

printf("coll: %p\n", coll);
  if(!coll)
  {
    pop_n_elems(args + 1);
    push_int(0);
    return;
  }
  else
  {
    pop_n_elems(args + 1);
    push_coll(coll);
    return;
  }
}

/*! @decl object create_collection(string name, mapping|void opts) 
  *! OPTIONS:
  *!large
  *!compressed
  *!records
  *!cachcedrecords
  */
PIKEFUN object create_collection(string name, mapping|void opts)
{
  EJCOLL* coll;
  EJCOLLOPTS _opts;
  struct svalue * sv;

  ref_push_string(name);
  f_string_to_utf8(1);
  name = Pike_sp[0-1].u.string;

  if(opts)
  {
    sv = simple_mapping_string_lookup(opts, "large");
    
    if(sv && sv->type == T_INT)
    {
      _opts.large = (sv->u.integer?1:0);
    }
    
    sv = simple_mapping_string_lookup(opts, "compressed");

    if(sv && sv->type == T_INT)
    {
      _opts.compressed = (sv->u.integer?1:0);
    }

    sv = simple_mapping_string_lookup(opts, "records");

    if(sv && sv->type == T_INT)
    {
      _opts.records = (sv->u.integer);
    }

    sv = simple_mapping_string_lookup(opts, "cachedrecords");

    if(sv && sv->type == T_INT)
    {
      _opts.cachedrecords = (sv->u.integer?1:0);
    }
  }

  coll = ejdbcreatecoll(THIS->jb, (name->str), &_opts);
  if(!coll)
  {
    pop_n_elems(args + 1);
    push_int(0);
    return;
  }
  else
  {
    pop_n_elems(args + 1);
    push_coll(coll);
    return;
  }
}

#define OBJ2_COLLECTION(X) ((struct LowCollection_struct *)get_storage(X, LowCollection_program))

void push_coll(EJCOLL * coll)
{
  struct object * c;
  struct pike_string * name;
  if(!Collection_program)
    lookup_collection_program();
  c = clone_object(Collection_program, 0);
  name = make_shared_binary_string(coll->cname, coll->cnamesz);
  push_string(name);
  f_utf8_to_string(1);
  name = Pike_sp[-1].u.string;
  add_ref(name);
  pop_stack();
  OBJ2_COLLECTION(c)->coll = coll;
  OBJ2_COLLECTION(c)->db = this_object();
  OBJ2_COLLECTION(c)->name = name;
  add_ref(OBJ2_COLLECTION(c)->db);
  push_object(c);
}

void lookup_collection_program()
{
  push_text("Database.EJDB.Collection");
  SAFE_APPLY_MASTER("resolv", 1 );
  if(Pike_sp[-1].type != T_PROGRAM)
  {
    Pike_error("Unable to load class Database.EJDB.Collection.\n");
  }
  
  Collection_program = Pike_sp[-1].u.program;
  add_ref(Collection_program);
  pop_stack();
}

INIT
{
}

EXIT
{
  EJDB * jb;
  jb = THIS->jb;
  if(jb && ejdbisopen(jb))
  { 
    printf("closing\n");
    ejdbclose(jb);
  }
  if(jb)
  {
    printf("freeing\n");
    ejdbdel(jb);
  }
  
  if(Collection_program)
    free_program(Collection_program);
}

}

/*! @endclass
 */

 EXTRA
 {
   /* DB OBJECT CREATION CONSTANTS */

   /*! @decl constant JBOREADER
     *! Create: Open as a reader.
     */
   add_integer_constant("JBOREADER", JBOREADER, 0);

   /*! @decl constant JBOWRITER 
    *! Create: Open as a writer. 
   */
   add_integer_constant("JBOWRITER", JBOWRITER, 0);

   /*! @decl constant JBOCREAT 
    *! Create: Create if db file not exists.
    */
   add_integer_constant("JBOCREAT", JBOCREAT, 0);

   /*! @decl constant JBOTRUNC 
    *! Create: Truncate db on open.
    */
   add_integer_constant("JBOTRUNC", JBOTRUNC, 0);

   /*! @decl constant JBONOLCK 
    *! Create: Open without locking.
    */
   add_integer_constant("JBONOLCK", JBONOLCK, 0);

   /*! @decl constant JBOLCKNB
    *! Create: Lock without blocking.
    */
   add_integer_constant("JBOLCKNB", JBOLCKNB, 0);

   /*! @decl constant JBOTSYNC 
    *! Create: Synchronize every transaction. 
    */
   add_integer_constant("JBOTSYNC", JBOTSYNC, 0);


   /* INDEX CONSTANTS */

   /*! @decl constant JBIDXDROP 
    *! Index: Drop index. 
    */
   add_integer_constant("JBIDXDROP", JBIDXDROP, 0);

   /*! @decl constant JBIDXDROPALL 
    *! Index: Drop index for all types. 
    */
   add_integer_constant("JBIDXDROPALL", JBIDXDROPALL, 0);

   /*! @decl constant JBIDXOP 
    *! Index: Optimize index. 
    */
   add_integer_constant("JBIDXOP", JBIDXOP, 0);

   /*! @decl constant JBIDXREBLD 
    *! Index: Rebuild index. 
    */
   add_integer_constant("JBIDXREBLD", JBIDXREBLD, 0);

   /*! @decl constant JBIDXNUM 
    *! Index: Number index. 
    */
   add_integer_constant("JBIDXNUM", JBIDXNUM, 0);

   /*! @decl constant JBIDXSTR 
    *! Index: String index. 
    */
   add_integer_constant("JBIDXSTR", JBIDXSTR, 0);

   /*! @decl constant JBIDXARR 
    *! Index: Array token index. 
    */
   add_integer_constant("JBIDXARR", JBIDXARR, 0);

   /*! @decl constant JBIDXISTR 
    *! Index: Case insensitive string index. 
    */
   add_integer_constant("JBIDXISTR", JBIDXISTR, 0);


   /* QUERY CONSTANTS */

   /*! @decl constant JBQURYCOUNT
    *! Query only count(*) in find()
    */
   add_integer_constant("JBQRYCOUNT", JBQRYCOUNT, 0);
 }
 PIKE_MODULE_INIT
 {
   INIT;
 }

 PIKE_MODULE_EXIT
 {
   EXIT;
 }

 EJDB * getdb(struct object * db)
 {
    struct Database_struct * _db;
    _db = (OBJ2_DATABASE(db));
    return _db->jb; 
 }

 void throw_ejdb_error(struct object * db)
 {
   EJDB * _db;
   int ecode;
   
   _db = getdb(db);
   ecode = ejdbecode(_db);
//printf("throwing error!\n");
   Pike_error(ejdberrmsg(ecode));
 }

 /*! @endmodule
  */

 /*! @endmodule
  */


gotpike.org | Copyright © 2004 - 2019 | Pike is a trademark of Department of Computer and Information Science, Linköping University