1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
|
//
// Copyright (c) ZeroC, Inc. All rights reserved.
//
#include <Ice/Ice.h>
#include <BlobjectI.h>
using namespace std;
#ifndef ICE_CPP11_MAPPING
class Callback : public IceUtil::Shared
{
public:
Callback(const Ice::AMD_Object_ice_invokePtr& cb, bool twoway) :
_cb(cb), _twoway(twoway)
{
}
void response(bool ok, const vector<Ice::Byte>& encaps)
{
_cb->ice_response(ok, encaps);
}
void exception(const Ice::Exception& ex)
{
_cb->ice_exception(ex);
}
void sent(bool)
{
if(!_twoway)
{
_cb->ice_response(true, vector<Ice::Byte>());
}
}
private:
Ice::AMD_Object_ice_invokePtr _cb;
bool _twoway;
};
typedef IceUtil::Handle<Callback> CallbackPtr;
#endif
BlobjectI::BlobjectI() :
_startBatch(false)
{
}
void
BlobjectI::setConnection(const Ice::ConnectionPtr& connection)
{
Lock sync(*this);
_connection = connection;
notifyAll();
}
void
BlobjectI::startBatch()
{
assert(!_batchProxy);
_startBatch = true;
}
void
BlobjectI::flushBatch()
{
assert(_batchProxy);
_batchProxy->ice_flushBatchRequests();
_batchProxy = 0;
}
#ifdef ICE_CPP11_MAPPING
void
BlobjectI::ice_invokeAsync(std::vector<Ice::Byte> inEncaps,
std::function<void(bool, const std::vector<Ice::Byte>&)> response,
std::function<void(std::exception_ptr)> ex,
const Ice::Current& current)
{
auto connection = getConnection(current);
const bool twoway = current.requestId > 0;
auto obj = connection->createProxy(current.id);
if(!twoway)
{
if(_startBatch)
{
_startBatch = false;
_batchProxy = obj->ice_batchOneway();
}
if(_batchProxy)
{
obj = _batchProxy;
}
if(!current.facet.empty())
{
obj = obj->ice_facet(current.facet);
}
if(_batchProxy)
{
vector<Ice::Byte> out;
obj->ice_invoke(current.operation, current.mode, inEncaps, out, current.ctx);
response(true, vector<Ice::Byte>());
}
else
{
obj->ice_oneway()->ice_invokeAsync(current.operation, current.mode, inEncaps,
[](bool, const std::vector<Ice::Byte>&) { assert(0); },
ex,
[&](bool) { response(true, vector<Ice::Byte>()); },
current.ctx);
}
}
else
{
if(!current.facet.empty())
{
obj = obj->ice_facet(current.facet);
}
obj->ice_invokeAsync(current.operation, current.mode, inEncaps, response, ex, nullptr, current.ctx);
}
}
#else
void
BlobjectI::ice_invoke_async(const Ice::AMD_Object_ice_invokePtr& amdCb, const vector<Ice::Byte>& inEncaps,
const Ice::Current& current)
{
Ice::ConnectionPtr connection = getConnection(current);
const bool twoway = current.requestId > 0;
Ice::ObjectPrx obj = connection->createProxy(current.id);
if(!twoway)
{
if(_startBatch)
{
_startBatch = false;
_batchProxy = obj->ice_batchOneway();
}
if(_batchProxy)
{
obj = _batchProxy;
}
if(!current.facet.empty())
{
obj = obj->ice_facet(current.facet);
}
if(_batchProxy)
{
vector<Ice::Byte> out;
obj->ice_invoke(current.operation, current.mode, inEncaps, out, current.ctx);
amdCb->ice_response(true, vector<Ice::Byte>());
}
else
{
CallbackPtr cb = new Callback(amdCb, false);
Ice::Callback_Object_ice_invokePtr del =
Ice::newCallback_Object_ice_invoke(cb, &Callback::response, &Callback::exception, &Callback::sent);
obj->ice_oneway()->begin_ice_invoke(current.operation, current.mode, inEncaps, current.ctx, del);
}
}
else
{
if(!current.facet.empty())
{
obj = obj->ice_facet(current.facet);
}
CallbackPtr cb = new Callback(amdCb, true);
Ice::Callback_Object_ice_invokePtr del =
Ice::newCallback_Object_ice_invoke(cb, &Callback::response, &Callback::exception, &Callback::sent);
obj->begin_ice_invoke(current.operation, current.mode, inEncaps, current.ctx, del);
}
}
#endif
Ice::ConnectionPtr
BlobjectI::getConnection(const Ice::Current& current)
{
Lock sync(*this);
if(!_connection)
{
return current.con;
}
try
{
_connection->throwException();
}
catch(const Ice::ConnectionLostException&)
{
// If we lost the connection, wait 5 seconds for the server to re-establish it. Some tests,
// involve connection closure (e.g.: exceptions MemoryLimitException test) and the server
// automatically re-establishes the connection with the echo server.
timedWait(IceUtil::Time::seconds(5));
if(!_connection)
{
throw;
}
}
return _connection;
}
|