I want to let my newlisp app access MongoDB server. There is C driver for MongoDB, but I have no time to learn C driver, just want to finish my job ASAP.
Below is my way, create a dynamic library using C++, also link to MongoDB C++ driver. But export C function using extern "C" statement.One thing needs to note, MongoDB C++ driver must be compiled using -fPIC option.
First, create db.h file
extern "C" void CheckOnline();
extern "C" void Init(char * mongo_uri);
edit db.cc file
#include "db.h"
#include <stdlib.h>
#include <ctype.h>
#include <iostream>
#include "mongo_session_factory.h"
#include "mongo_session.h"
#include <mongo/bson/bsonobj.h>
#include <mongo/bson/bsonobjbuilder.h>
using namespace std;
class Config {
public:
string mongo_uri;
};
Config config;
void SetOffline(mongo::DBClientBase& con, mongo::OID const& id) {
mongo::BSONObjBuilder condition;
condition.append("_id", id);
mongo::BSONObjBuilder update_field;
update_field.append("status", "offline");
mongo::BSONObjBuilder set_field;
set_field.append("$set", update_field.obj());
con.update("kaimei.display", mongo::Query(condition.obj()), set_field.obj());
}
/**
* Check every sign status
*/
void CheckOnline() {
cout << config.mongo_uri << endl;
std::shared_ptr<MongoSession> session = MongoSessionFactory::GetSession(config.mongo_uri);
mongo::DBClientBase & con = session->get_db_client_base();
mongo::BSONObjBuilder condition;
std::unique_ptr<mongo::DBClientCursor> cursor = con.query("kaimei.display", mongo::Query(condition.obj()));
while (cursor->more()) {
mongo::BSONObj record = cursor->next();
uint64_t t1 = record.getField("last_active_time").numberLong();
timeval tv;
gettimeofday(&tv,NULL);
if (tv.tv_sec - t1 > 300) {
SetOffline(con, record.getField("_id").OID());
}
}
}
void Init(char * mongo_uri) {
config.mongo_uri = mongo_uri;
}
in include and src folders, there are some helper classes called MongoSessionFactory and MongoSesion. They are useful to connect to MongoDB server(Replicaset or Single server)
Ok, build it, see build.lsp file
#!/usr/bin/newlisp
(if (file? "db.so")
(delete-file "db.so"))
(if (directory? "objects")
(exec "rm -rf objects"))
(make-dir "objects")
(exec "c++ -g -fPIC -std=c++11 -I./include -Wall -o ./objects/mongo_session_factory.cc.o -c ./src/mongo_session_factory.cc")
(exec "c++ -g -fPIC -std=c++11 -I./include -Wall -o ./objects/mongo_session.cc.o -c ./src/mongo_session.cc")
(exec "c++ -g -fPIC -std=c++11 -I./include -Wall -o ./objects/db.cc.o -c ./src/db.cc")
(exec "c++ -g -fPIC -std=c++11 ./objects/mongo_session_factory.cc.o ./objects/mongo_session.cc.o ./objects/db.cc.o -shared -o db.so -rdynamic -lpthread -lmongoclient -lboost_system -lboost_thread -lboost_filesystem")
(exit)
After building succeeds, write a check.lsp to use the db.so library.
#!/usr/bin/newlisp
(set 'db-path "/path/to/your/db.so")
(import db-path "Init")
(import db-path "CheckOnline")
(Init "localhost:27017")
(CheckOnline)
(exit)
That's all. It works now.
No comments:
Post a Comment