blob: af3b61f3b2ac9680caf0642ce884be75fc85323d [file] [log] [blame]
/*
* File: CvCouchDb.cpp
* Author: mony
*
* Created on August 28, 2012, 12:23 PM
*/
#include "CvHttpCommon.h"
#include "CvCouchDb.h"
#include "CvHttpRequest.h"
#include "CvLogger.h"
#include "json/writer.h"
using namespace std;
using namespace CvShared;
CvCouchDb::CvCouchDb( const CvString& aHost, u_short aPort, const CvString& aUser, const CvString& aPassword ) :
m_host(aHost), m_port(aPort), m_user(aUser), m_password(aPassword)
{
if ( m_user.empty() )
m_url.Format( "http://%s:%d", m_host.c_str(), m_port );
else
m_url.Format( "http://%s:%s@%s:%d", m_user.c_str(), m_password.c_str(), m_host.c_str(), m_port );
}
CvCouchDb::~CvCouchDb()
{
}
bool CvCouchDb::CreateDatabase( const CvString& aDbName ) const
{
CvString dbName;
CvHttpRequest::EncodeURL( aDbName, dbName );
CvHttpRequest httpRequest;
httpRequest.SetUrl( m_url + "/" + dbName );
httpRequest.SetMethod( enHttpMethod_PUT );
if ( httpRequest.Execute() != CvHttpRequest::enStatus_Ok )
return false;
json::Object joResponse;
try
{
istringstream iss( httpRequest.GetResponse() );
json::Reader::Read( joResponse, iss );
}
catch ( exception& e )
{
LogMessage( enLogLevel_Error, "Exception [%s] while parsing json response: %s", e.what(), httpRequest.GetResponse().c_str() );
return false;
}
catch ( ... )
{
LogMessage( enLogLevel_Error, "Unexpected exception while parsing json response: %s", httpRequest.GetResponse().c_str() );
return false;
}
if ( httpRequest.GetResponseCode() >= 200 &&
httpRequest.GetResponseCode() < 300 &&
(json::Boolean&)joResponse["ok"] )
return true;
const string& error = (json::String&)joResponse["error"];
const string& reason = (json::String&)joResponse["reason"];
LogMessage( enLogLevel_Error, "ERROR while trying to create database [%s] on CouchDB [%s]: %s (%s)",
aDbName.c_str(), m_url.c_str(), reason.c_str(), error.c_str() );
return false;
}
bool CvCouchDb::IsDatabaseExists( const CvString& aDbName ) const
{
CvString dbName;
CvHttpRequest::EncodeURL( aDbName, dbName );
CvHttpRequest httpRequest;
httpRequest.SetUrl( m_url + "/" + dbName );
httpRequest.SetMethod( enHttpMethod_GET );
if ( httpRequest.Execute() != CvHttpRequest::enStatus_Ok )
return false;
json::Object joResponse;
try
{
istringstream iss( httpRequest.GetResponse() );
json::Reader::Read( joResponse, iss );
}
catch ( exception& e )
{
LogMessage( enLogLevel_Error, "Exception [%s] while parsing json response: %s", e.what(), httpRequest.GetResponse().c_str() );
return false;
}
catch ( ... )
{
LogMessage( enLogLevel_Error, "Unexpected exception while parsing json response: %s", httpRequest.GetResponse().c_str() );
return false;
}
return ( httpRequest.GetResponseCode() >= 200 &&
httpRequest.GetResponseCode() < 300 &&
((json::String&)joResponse["db_name"]).Value() == aDbName );
}
bool CvCouchDb::PutDocument( const CvString& aDbName, const CvString& aId, const json::Object aDoc, OUT bool& abExists ) const
{
abExists = false;
CvString dbName;
CvHttpRequest::EncodeURL( aDbName, dbName );
CvString docId;
CvHttpRequest::EncodeURL( aId, docId );
CvHttpRequest httpRequest;
httpRequest.SetUrl( m_url + "/" + dbName + "/" + docId );
httpRequest.SetMethod( enHttpMethod_PUT );
ostringstream oss;
json::Writer::Write( aDoc, oss );
CvString content = oss.str();
httpRequest.SetContent( content.data(), content.length() );
CMapHttpHeaders mapHeaders;
httpRequest.SetHeaders( mapHeaders );
if ( httpRequest.Execute() != CvHttpRequest::enStatus_Ok )
return false;
json::Object joResponse;
try
{
istringstream iss( httpRequest.GetResponse() );
json::Reader::Read( joResponse, iss );
}
catch ( exception& e )
{
LogMessage( enLogLevel_Error, "Exception [%s] while parsing json response: %s", e.what(), httpRequest.GetResponse().c_str() );
return false;
}
catch ( ... )
{
LogMessage( enLogLevel_Error, "Unexpected exception while parsing json response: %s", httpRequest.GetResponse().c_str() );
return false;
}
if ( httpRequest.GetResponseCode() >= 200 &&
httpRequest.GetResponseCode() < 300 &&
(json::Boolean&)joResponse["ok"] )
return true;
const string& error = (json::String&)joResponse["error"];
const string& reason = (json::String&)joResponse["reason"];
abExists = ( error == "conflict" && reason == "Document update conflict." );
LogMessage( enLogLevel_Error, "ERROR while trying to create document [%s/%s] on CouchDB [%s]: %s (%s)",
aDbName.c_str(), aId.c_str(), m_url.c_str(), reason.c_str(), error.c_str() );
return false;
}
bool CvCouchDb::GetDocument( const CvString& aDbName, const CvString& aId, json::Object& aDoc ) const
{
CvString dbName;
CvHttpRequest::EncodeURL( aDbName, dbName );
CvString docId;
CvHttpRequest::EncodeURL( aId, docId );
CvHttpRequest httpRequest;
httpRequest.SetUrl( m_url + "/" + dbName + "/" + docId );
httpRequest.SetMethod( enHttpMethod_GET );
if ( httpRequest.Execute() != CvHttpRequest::enStatus_Ok )
return false;
try
{
istringstream iss( httpRequest.GetResponse() );
json::Reader::Read( aDoc, iss );
}
catch ( exception& e )
{
LogMessage( enLogLevel_Error, "Exception [%s] while parsing json response: %s", e.what(), httpRequest.GetResponse().c_str() );
return false;
}
catch ( ... )
{
LogMessage( enLogLevel_Error, "Unexpected exception while parsing json response: %s", httpRequest.GetResponse().c_str() );
return false;
}
if ( httpRequest.GetResponseCode() >= 200 &&
httpRequest.GetResponseCode() < 300 &&
((json::String&)aDoc["_id"]).Value() == aId )
return true;
const string& error = (json::String&)aDoc["error"];
const string& reason = (json::String&)aDoc["reason"];
LogMessage( enLogLevel_Error, "ERROR while trying to get document [%s/%s] from CouchDB [%s]: %s (%s)",
aDbName.c_str(), aId.c_str(), m_url.c_str(), reason.c_str(), error.c_str() );
return false;
}