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.4/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, array|void or_queries, 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;
    int numorq = 0;
    int q;
    EJDB * dbo;
    EJCOLL * coll;
    
    bson* orq = NULL;
    
    if(!THISLC->coll)
    {
      pop_n_elems(args);
      Pike_error("Collection not initialized properly.\n");
    }

    if(!THISLC->db)    
    {
      pop_n_elems(args);
      Pike_error("No db!\n");
    }

    if(!getdb(THISLC->db))
    {
      pop_n_elems(args);
      Pike_error("No low db.\n");
    }

    if(flags && flags->type == T_INT)
     {
       _flags = flags->u.integer;
     }
    
    bson_init_finished_data(&_bson, bson_query->str);
    
    if(or_queries)
    {
      struct svalue * sv;
      numorq = or_queries->size;
      orq = malloc(sizeof(bson) * numorq);
      for(q = 0; q < numorq; q++)
      {
        sv = ITEM(or_queries)+q;
        bson_init_finished_data(&(orq[q]), sv->u.string->str);
        
      }
    }
    
    if(bson_hints)
    {
      havehints = 1;
      bson_init_finished_data(&_hints, bson_hints->str);
      
    }    
    
   dbo = getdb(THISLC->db);
   coll = THISLC->coll;
   THREADS_ALLOW();

    if(havehints)
      q1 = ejdbcreatequery(dbo, &_bson, orq, numorq, &_hints);
   else
      q1 = ejdbcreatequery(dbo, &_bson, orq, numorq, NULL);

      res = ejdbqryexecute(coll, q1, &count, _flags, NULL);

   THREADS_DISALLOW();

   if (ejdbecode(dbo) == TCESUCCESS) {  
    pop_n_elems(args);

    if(_flags)
    {
      push_int(count);
    }
    else
    {
    //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);
      }
      f_aggregate(count);

    //Dispose result set
    tclistdel(res);

    //Dispose query
    ejdbquerydel(q1);

     }
    }
    else
    {
      // failure
      tclistdel(res);
      ejdbquerydel(q1);
      if(orq)
        free(orq);
      
      throw_ejdb_error(THISLC->db);
   }
   
 //   bson_destroy(&_bson);
     if(orq)
     { 
//       for(q=0; q < numorq; q++)
//         bson_destroy(orq + q);
     //  free(orq);
     }
  }
  
  /*! @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 LowDatabase
{


DECLARATIONS

#define THISLD ((struct LowDatabase_struct *)get_storage(Pike_fp->current_object, LowDatabase_program))

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)) {
     int ecode;
     char msg2[256];
     const char * msg;
     ecode = ejdbecode(jb);
     msg = ejdberrmsg(ecode);
     snprintf(msg2, sizeof(msg2), "Error creating database object: %s\n", msg);
     Pike_error(msg2); 
  }
  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(THISLD->jb)) {
       RETURN ejdbecode(THISLD->jb);
   }
   else RETURN 0;
}

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

/*! @decl int close()
 */
PIKEFUN int close()
{
   if (!ejdbclose(THISLD->jb)) {
       RETURN ejdbecode(THISLD->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(THISLD->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(THISLD->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(THISLD->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) 
  *!@param name
  *! name of the collection to create.
  *!@param opts
  *!large,
  *!compressed,
  *!records,
  *!cachedrecords
  */
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(THISLD->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;
  }
}


  /*! @decl string low_command(string bson)
   *!
   */
  PIKEFUN string low_command(string bson_cmd)
  {
    bson _bson;

    bson *res; 
    EJDB * dbo;
    struct pike_string * bt;

#ifdef HAVE_EJDBCOMMAND

    if(!THISLD->jb)
    {
      pop_n_elems(args);
      Pike_error("No db!\n");
    }
    
    dbo = THISLD->jb;
    bson_init_finished_data(&_bson, bson_cmd->str);

    THREADS_ALLOW();

    res = ejdbcommand(dbo, &_bson);

    THREADS_DISALLOW();
    pop_stack();

    if(res)
    {
      bt = make_shared_binary_string(bson_data(res), bson_size(res));
      push_string(bt);
      bson_del(res);
    }
    else
    {
      push_int(0);
    }
#else
    pop_stack();
    Pike_error("low_command() is not available. please upgrade your ejdb library.\n");
#endif /* HAVE_EJDBCOMMAND */
  }  

#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);

  /* COMMAND CONSTANTS */
#ifdef HAVE_EJDBCOMMAND

   /*! @decl constant JBJSONEXPORT
    *!
    *! Export data as JSON files instead exporting into BSONs.
    */
  add_integer_constant("JBJSONEXPORT", JBJSONEXPORT, 0);

   /*! @decl constant JBIMPORTUPDATE
    *!
    *! Update existing collection entries with imported ones.
    *! Existing collections will not be recreated.
    *! For existing collections options will not be imported.
    */
  add_integer_constant("JBIMPORTUPDATE", JBIMPORTUPDATE, 0);

   /*! @decl constant JBIMPORTREPLACE
    *! Recreate existing collections and replace all their data
    *! with imported entries. Collections options will be imported.
    *!
    */
  add_integer_constant("JBIMPORTREPLACE", JBIMPORTREPLACE, 0);
#endif /* HAVE_EJDB_COMMAND */
 }
 PIKE_MODULE_INIT
 {
   INIT;
 }

 PIKE_MODULE_EXIT
 {
   EXIT;
 }

 EJDB * getdb(struct object * dbo)
 {
    EJDB * db;
    struct LowDatabase_struct * _db;
    _db = (OBJ2_LOWDATABASE(dbo));
    db = _db->jb;
    return db; 
 }

 void throw_ejdb_error(struct object * db)
 {
   EJDB * _db;
   int ecode;
   char msg2[256];
   const char * msg;
   
   _db = getdb(db);
   ecode = ejdbecode(_db);
   msg = ejdberrmsg(ecode);
   snprintf(msg2, sizeof(msg2), "Error creating database object: %s\n", msg);
   Pike_error(msg2);
 }

 /*! @endmodule
  */

 /*! @endmodule
  */


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