summaryrefslogtreecommitdiff
path: root/lib/server/makeprotocol.pl.in
diff options
context:
space:
mode:
Diffstat (limited to 'lib/server/makeprotocol.pl.in')
-rwxr-xr-xlib/server/makeprotocol.pl.in497
1 files changed, 324 insertions, 173 deletions
diff --git a/lib/server/makeprotocol.pl.in b/lib/server/makeprotocol.pl.in
index a074b435..d6c0e216 100755
--- a/lib/server/makeprotocol.pl.in
+++ b/lib/server/makeprotocol.pl.in
@@ -78,7 +78,7 @@ sub add_type
my ($protocol_name, $cpp_name, $header_file) = split /\s+/,$_[0];
$translate_type_info{$protocol_name} = [0, $cpp_name];
- push @extra_header_files, $header_file;
+ push @extra_header_files, $header_file if $header_file;
}
# check attributes
@@ -158,7 +158,10 @@ print CPP <<__E;
#include <sstream>
#include "$filename_base.h"
-#include "IOStream.h"
+#include "CollectInBufferStream.h"
+#include "MemBlockStream.h"
+#include "SelfFlushingStream.h"
+#include "SocketStream.h"
__E
print H <<__E;
@@ -174,12 +177,10 @@ print H <<__E;
#include <syslog.h>
#endif
+#include "autogen_ConnectionException.h"
#include "Protocol.h"
#include "Message.h"
-#include "ServerException.h"
-
-class IOStream;
-
+#include "SocketStream.h"
__E
@@ -210,19 +211,26 @@ __E
my $request_base_class = "${protocol_name}ProtocolRequest";
my $reply_base_class = "${protocol_name}ProtocolReply";
# the abstract protocol interface
-my $protocol_base_class = $protocol_name."ProtocolBase";
+my $custom_protocol_subclass = $protocol_name."Protocol";
+my $client_server_base_class = $protocol_name."ProtocolClientServer";
my $replyable_base_class = $protocol_name."ProtocolReplyable";
+my $callable_base_class = $protocol_name."ProtocolCallable";
+my $send_receive_class = $protocol_name."ProtocolSendReceive";
print H <<__E;
-class $protocol_base_class;
+class $custom_protocol_subclass;
+class $client_server_base_class;
+class $callable_base_class;
class $replyable_base_class;
-class $reply_base_class;
class $message_base_class : public Message
{
public:
virtual std::auto_ptr<$message_base_class> DoCommand($replyable_base_class &rProtocol,
$context_class &rContext) const;
+ virtual std::auto_ptr<$message_base_class> DoCommand($replyable_base_class &rProtocol,
+ $context_class &rContext, IOStream& rDataStream) const;
+ virtual bool HasStreamWithCommand() const = 0;
};
class $reply_base_class
@@ -233,17 +241,44 @@ class $request_base_class
{
};
+class $send_receive_class {
+public:
+ virtual void Send(const $message_base_class &rObject) = 0;
+ virtual std::auto_ptr<$message_base_class> Receive() = 0;
+};
+
+class $custom_protocol_subclass : public Protocol
+{
+public:
+ $custom_protocol_subclass(std::auto_ptr<SocketStream> apConn)
+ : Protocol(apConn)
+ { }
+ virtual ~$custom_protocol_subclass() { }
+ virtual std::auto_ptr<Message> MakeMessage(int ObjType);
+ virtual const char *GetProtocolIdentString();
+
+private:
+ $custom_protocol_subclass(const $custom_protocol_subclass &rToCopy);
+};
+
__E
print CPP <<__E;
std::auto_ptr<$message_base_class> $message_base_class\::DoCommand($replyable_base_class &rProtocol,
$context_class &rContext) const
{
- THROW_EXCEPTION(ConnectionException, Conn_Protocol_TriedToExecuteReplyCommand)
+ THROW_EXCEPTION(ConnectionException, Protocol_TriedToExecuteReplyCommand)
+}
+
+std::auto_ptr<$message_base_class> $message_base_class\::DoCommand($replyable_base_class &rProtocol,
+ $context_class &rContext, IOStream& rDataStream) const
+{
+ THROW_EXCEPTION(ConnectionException, Protocol_TriedToExecuteReplyCommand)
}
__E
-my %cmd_class;
+my %cmd_classes;
+my $error_message = undef;
# output the classes
foreach my $cmd (@cmd_list)
@@ -262,7 +297,7 @@ foreach my $cmd (@cmd_list)
my $cmd_base_class = join(", ", map {"public $_"} @cmd_base_classes);
my $cmd_class = $protocol_name."Protocol".$cmd;
- $cmd_class{$cmd} = $cmd_class;
+ $cmd_classes{$cmd} = $cmd_class;
print H <<__E;
class $cmd_class : $cmd_base_class
@@ -294,18 +329,50 @@ __E
if(obj_is_type($cmd,'IsError'))
{
- print H "\tbool IsError(int &rTypeOut, int &rSubTypeOut) const;\n";
- print H "\tstd::string GetMessage() const;\n";
+ $error_message = $cmd;
+ my ($mem_type,$mem_subtype) = split /,/,obj_get_type_params($cmd,'IsError');
+ my $error_type = $cmd_constants{"ErrorType"};
+ print H <<__E;
+ $cmd_class(int SubType) : m$mem_type($error_type), m$mem_subtype(SubType) { }
+ bool IsError(int &rTypeOut, int &rSubTypeOut) const;
+ std::string GetMessage() const { return GetMessage(m$mem_subtype); };
+ static std::string GetMessage(int subtype);
+__E
}
- if(obj_is_type($cmd, 'Command'))
+ my $has_stream = obj_is_type($cmd, 'StreamWithCommand');
+
+ if(obj_is_type($cmd, 'Command') && $has_stream)
+ {
+ print H <<__E;
+ std::auto_ptr<$message_base_class> DoCommand($replyable_base_class &rProtocol,
+ $context_class &rContext, IOStream& rDataStream) const; // IMPLEMENT THIS\n
+ std::auto_ptr<$message_base_class> DoCommand($replyable_base_class &rProtocol,
+ $context_class &rContext) const
+ {
+ THROW_EXCEPTION_MESSAGE(CommonException, Internal,
+ "This command requires a stream parameter");
+ }
+__E
+ }
+ elsif(obj_is_type($cmd, 'Command') && !$has_stream)
{
print H <<__E;
std::auto_ptr<$message_base_class> DoCommand($replyable_base_class &rProtocol,
$context_class &rContext) const; // IMPLEMENT THIS\n
+ std::auto_ptr<$message_base_class> DoCommand($replyable_base_class &rProtocol,
+ $context_class &rContext, IOStream& rDataStream) const
+ {
+ THROW_EXCEPTION_MESSAGE(CommonException, NotSupported,
+ "This command requires no stream parameter");
+ }
__E
}
+ print H <<__E;
+ bool HasStreamWithCommand() const { return $has_stream; }
+__E
+
# want to be able to read from streams?
print H "\tvoid SetPropertiesFromStreamData(Protocol &rProtocol);\n";
@@ -442,9 +509,9 @@ bool $cmd_class\::IsError(int &rTypeOut, int &rSubTypeOut) const
rSubTypeOut = m$mem_subtype;
return true;
}
-std::string $cmd_class\::GetMessage() const
+std::string $cmd_class\::GetMessage(int subtype)
{
- switch(m$mem_subtype)
+ switch(subtype)
{
__E
foreach my $const (@{$cmd_constants{$cmd}})
@@ -459,7 +526,7 @@ __E
print CPP <<__E;
default:
std::ostringstream out;
- out << "Unknown subtype " << m$mem_subtype;
+ out << "Unknown subtype " << subtype;
return out.str();
}
}
@@ -505,47 +572,44 @@ my $error_class = $protocol_name."ProtocolError";
# the abstract protocol interface
print H <<__E;
-class $protocol_base_class
+
+class $client_server_base_class
{
public:
- $protocol_base_class();
- virtual ~$protocol_base_class();
- virtual const char *GetIdentString();
+ $client_server_base_class();
+ virtual ~$client_server_base_class();
+ virtual std::auto_ptr<IOStream> ReceiveStream() = 0;
bool GetLastError(int &rTypeOut, int &rSubTypeOut);
+ int GetLastErrorType() { return mLastErrorSubType; }
protected:
- void CheckReply(const std::string& requestCommand,
- const $message_base_class &rReply, int expectedType);
void SetLastError(int Type, int SubType)
{
mLastErrorType = Type;
mLastErrorSubType = SubType;
}
+ std::string mPreviousCommand;
+ std::string mPreviousReply;
private:
- $protocol_base_class(const $protocol_base_class &rToCopy); /* do not call */
+ $client_server_base_class(const $client_server_base_class &rToCopy); /* do not call */
int mLastErrorType;
int mLastErrorSubType;
};
-class $replyable_base_class : public virtual $protocol_base_class
+class $replyable_base_class : public virtual $client_server_base_class
{
public:
- $replyable_base_class();
+ $replyable_base_class() { }
virtual ~$replyable_base_class();
- /*
- virtual std::auto_ptr<$message_base_class> Receive() = 0;
- virtual void Send(const ${message_base_class} &rObject) = 0;
- */
-
- virtual std::auto_ptr<IOStream> ReceiveStream() = 0;
virtual int GetTimeout() = 0;
void SendStreamAfterCommand(std::auto_ptr<IOStream> apStream);
-
+
protected:
std::list<IOStream*> mStreamsToSend;
void DeleteStreamsToSend();
+ virtual std::auto_ptr<$message_base_class> HandleException(BoxException& e) const;
private:
$replyable_base_class(const $replyable_base_class &rToCopy); /* do not call */
@@ -554,24 +618,47 @@ private:
__E
print CPP <<__E;
-$protocol_base_class\::$protocol_base_class()
+$client_server_base_class\::$client_server_base_class()
: mLastErrorType(Protocol::NoError),
mLastErrorSubType(Protocol::NoError)
{ }
-$protocol_base_class\::~$protocol_base_class()
+$client_server_base_class\::~$client_server_base_class()
{ }
-const char *$protocol_base_class\::GetIdentString()
+const char *$custom_protocol_subclass\::GetProtocolIdentString()
{
return "$ident_string";
}
-$replyable_base_class\::$replyable_base_class()
-{ }
+std::auto_ptr<Message> $custom_protocol_subclass\::MakeMessage(int ObjType)
+{
+ switch(ObjType)
+ {
+__E
+
+# do objects within this
+for my $cmd (@cmd_list)
+{
+ print CPP <<__E;
+ case $cmd_id{$cmd}:
+ return std::auto_ptr<Message>(new $cmd_classes{$cmd}());
+ break;
+__E
+}
+
+print CPP <<__E;
+ default:
+ THROW_EXCEPTION(ConnectionException, Protocol_UnknownCommandRecieved)
+ }
+}
$replyable_base_class\::~$replyable_base_class()
-{ }
+{
+ // If there were any streams left over, there's no longer any way to
+ // access them, and we're responsible for them, so we'd better delete them.
+ DeleteStreamsToSend();
+}
void $replyable_base_class\::SendStreamAfterCommand(std::auto_ptr<IOStream> apStream)
{
@@ -589,12 +676,14 @@ void $replyable_base_class\::DeleteStreamsToSend()
mStreamsToSend.clear();
}
-void $protocol_base_class\::CheckReply(const std::string& requestCommand,
- const $message_base_class &rReply, int expectedType)
+void $callable_base_class\::CheckReply(const std::string& requestCommandName,
+ const $message_base_class &rCommand, const $message_base_class &rReply,
+ int expectedType)
{
if(rReply.GetType() == expectedType)
{
// Correct response, do nothing
+ SetLastError(Protocol::NoError, Protocol::NoError);
}
else
{
@@ -605,8 +694,8 @@ void $protocol_base_class\::CheckReply(const std::string& requestCommand,
{
SetLastError(type, subType);
THROW_EXCEPTION_MESSAGE(ConnectionException,
- Conn_Protocol_UnexpectedReply,
- requestCommand << " command failed: "
+ Protocol_UnexpectedReply,
+ requestCommandName << " command failed: "
"received error " <<
(($error_class&)rReply).GetMessage());
}
@@ -614,12 +703,18 @@ void $protocol_base_class\::CheckReply(const std::string& requestCommand,
{
SetLastError(Protocol::UnknownError, Protocol::UnknownError);
THROW_EXCEPTION_MESSAGE(ConnectionException,
- Conn_Protocol_UnexpectedReply,
- requestCommand << " command failed: "
+ Protocol_UnexpectedReply,
+ requestCommandName << " command failed: "
"received unexpected response type " <<
rReply.GetType());
}
}
+
+ // As a client, if we get an unexpected reply later, we'll want to know
+ // the last command that we executed, and the reply, to help debug the
+ // server.
+ mPreviousCommand = rCommand.ToString();
+ mPreviousReply = rReply.ToString();
}
// --------------------------------------------------------------------------
@@ -630,7 +725,7 @@ void $protocol_base_class\::CheckReply(const std::string& requestCommand,
// Created: 2003/08/19
//
// --------------------------------------------------------------------------
-bool $protocol_base_class\::GetLastError(int &rTypeOut, int &rSubTypeOut)
+bool $client_server_base_class\::GetLastError(int &rTypeOut, int &rSubTypeOut)
{
if(mLastErrorType == Protocol::NoError)
{
@@ -653,13 +748,19 @@ __E
# the callable protocol interface (implemented by Client and Local classes)
# with Query methods that don't take a context parameter
-my $callable_base_class = $protocol_name."ProtocolCallable";
print H <<__E;
-class $callable_base_class : public virtual $protocol_base_class
+class $callable_base_class : public virtual $client_server_base_class,
+ public $send_receive_class
{
public:
- virtual std::auto_ptr<IOStream> ReceiveStream() = 0;
virtual int GetTimeout() = 0;
+
+protected:
+ void CheckReply(const std::string& requestCommandName,
+ const $message_base_class &rCommand,
+ const $message_base_class &rReply, int expectedType);
+
+public:
__E
# add plain object taking query functions
@@ -671,8 +772,8 @@ for my $cmd (@cmd_list)
my $has_stream = obj_is_type($cmd,'StreamWithCommand');
my $argextra = $has_stream?', std::auto_ptr<IOStream> apStream':'';
my $queryextra = $has_stream?', apStream':'';
- my $request_class = $cmd_class{$cmd};
- my $reply_class = $cmd_class{obj_get_type_params($cmd,'Command')};
+ my $request_class = $cmd_classes{$cmd};
+ my $reply_class = $cmd_classes{obj_get_type_params($cmd,'Command')};
print H "\tvirtual std::auto_ptr<$reply_class> Query(const $request_class &rQuery$argextra) = 0;\n";
my @a;
@@ -720,13 +821,15 @@ foreach my $type ('Client', 'Server', 'Local')
{
push @base_classes, $replyable_base_class;
}
+
if (not $writing_server)
{
push @base_classes, $callable_base_class;
}
+
if (not $writing_local)
{
- push @base_classes, "Protocol";
+ push @base_classes, $custom_protocol_subclass;
}
my $base_classes_str = join(", ", map {"public $_"} @base_classes);
@@ -735,6 +838,7 @@ foreach my $type ('Client', 'Server', 'Local')
class $server_or_client_class : $base_classes_str
{
public:
+ virtual ~$server_or_client_class();
__E
if($writing_local)
@@ -743,18 +847,12 @@ __E
$server_or_client_class($context_class &rContext);
__E
}
- else
- {
- print H <<__E;
- $server_or_client_class(IOStream &rStream);
+
+ print H <<__E;
+ $server_or_client_class(std::auto_ptr<SocketStream> apConn);
std::auto_ptr<$message_base_class> Receive();
void Send(const $message_base_class &rObject);
__E
- }
-
- print H <<__E;
- virtual ~$server_or_client_class();
-__E
if($writing_server)
{
@@ -775,37 +873,29 @@ __E
my $has_stream = obj_is_type($cmd,'StreamWithCommand');
my $argextra = $has_stream?', std::auto_ptr<IOStream> apStream':'';
my $queryextra = $has_stream?', apStream':'';
- my $request_class = $cmd_class{$cmd};
- my $reply_class = $cmd_class{obj_get_type_params($cmd,'Command')};
+ my $request_class = $cmd_classes{$cmd};
+ my $reply_class = $cmd_classes{obj_get_type_params($cmd,'Command')};
print H "\tstd::auto_ptr<$reply_class> Query(const $request_class &rQuery$argextra);\n";
}
}
}
-
+
if($writing_local)
{
print H <<__E;
private:
$context_class &mrContext;
-__E
- }
-
- print H <<__E;
-
-protected:
- virtual std::auto_ptr<Message> MakeMessage(int ObjType);
-
-__E
-
- if($writing_local)
- {
- print H <<__E;
- virtual void InformStreamReceiving(u_int32_t Size) { }
- virtual void InformStreamSending(u_int32_t Size) { }
-
+ std::auto_ptr<$message_base_class> mapLastReply;
public:
virtual std::auto_ptr<IOStream> ReceiveStream()
{
+ if(mStreamsToSend.empty())
+ {
+ THROW_EXCEPTION_MESSAGE(CommonException, Internal,
+ "Tried to ReceiveStream when none was sent or "
+ "made available");
+ }
+
std::auto_ptr<IOStream> apStream(mStreamsToSend.front());
mStreamsToSend.pop_front();
return apStream;
@@ -815,29 +905,33 @@ __E
else
{
print H <<__E;
- virtual void InformStreamReceiving(u_int32_t Size)
- {
- this->Protocol::InformStreamReceiving(Size);
- }
- virtual void InformStreamSending(u_int32_t Size)
- {
- this->Protocol::InformStreamSending(Size);
- }
+ virtual std::auto_ptr<IOStream> ReceiveStream();
+__E
-public:
- virtual std::auto_ptr<IOStream> ReceiveStream()
+ print CPP <<__E;
+std::auto_ptr<IOStream> $server_or_client_class\::ReceiveStream()
+{
+ try
{
- return this->Protocol::ReceiveStream();
- }
-__E
+ return $custom_protocol_subclass\::ReceiveStream();
}
-
- print H <<__E;
- virtual const char *GetProtocolIdentString()
+ catch(ConnectionException &e)
{
- return GetIdentString();
+ if(e.GetSubType() == ConnectionException::Protocol_ObjWhenStreamExpected)
+ {
+ THROW_EXCEPTION_MESSAGE(ConnectionException,
+ Protocol_ObjWhenStreamExpected,
+ "Last exchange was " << mPreviousCommand <<
+ " => " << mPreviousReply);
+ }
+ else
+ {
+ throw;
+ }
}
+}
__E
+ }
if($writing_local)
{
@@ -853,23 +947,13 @@ __E
print H <<__E;
virtual int GetTimeout()
{
- return this->Protocol::GetTimeout();
+ return $custom_protocol_subclass\::GetTimeout();
}
__E
}
-
+
print H <<__E;
- /*
- virtual void Handshake()
- {
- this->Protocol::Handshake();
- }
- virtual bool GetLastError(int &rTypeOut, int &rSubTypeOut)
- {
- return this->Protocol::GetLastError(rTypeOut, rSubTypeOut);
- }
- */
-
+
private:
$server_or_client_class(const $server_or_client_class &rToCopy); /* no copies */
};
@@ -890,8 +974,8 @@ __E
else
{
print CPP <<__E;
-$server_or_client_class\::$server_or_client_class(IOStream &rStream)
-: Protocol(rStream)
+$server_or_client_class\::$server_or_client_class(std::auto_ptr<SocketStream> apConn)
+: $custom_protocol_subclass(apConn)
{ }
__E
}
@@ -903,49 +987,58 @@ $server_or_client_class\::~$server_or_client_class()
__E
# write receive and send functions
- print CPP <<__E;
-std::auto_ptr<Message> $server_or_client_class\::MakeMessage(int ObjType)
-{
- switch(ObjType)
- {
-__E
-
- # do objects within this
- for my $cmd (@cmd_list)
+ if($writing_local)
{
print CPP <<__E;
- case $cmd_id{$cmd}:
- return std::auto_ptr<Message>(new $cmd_class{$cmd}());
- break;
-__E
- }
-
- print CPP <<__E;
- default:
- THROW_EXCEPTION(ConnectionException, Conn_Protocol_UnknownCommandRecieved)
- }
+std::auto_ptr<$message_base_class> $server_or_client_class\::Receive()
+{
+ return mapLastReply;
+}
+void $server_or_client_class\::Send(const $message_base_class &rObject)
+{
+ mapLastReply = rObject.DoCommand(*this, mrContext);
}
__E
-
- if(not $writing_local)
+ }
+ else
{
print CPP <<__E;
std::auto_ptr<$message_base_class> $server_or_client_class\::Receive()
{
- std::auto_ptr<$message_base_class> preply(($message_base_class *)
- Protocol::ReceiveInternal().release());
+ std::auto_ptr<$message_base_class> apReply;
+
+ try
+ {
+ apReply = std::auto_ptr<$message_base_class>(
+ static_cast<$message_base_class *>
+ ($custom_protocol_subclass\::ReceiveInternal().release()));
+ }
+ catch(ConnectionException &e)
+ {
+ if(e.GetSubType() == ConnectionException::Protocol_StreamWhenObjExpected)
+ {
+ THROW_EXCEPTION_MESSAGE(ConnectionException,
+ Protocol_StreamWhenObjExpected,
+ "Last exchange was " << mPreviousCommand <<
+ " => " << mPreviousReply);
+ }
+ else
+ {
+ throw;
+ }
+ }
if(GetLogToSysLog())
{
- preply->LogSysLog("Receive");
+ apReply->LogSysLog("Receive");
}
if(GetLogToFile() != 0)
{
- preply->LogFile("Receive", GetLogToFile());
+ apReply->LogFile("Receive", GetLogToFile());
}
- return preply;
+ return apReply;
}
void $server_or_client_class\::Send(const $message_base_class &rObject)
@@ -981,10 +1074,40 @@ void $server_or_client_class\::DoServer($context_class &rContext)
{
// Get an object from the conversation
std::auto_ptr<$message_base_class> pobj = Receive();
+ std::auto_ptr<$message_base_class> preply;
// Run the command
- std::auto_ptr<$message_base_class> preply = pobj->DoCommand(*this, rContext);
-
+ try
+ {
+ try
+ {
+ if(pobj->HasStreamWithCommand())
+ {
+ std::auto_ptr<IOStream> apDataStream = ReceiveStream();
+ SelfFlushingStream autoflush(*apDataStream);
+ preply = pobj->DoCommand(*this, rContext, *apDataStream);
+ }
+ else
+ {
+ preply = pobj->DoCommand(*this, rContext);
+ }
+ }
+ catch(BoxException &e)
+ {
+ // First try a the built-in exception handler
+ preply = HandleException(e);
+ }
+ }
+ catch (...)
+ {
+ // Fallback in case the exception isn't a BoxException
+ // or the exception handler fails as well. This path
+ // throws the exception upwards, killing the process
+ // that handles the current client.
+ Send($cmd_classes{$error_message}(-1));
+ throw;
+ }
+
// Send the reply
Send(*preply);
@@ -995,7 +1118,16 @@ void $server_or_client_class\::DoServer($context_class &rContext)
{
SendStream(**i);
}
-
+
+ // As a server, if we get an unexpected message later, we'll
+ // want to know the last command that we received, and the
+ // reply, to help debug our response to it.
+ mPreviousCommand = pobj->ToString();
+ std::ostringstream reply;
+ reply << preply->ToString() << " and " <<
+ mStreamsToSend.size() << " streams";
+ mPreviousReply = reply.str();
+
// Delete these streams
DeleteStreamsToSend();
@@ -1004,7 +1136,7 @@ void $server_or_client_class\::DoServer($context_class &rContext)
{
inProgress = false;
}
- }
+ }
}
__E
@@ -1017,67 +1149,86 @@ __E
{
if(obj_is_type($cmd,'Command'))
{
- my $request_class = $cmd_class{$cmd};
+ my $request_class = $cmd_classes{$cmd};
my $reply_msg = obj_get_type_params($cmd,'Command');
- my $reply_class = $cmd_class{$reply_msg};
+ my $reply_class = $cmd_classes{$reply_msg};
my $reply_id = $cmd_id{$reply_msg};
my $has_stream = obj_is_type($cmd,'StreamWithCommand');
- my $argextra = $has_stream?', std::auto_ptr<IOStream> apStream':'';
+ my $argextra = $has_stream?', std::auto_ptr<IOStream> apDataStream':'';
my $send_stream_extra = '';
- my $send_stream_method = $writing_client ? "SendStream"
- : "SendStreamAfterCommand";
-
+
+ print CPP <<__E;
+std::auto_ptr<$reply_class> $server_or_client_class\::Query(const $request_class &rQuery$argextra)
+{
+__E
+
if($writing_client)
{
if($has_stream)
{
$send_stream_extra = <<__E;
// Send stream after the command
- SendStream(*apStream);
+ try
+ {
+ SendStream(*apDataStream);
+ }
+ catch (BoxException &e)
+ {
+ BOX_WARNING("Failed to send stream after command: " <<
+ rQuery.ToString() << ": " << e.what());
+ throw;
+ }
__E
}
print CPP <<__E;
-std::auto_ptr<$reply_class> $server_or_client_class\::Query(const $request_class &rQuery$argextra)
-{
// Send query
Send(rQuery);
- $send_stream_extra
+$send_stream_extra
// Wait for the reply
- std::auto_ptr<$message_base_class> preply = Receive();
-
- CheckReply("$cmd", *preply, $reply_id);
-
- // Correct response, if no exception thrown by CheckReply
- return std::auto_ptr<$reply_class>(($reply_class *)preply.release());
-}
+ std::auto_ptr<$message_base_class> apReply = Receive();
__E
}
elsif($writing_local)
{
+ print CPP <<__E;
+ std::auto_ptr<$message_base_class> apReply;
+ try
+ {
+__E
if($has_stream)
{
- $send_stream_extra = <<__E;
- // Send stream after the command
- SendStreamAfterCommand(apStream);
+ print CPP <<__E;
+ apReply = rQuery.DoCommand(*this, mrContext, *apDataStream);
+__E
+ }
+ else
+ {
+ print CPP <<__E;
+ apReply = rQuery.DoCommand(*this, mrContext);
__E
}
print CPP <<__E;
-std::auto_ptr<$reply_class> $server_or_client_class\::Query(const $request_class &rQuery$argextra)
-{
- // Send query
- $send_stream_extra
- std::auto_ptr<$message_base_class> preply = rQuery.DoCommand(*this, mrContext);
-
- CheckReply("$cmd", *preply, $reply_id);
+ }
+ catch(BoxException &e)
+ {
+ // First try a the built-in exception handler
+ apReply = HandleException(e);
+ }
+__E
+ }
+
+ # Common to both client and local
+ print CPP <<__E;
+ CheckReply("$cmd", rQuery, *apReply, $reply_id);
// Correct response, if no exception thrown by CheckReply
- return std::auto_ptr<$reply_class>(($reply_class *)preply.release());
+ return std::auto_ptr<$reply_class>(
+ static_cast<$reply_class *>(apReply.release()));
}
__E
- }
}
}
}
@@ -1110,7 +1261,7 @@ sub obj_get_type_params
{
return $1 if $_ =~ m/\A$ty\((.+?)\)\Z/;
}
- die "Can't find attribute $ty\n"
+ die "Can't find attribute $ty on command $c\n"
}
# returns (is basic type, typename)