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.MongoDB
Viewing contents of Database_MongoDB-1.1/mongodb.cmod

/*! @module Database
 */

/*! @module MongoDB
 */

#define _GNU_SOURCE

#include "mongodb_config.h"
#include "util.h"

/*#if HAVE_MONGO_H
*/
#include 
/*#endif*/ /* HAVE_MONGO_H */

extern struct program * MonogDB_program;
struct program * Collection_program;

mongo * getdb(struct object * db);
void push_coll(struct pike_string * coll);
void lookup_collection_program();
void throw_mongodb_error(int ret, struct object * db);

DECLARATIONS

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

#define COLL_DB(X) (mongo *)(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))
#define THISLD ((struct LowDatabase_struct *)get_storage(Pike_fp->current_object, LowDatabase_program))
  PIKEFUN void create()
  {

  }
  
  PIKEFUN string _sprintf(mixed format, mixed bar)
  {
    push_text("MongoDB.Collection(");
    push_string(THISLC->name);
    f_add(2);
    push_text(")");
    f_add(2);
  }
  
  PIKEFUN int update_bson(string bson_cond, string bson_op, int flags)
  {
    bson _bson_cond;
    bson _bson_op;
    int ret = 0;
    char * ns;
    mongo * db;
    int ret2;
    
    ns = THIS->name->str; // TODO convert to UTF8.
    
    db = getdb(THISLC->db);
    bson_init_finished_data(&_bson_cond, bson_cond->str);
    bson_init_finished_data(&_bson_op, bson_op->str);
    
    ret = mongo_update(db, ns, &_bson_cond, &_bson_op, flags, NULL);
    
    ret2 = ret;

    if(ret == MONGO_ERROR && db->err == MONGO_IO_ERROR)
    {
      if(mongo_reconnect(db) != MONGO_ERROR)
      {
        ret = mongo_update(db, ns, &_bson_cond, &_bson_op, flags, NULL);
      }
    }

    if(ret != MONGO_OK)
    {
    //      pop_n_elems(args);
      throw_mongodb_error(ret, THISLC->db);
    }

    //    bson_print_raw(bson_data(&_bson), 10);
    RETURN ret;
  }
  
  PIKEFUN int insert_bson(string bson_doc)
  {
    bson _bson;
    int ret = 0;
    char * ns;
    mongo * db;
    int ret2;
    
    ns = THIS->name->str; // TODO convert to UTF8.
    
    db = getdb(THISLC->db);
    bson_init_finished_data(&_bson, bson_doc->str);

//    bson_print_raw(bson_data(&_bson), 10);
    ret = mongo_insert(db, ns, &_bson, NULL);


  ret2 = ret;
  
    if(ret == MONGO_ERROR && db->err == MONGO_IO_ERROR)
    {
      if(mongo_reconnect(db) != MONGO_ERROR)
      {
        ret = mongo_insert(db, ns, &_bson, NULL);
      }
    }
    
    if(ret != MONGO_OK)
    {
//      pop_stack();
      throw_mongodb_error(ret, THISLC->db);
    }
  
//    bson_print_raw(bson_data(&_bson), 10);
          
    RETURN ret;
  }
  
    PIKEFUN int remove_bson(string bson_doc)
    {
      bson _bson;
      int ret = 0;
      char * ns;
      mongo * db;
      int ret2;

      ns = THIS->name->str; // TODO convert to UTF8.

      db = getdb(THISLC->db);
      bson_init_finished_data(&_bson, bson_doc->str);

      ret = mongo_remove(db, ns, &_bson, NULL);
      ret2 = ret;

      if(ret2 == MONGO_ERROR && db->err == MONGO_IO_ERROR)
      {
        if(mongo_reconnect(db) != MONGO_ERROR)
        {
          ret = mongo_remove(db, ns, &_bson, NULL);
        }
      }

      if(ret != MONGO_OK)
      {
        throw_mongodb_error(ret, THISLC->db);
      }

      RETURN ret;
    }
    
   PIKEFUN int create_index_bson(string bson_doc, int flags)
    {
      bson _bson;
      int ret = 0;
      char * ns;
      mongo * db;
      int ret2;

      ns = THIS->name->str; // TODO convert to UTF8.

      db = getdb(THISLC->db);
      bson_init_finished_data(&_bson, bson_doc->str);

  //    bson_print_raw(bson_data(&_bson), 10);
      ret = mongo_create_index(db, ns, &_bson, flags, NULL);


    ret2 = ret;

      if(ret == MONGO_ERROR && db->err == MONGO_IO_ERROR)
      {
        if(mongo_reconnect(db) != MONGO_ERROR)
        {
          ret = mongo_insert(db, ns, &_bson, NULL);
        }
      }

      if(ret != MONGO_OK)
      {
  //      pop_stack();
        throw_mongodb_error(ret, THISLC->db);
      }

  //    bson_print_raw(bson_data(&_bson), 10);

      RETURN ret;
    }
        
    PIKEFUN array low_find(string query_bson)
    {
    int ret;
    char * ns;
    mongo * db;
    bson query;
    mongo_cursor cursor[1];
    int count = 0;
    
    ns = THIS->name->str; // TODO convert to UTF8.

    db = getdb(THISLC->db);
    bson_init_finished_data(&query, query_bson->str);
    mongo_cursor_init( cursor, db, ns );
    mongo_cursor_set_query( cursor, &query );
    pop_n_elems(args);
    while( mongo_cursor_next( cursor ) == MONGO_OK ) {
      struct pike_string * bt;
      const bson * _rb;
      
      _rb = mongo_cursor_bson(cursor);
      
      bt = make_shared_binary_string(bson_data(_rb), bson_size(_rb));                 
      push_string(bt);
      count++;
    }
    f_aggregate(count);

//    bson_destroy( query );
    mongo_cursor_destroy( cursor );

    }

  INIT
  {
  }

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

/*! @endclass
 */

/*! @class Database
 */
PIKECLASS LowDatabase
flags ID_PROTECTED;
{

DECLARATIONS
CVAR mongo * db;

/*! @decl void create(string|void replica_set)
 */

PIKEFUN void create()
{
  mongo * db;
  int status;

  db = malloc(sizeof(mongo));
  mongo_init(db);
  
  THIS->db = db;
}

PIKEFUN void create(string replica_set)
{
  mongo * db;
  int status;

  db = malloc(sizeof(mongo));
  mongo_replica_set_init(db, replica_set->str);
  
  THIS->db = db;
}

/*! @decl void add_seed(string ip, int|void port)
 *!
 *! add a seed to the replica set connection configuration.
 *!
 */
PIKEFUN void add_seed(string ip, int|void port)
{
  int prt;
  
  if(THIS->db && (THIS->db->connected))
    Pike_error("Database already connected.\n");
  if(THIS->db && !THIS->db->replica_set)
    Pike_error("Cannot add seed without using replica set name.\n");

  if(port)
    prt = port->u.integer;
  else
    prt = MONGO_DEFAULT_PORT;

  mongo_replica_set_add_seed(THIS->db, ip->str, prt);
  pop_n_elems(args);
}

/*! @decl void connect(string ip, int|void port)
 */
 PIKEFUN void connect(string ip, int|void port)
 {
   int status;
   int prt;
   
   if(THIS->db && THIS->db->replica_set)
     Pike_error("Cannot connect directly when using a replica set.\n");

   if(THIS->db && (THIS->db->connected))
     Pike_error("Database already connected.\n");


   if(port)
     prt = port->u.integer;
   else
     prt = MONGO_DEFAULT_PORT;

   mongo_set_op_timeout(THIS->db, 2000);
   status = mongo_client(THIS->db, ip->str, prt);
   if( status != MONGO_OK ) 
   {
     pop_n_elems(args);
     switch(THIS->db->err)
     {
       case MONGO_CONN_NO_SOCKET:  Pike_error( "no socket\n" );
       case MONGO_CONN_FAIL:       Pike_error( "connection failed\n" );
       case MONGO_CONN_NOT_MASTER: Pike_error( "not master\n" );
       default: Pike_error("unknown error.\n");
     }
   }

   pop_n_elems(args);
 }

/*! @decl void connect_replica_set()
 *!
 *! connect to a replica set, having specified the seeds using @[add_seed()].
 */
PIKEFUN void connect_replica_set()
{
  int status;
  
  if(THIS->db && (THIS->db->connected))
    Pike_error("Database already connected.\n");
  
  if(THIS->db && !THIS->db->replica_set)
    Pike_error("Cannot connect without specifying a replica set.\n");
  
  status = mongo_replica_set_client(THIS->db);
  
  if( status != MONGO_OK ) 
   {
     pop_n_elems(args);
     switch(THIS->db->err)
     {
       case MONGO_CONN_NO_SOCKET:  Pike_error( "no socket\n" );
       case MONGO_CONN_FAIL:       Pike_error( "connection failed\n" );
       case MONGO_CONN_NOT_MASTER: Pike_error( "not master\n" );
       default: Pike_error("unknown error.\n");
     }
   }

   pop_n_elems(args);
}

/*! @decl object get_collection(string name)
 *!
 */
PIKEFUN object get_collection(string name)
{  
  if(!THIS->db || !(THIS->db->connected))
    Pike_error("Database not connected yet.\n");
    
  add_ref(name);
  pop_n_elems(args);
  push_coll(name);
  free_string(name);
  return;
}

/*! @decl int authenticate(string db, string username, string password)
 *!
 */
PIKEFUN int authenticate(string db, string username, string password)
{
  int ret;

  if(!THIS->db || !(THIS->db->connected))
    Pike_error("Database not connected yet.\n");

  ret = mongo_cmd_authenticate(THIS->db, db->str, username->str, password->str);
  pop_n_elems(args);
  push_int(ret);
}
  
  PIKEFUN string run_command_bson(string dbname, string cmdbson)
  {
    bson _bson;
    int ret = 0;
    mongo * db;
    char * ns;
    bson out;
    struct pike_string * bt;
    
    db = THISLD->db;
    ns = dbname->str; // TODO convert to UTF8.

    if(!THIS->db || !(THIS->db->connected))
      Pike_error("Database not connected yet.\n");
    
    bson_init_finished_data(&_bson, cmdbson->str);
    
    ret = mongo_run_command( db, ns, &_bson, &out );
    if(ret == MONGO_ERROR && db->err == MONGO_IO_ERROR)
      {
        if(mongo_reconnect(db) != MONGO_ERROR)
        {
          ret = mongo_run_command(db, ns, &_bson, &out);
        }
      }

    if(ret != MONGO_OK)
    {
 //    printf("retval: %d\n", ret);
 // printf("res: %s\n", bson_data(&out));
 //   printf("err: %d, %d, %s, %d, %s\n", db->err, db->errcode, db->errstr, db->lasterrcode, db->lasterrstr);
        throw_mongodb_error(ret, Pike_fp->current_object);
    }

      bt = make_shared_binary_string(bson_data(&out), bson_size(&out));                 

      pop_n_elems(args);
      
      push_string(bt);
  }

/*! @decl string get_replica_set_name()
 *!
 */
PIKEFUN string get_replica_set_name()
{
  if(!THIS->db || !THIS->db->replica_set)
    Pike_error("no replica set specified.\n");

  push_text(THIS->db->replica_set->name);
}

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

void push_coll(struct pike_string * coll)
{
  struct object * c;
  if(!Collection_program)
    lookup_collection_program();
  c = clone_object(Collection_program, 0);
  add_ref(coll);
  OBJ2_COLLECTION(c)->db = this_object();
  OBJ2_COLLECTION(c)->name = coll;
  add_ref(OBJ2_COLLECTION(c)->db);
  push_object(c);
}

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

INIT
{
}

EXIT
{
  mongo * db;
  db = THIS->db;
  if(db)
  { 
    mongo_destroy(db);
  }
  
  if(Collection_program)
    free_program(Collection_program);
}

}

/*! @endclass
 */

 EXTRA
 {
 
 /*! @decl constant UPDATE_UPSERT 
  *! Index: Update/Insert operation. 
  */
 add_integer_constant("UPDATE_UPSERT", MONGO_UPDATE_UPSERT, 0);
 
 /*! @decl constant UPDATE_MULTI 
   *! Index: Multi-object Update operation. 
   */
  add_integer_constant("UPDATE_MULTI", MONGO_UPDATE_MULTI, 0);
 
 /*! @decl constant UPDATE_MULTI 
   *! Index: Multi-object Update operation. 
   */
  add_integer_constant("UPDATE_BASIC", MONGO_UPDATE_BASIC, 0);
 
 
  /* INDEX Constants */
 
  /*! @decl constant INDEX_UNIQUE 
     *! Index: Multi-object Update operation. 
     */
    add_integer_constant("INDEX_UNIQUE", MONGO_INDEX_UNIQUE, 0);
 
    /*! @decl constant INDEX_DROP_DUPS 
       *! Index: Multi-object Update operation. 
       */
      add_integer_constant("INDEX_DROP_DUPS", MONGO_INDEX_DROP_DUPS, 0);
 
      /*! @decl constant INDEX_BACKGROUND 
         *! Index: Multi-object Update operation. 
         */
        add_integer_constant("INDEX_BACKGROUND", MONGO_INDEX_BACKGROUND, 0);
 
        /*! @decl constant INDEX_SPARSE 
           *! Index: Multi-object Update operation. 
           */
          add_integer_constant("INDEX_SPARSE", MONGO_INDEX_SPARSE, 0);  
 }
 PIKE_MODULE_INIT
 {
   INIT;
 }

 PIKE_MODULE_EXIT
 {
   EXIT;
 }

 void throw_mongodb_error(int ret, struct object * db)
 {
   mongo * _db;
   int ecode;
   char msg2[256];
   const char * msg;

   _db = getdb(db);
   
//   printf("ret: %d\n", ret);
   switch(_db->err)
   {
     case MONGO_CONN_NO_SOCKET:    /**< Could not create a socket. */
       Pike_error("Could not create a socket.\n");
     case MONGO_CONN_FAIL:         /**< An error occured while calling connect(). */
       Pike_error("An error occured while calling connect().\n");
     case MONGO_CONN_ADDR_FAIL:    /**< An error occured while calling getaddrinfo(). */
       Pike_error("An error occured while calling getaddrinfo().\n");
     case MONGO_CONN_NOT_MASTER:   /**< Warning: connected to a non-master node (read-only). */
       Pike_error("Warning: connected to a non-master node (read-only).\n");
     case MONGO_CONN_BAD_SET_NAME: /**< Given rs name doesn't match this replica set. */
       Pike_error("Given rs name doesn't match this replica set.\n");
     case MONGO_CONN_NO_PRIMARY:   /**< Can't find primary in replica set. Connection closed. */
       Pike_error("Can't find primary in replica set. Connection closed.\n");

     case MONGO_IO_ERROR:          /**< An error occurred while reading or writing on the socket. */
       Pike_error("An error occurred while reading or writing on the socket.\n");
     case MONGO_SOCKET_ERROR:      /**< Other socket error. */
       Pike_error("Other socket error.\n");
     case MONGO_READ_SIZE_ERROR:   /**< The response is not the expected length. */
       Pike_error("The response is not the expected length.\n");
     case MONGO_COMMAND_FAILED:    /**< The command returned with 'ok' value of 0. */
       Pike_error("The command returned with 'ok' value of 0.\n");
     case MONGO_WRITE_ERROR:       /**< Write with given write_concern returned an error. */
       Pike_error("Write with given write_concern returned an error.\n");
     case MONGO_NS_INVALID:        /**< The name for the ns (database or collection) is invalid. */
       Pike_error("The name for the ns (database or collection) is invalid.\n");
     case MONGO_BSON_INVALID:      /**< BSON not valid for the specified op. */
       Pike_error("BSON not valid for the specified op.\n");
     case MONGO_BSON_NOT_FINISHED: /**< BSON object has not been finished. */
       Pike_error("BSON object has not been finished.\n");
     case MONGO_BSON_TOO_LARGE:    /**< BSON object exceeds max BSON size. */
       Pike_error("BSON object exceeds max BSON size.\n");
     case MONGO_WRITE_CONCERN_INVALID: /**< Supplied write concern object is invalid. */
       Pike_error("Supplied write concern object is invalid.\n");
     default:
       Pike_error("unknown error\n");
     
   }
/*
   msg = mongo_get_server_err_string(_db);
   printf("mongodb error: %s\n", msg);
   Pike_error(msg);
*/
 }

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

 /*! @endmodule
  */

 /*! @endmodule
  */


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