Source

libpycom / libpycom / pycom.h

Full commit
//  PyCOM - Distributed Component Model for Python - C++ Client Library
//  Copyright (c) 2011-2012, Dmitry "Divius" Tantsur
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//  * Redistributions in binary form must reproduce the above
//    copyright notice, this list of conditions and the following disclaimer
//    in the documentation and/or other materials provided with the
//    distribution.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
//  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
//  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
//  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
//  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
//  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
//  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef PYCOM_H__INCLUDED
#define PYCOM_H__INCLUDED

# if defined(PYCOM_DLL_BUILD)
#  define PYCOM_API __declspec(dllexport)
# elif defined(PYCOM_DLL)
#  define PYCOM_API __declspec(dllimport)
# else
#  define PYCOM_API
# endif

#include <stdexcept>
#include <string>

#include <pycom-json.h>

namespace pycom {

// Forward definitions

class Component;

struct _context_pvt;
struct _component_pvt;

// Public API

/*! All known error codes.
    Partly copied from pycom.constants module.
*/
enum ErrorCode {
    SUCCESS = 0,
    ERROR_UNKNOWN = 1,
    ERROR_METHOD_NOT_FOUND = 2,
    ERROR_SERVICE_NOT_FOUND = 3,
    ERROR_BAD_REQUEST = 4
};

/*! Class representing error. */
class Error: public std::runtime_error {
public:
    /*! Exception constructor. */
    explicit Error (const std::string &message) throw()
        : std::runtime_error(message)
    {}
};

/*! Class representing service/interface/method lookup error. */
class LookupError: public Error {
public:
    /*! Exception constructor. */
    explicit LookupError (const std::string &message) throw()
        : Error(message)
    {}
};

/*! Class representing internal error in protocol code. */
class InternalError: public Error {
public:
    /*! Exception constructor. */
    explicit InternalError (const std::string &message) throw()
        : Error(message)
    {}
};

/*! Class representing any server-side error. */
class RemoteError: public Error {
public:
    /*! Exception constructor. */
    RemoteError (int new_code, const std::string &message) throw()
        : Error(message), _code(new_code)
    {}
    /*! Error code.
        \see ErrorCode
    */
    inline int code() const throw() {
        return _code;
    }
private:
    int _code;
};

/*! Class bad request error error. */
class BadRequest: public RemoteError {
public:
    /*! Exception constructor. */
    BadRequest (const std::string &message) throw()
        : RemoteError(ERROR_BAD_REQUEST, message)
    {}
};

/*! Context object that should be created before any other PyCOM objects.
    You MUST NOT use any PyCOM object after context is deleted.
 */
class PYCOM_API Context {
public:
    /*! Default constructor.
        \param ns_address nameserver address in ZeroMQ format
        \throw std::invalid_argument on bad address
    */
    Context(const std::string &ns_address);
    /*! Destructor. */
    ~Context();
    /*! Get nameserver implementation.
        \return component for nameserver
        \throw LookupError if nameserver cannot be reached
        \see pycom::invoker
     */
    Component *nameserver();
    /*! Locate an interface.
        \param iface_name interface name
        \return component for service
        \throw LookupError if nameserver or service cannot be reached
        \throw InternalError on protocol failure
        \see pycom::Component
     */
    Component *locate(const std::string &iface_name);
private:
    _context_pvt *_pvt;
    Component *open(const std::string &iface_name, const std::string &address);
};

/*! Proxy object for invoking remote method.
    \note components are NOT thread-safe!
    \note You program will hang on exit if you do not delete all opened
        components BEFORE context deletion
*/
class PYCOM_API Component {
public:
    /*! Destructor. */
    ~Component();
    /*! Invoke remote method.
        \param method_name rmeote method name
        \param args JSON arguments
        \return JSON return value (null on error)
        \throw InternalError on protocol failure
        \throw LookupError if service or method cannot be accessed
        \throw BadRequest if server side detects malformed request
        \throw RemoteError on any other server-side error
     */
    Value invoke(const std::string &method_name, const Value &args = Value());
protected:
    /*! Constructor is hidden, use pycom::Context::locate(). */
    Component(_component_pvt *pvt);
private:
    _component_pvt *_pvt;
friend class Context;
};

} // namespace pycom

#endif // PYCOM_H__INCLUDED