Skip to content

Commit

Permalink
Embryo of RPCCallTimeoutHandler
Browse files Browse the repository at this point in the history
  • Loading branch information
leandro.costa committed Jun 10, 2010
1 parent da03bb1 commit a6dd88d
Show file tree
Hide file tree
Showing 7 changed files with 235 additions and 26 deletions.
36 changes: 33 additions & 3 deletions TODO
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
* Start to use issues in google codes to manage these tasks!!!

* Unit tests
We already have unit tests for casock::rpc::protobuf::client::RPCClientProxy. Now we need tests to other phases of the process:
- The sending of a message by client (casock::rpc::asio::protobuf::client::RPCClientProxy, socket client, communicator, etc.);
Expand All @@ -11,21 +13,49 @@
- RPCServerCommunicator should be removed from RPCSocketServer:
RPCSocketSession shoud register itself in RPCClientProxy, and RPCClientProxy should create an RPCServerCommunicator for each RPCSocketSession.
- Use googletest, googlemock and google-glog.
- It should be possible for the server to disconnect specific clients. For that, the RPCSocketSession should register itself in RPCServerProxy, and the RPCCall should identify the session from wich the request came. We need to think in a way to permit the user to disconnect a RPCClientSession from the RPC service implementation;
- addCallHandlers, removeCallHandlers and setNumCallHandlers should be methods of a superclass (RPCProxy) with a list of handlers (std::vector<Thread>).

* Documentation!!!
- We need Doxygen comments;
- We need update the UML diagrams in astah-community document (doc/casocklib.asta).

=== casock::rpc::protobuf::asio ===

* Check if sigio rpc server is closing socket when the user closes RPCServerProxy;
* Implement timeouts for calls, it should be possible for the user to decide what timeout to use;
- Add a method to set timeout in RPCClientProxy;
- Add a method to set timeout in RPCCallController;
- Add a method to build an RPCCallController from RPCClientProxy and deny direct costruction of RPCCallController;
- DONE: Add a method to set timeout in RPCClientProxy;
- DONE: Add a method to set timeout in RPCCallController;
- DONE: Add a method to build an RPCCallController from RPCClientProxy and deny direct costruction of RPCCallController;
- Implement cond_wait by useconds in casock::util::Lockable;
- Implement method find() that returns an RPCCall pointer (or NULL) in RPCCallHash;
- Create an RPCCall handler responsible for checking the timeout condition of each RPCCall. If a timeout happens, this handler should:
. Remove the RPCCall from the hash;
. Set the timeout condition in RPCCall::controller ();
. Put the RPCCall in the RPCCallQueue.
. Now we have RPCCallHash and RPCCallQueue inside RPCClientProxy. We need a new class to encapsulate these containers and the RPCCallTimeoutHandler. Eventually we will need a new container to controll timeouts (priority_queue).
. Create RPCCallTimeoutHandler:
. Characteristics:
. Inherits from Thread;
. Contains references to RPCCallHash and RPCCallQueue;
. Contains an RPCCall's ordered container (priority_queue);
. Permits register the pair RPCCall ID / timeout;
. Behavior:
. The method run () sleeps until the end of the earliest RPCCall timeout (the first in priority_queue).
When it is waken up, it pops up all pairs from priority_queue until it finds an RPCCall that is still in RPCCallHash and is not timed out doing the following with each entry:
When it is waken up, while there is RPCCall in the begining of priority_queue that is timed out or is not in RPCCallHash anymore, pops up the pair and do the following:
. If the RPCCall is timed out and it still exists in RPCCallHash:
. pops it from RPCCallhash;
. pushs it in RPCCallQueue;
. set timeout condition in RPCCallController.
. The method register () wakes up the thread if the pair is inserted in the first position of priority_queue.
. Specification:
. Should permit register RPCCall using ID (uint32) and timeout (struct timeval);
. Should push RPCCall from RPCCallHash, set timeout condition in RPCCallController and put it in RPCCallQueue after RPCCall timeout;
. Should discard RPCCalls that are not in RPCCallHash anymore after timeout;
. Should handle RPCCalls in order of timeout;
. Should handle only RPCCalls that are timed out or are not in RPCCallHash aymore.

- Add feature to RPCClientCommunicator to discard RPCCall response when it is not in the hash anymore.

* Make tests using more than 1 proxy (in client and server);
Expand Down
4 changes: 0 additions & 4 deletions src/casock/rpc/protobuf/api/rpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,3 @@ message RpcResponse {
required ResponseType type = 2;
optional bytes response = 3;
}

service RpcService {
rpc RpcCall (RpcRequest) returns (RpcResponse);
}
103 changes: 103 additions & 0 deletions src/casock/rpc/protobuf/client/RPCCallTimeoutHandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* casocklib - An asynchronous communication library for C++
* ---------------------------------------------------------
* Copyright (C) 2010 Leandro Costa
*
* This file is part of casocklib.
*
* casocklib is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* casocklib is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with casocklib. If not, see <http://www.gnu.org/licenses/>.
*/

/*!
* \file casock/rpc/protobuf/client/RPCCallTimeoutHandler.h
* \brief [brief description]
* \author Leandro Costa
* \date 2010
*
* $LastChangedDate$
* $LastChangedBy$
* $Revision$
*/

#ifndef __CASOCKLIB__CASOCK_RPC_PROTOBUF_CLIENT__RPC_CALL_TIMEOUT_HANDLER_H_
#define __CASOCKLIB__CASOCK_RPC_PROTOBUF_CLIENT__RPC_CALL_TIMEOUT_HANDLER_H_

#include "casock/util/Thread.h"
#include "casock/util/Lockable.h"

namespace casock {
namespace rpc {
namespace protobuf {
namespace client {
class RPCCallHash;
class RPCCallQueue;

class RPCCallTimeoutHandler : public casock::util::Thread, private casock::util::Lockable
{
public:
RPCCallTimeoutHandler (RPCCallHash& rCallHash, RPCCallQueue& rCallQueue)
//: id (0), timeout (), mrCallHash (rCallHash), mrCallQueue (rCallQueue)
: mrCallHash (rCallHash), mrCallQueue (rCallQueue)
{ }

public:
void run ()
{
/*
lock ();
while (true)
{
if (id == 0)
cond_wait ();
else
cond_wait (timeout.tv_sec);
if (! mrCallHash.find (id)) // or timeout already expired)
{
if (mrCallHash.find (id))
{
RPCCall* pCall = mrCallHash.pop (id);
}
}
}
*/
}

public:
void registerTimeout (const uint32& id, const struct timeval& timeout)
{
/*
lock ();
this->id = id;
this->timeout = timeout;
cond_signal ();
unlock ();
*/
};

private:
//uint32 id;
//struct timeval timeout;
RPCCallHash& mrCallHash;
RPCCallQueue& mrCallQueue;
};
}
}
}
}

#endif // __CASOCKLIB__CASOCK_RPC_PROTOBUF_CLIENT__RPC_CALL_TIMEOUT_HANDLER_H_
36 changes: 20 additions & 16 deletions src/tests/casock/rpc/protobuf/client/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ CXXTSRCS_RPC_CLIENT_PROXY = test_RPCClientProxy_cxx.cc
CXXTSRCS_RPC_REQUEST_BUILDER = test_RPCRequestBuilder_cxx.cc
CXXTSRCS = $(CXXTSRCS_RPC_CLIENT_PROXY) $(CXXTSRCS_RPC_REQUEST_BUILDER)

SRCS_RPC_CLIENT_PROXY = $(CXXTSRCS_RPC_CLIENT_PROXY) \
RPCCallHandlerMock.cc RPCCallHandlerFactoryMock.cc
SRCS_RPC_CLIENT_PROXY_CXX = $(CXXTSRCS_RPC_CLIENT_PROXY) \
RPCCallHandlerMock.cc RPCCallHandlerFactoryMock.cc

SRCS_RPC_REQUEST_BUILDER = $(CXXTSRCS_RPC_REQUEST_BUILDER)

SRCS_RPC_CLIENT_PROXY = test_RPCClientProxy.cc
SRCS_RPC_CALL_CONTROLLER = test_RPCCallController.cc
SRCS_RPC_CLIENT_PROXY = test_RPCClientProxy.cc
SRCS_RPC_CALL_CONTROLLER = test_RPCCallController.cc
SRCS_RPC_CALL_TIMEOUT_HANDLER = test_RPCCallTimeoutHandler.cc

LIB_UTIL = $(top_srcdir)/src/casock/util/libcasutil.la
LIB_RPCCLIENT = $(top_srcdir)/src/casock/rpc/protobuf/client/libcasrpcpbclient.la
Expand All @@ -17,23 +18,26 @@ LIB_RPCTEST1 = $(top_srcdir)/src/tests/casock/rpc/protobuf/api/libcasrpcpbtapi.

AM_CPPFLAGS = -DUSE_UT_CXXTEST

check_PROGRAMS = test_RPCClientProxy_cxx test_RPCRequestBuilder_cxx test_RPCClientProxy test_RPCCallController
check_PROGRAMS = test_RPCClientProxy_cxx test_RPCRequestBuilder_cxx test_RPCClientProxy test_RPCCallController test_RPCCallTimeoutHandler

test_RPCClientProxy_cxx_SOURCES = $(SRCS_RPC_CLIENT_PROXY)
test_RPCClientProxy_cxx_LDADD = $(LIB_RPCCLIENT) $(LIB_UTIL) $(LIB_RPCTEST1)# $(LIB_PROTOBUF)
test_RPCClientProxy_cxx_LDFLAGS = -static
test_RPCClientProxy_cxx_SOURCES = $(SRCS_RPC_CLIENT_PROXY_CXX)
test_RPCClientProxy_cxx_LDADD = $(LIB_RPCCLIENT) $(LIB_UTIL) $(LIB_RPCTEST1)# $(LIB_PROTOBUF)
#test_RPCClientProxy_cxx_LDFLAGS = -static

test_RPCRequestBuilder_cxx_SOURCES = $(SRCS_RPC_REQUEST_BUILDER)
test_RPCRequestBuilder_cxx_LDADD = $(LIB_RPCCLIENT) $(LIB_UTIL) $(LIB_RPCTEST1)# $(LIB_PROTOBUF)
test_RPCRequestBuilder_cxx_LDFLAGS = -static
test_RPCRequestBuilder_cxx_SOURCES = $(SRCS_RPC_REQUEST_BUILDER)
test_RPCRequestBuilder_cxx_LDADD = $(LIB_RPCCLIENT) $(LIB_UTIL) $(LIB_RPCTEST1)# $(LIB_PROTOBUF)
#test_RPCRequestBuilder_cxx_LDFLAGS = -static

test_RPCClientProxy_SOURCES = $(SRCS_RPC_CLIENT_PROXY)
test_RPCClientProxy_LDADD = $(LIB_RPCCLIENT) $(LIB_UTIL)
test_RPCClientProxy_SOURCES = $(SRCS_RPC_CLIENT_PROXY)
test_RPCClientProxy_LDADD = $(LIB_RPCCLIENT) $(LIB_UTIL)

test_RPCCallController_SOURCES = $(SRCS_RPC_CALL_CONTROLLER)
test_RPCCallController_LDADD = $(LIB_RPCCLIENT) $(LIB_UTIL)
test_RPCCallController_SOURCES = $(SRCS_RPC_CALL_CONTROLLER)
test_RPCCallController_LDADD = $(LIB_RPCCLIENT) $(LIB_UTIL)

TESTS = $(check_PROGRAMS)
test_RPCCallTimeoutHandler_SOURCES = $(SRCS_RPC_CALL_TIMEOUT_HANDLER)
test_RPCCallTimeoutHandler_LDADD = $(LIB_RPCCLIENT) $(LIB_UTIL)

TESTS = $(check_PROGRAMS)

%_cxx.cc: %_cxx.h
$(CXXTESTGEN) $(CXXTFLAGS) $< -o $@
Expand Down
2 changes: 2 additions & 0 deletions src/tests/casock/rpc/protobuf/client/RPCClientProxyTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
#ifndef __CASOCKLIB__TESTS_RPC_PROTOBUF_CLIENT__RPC_CLIENT_PROXY_TEST_H_
#define __CASOCKLIB__TESTS_RPC_PROTOBUF_CLIENT__RPC_CLIENT_PROXY_TEST_H_

#include <list>

#include "casock/rpc/protobuf/client/RPCClientProxy.h"

namespace casock {
Expand Down
72 changes: 72 additions & 0 deletions src/tests/casock/rpc/protobuf/client/test_RPCCallTimeoutHandler.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* casocklib - An asynchronous communication library for C++
* ---------------------------------------------------------
* Copyright (C) 2010 Leandro Costa
*
* This file is part of casocklib.
*
* casocklib is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* casocklib is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with casocklib. If not, see <http://www.gnu.org/licenses/>.
*/

/*!
* \file tests/casock/rpc/protobuf/client/test_RPCCallTimeoutHandler.cc
* \brief [brief description]
* \author Leandro Costa
* \date 2010
*
* $LastChangedDate$
* $LastChangedBy$
* $Revision$
*/

#include <gtest/gtest.h>

#include "casock/rpc/protobuf/api/rpc.pb.h"
#include "casock/rpc/protobuf/client/RPCCall.h"
#include "casock/rpc/protobuf/client/RPCCallHash.h"
#include "casock/rpc/protobuf/client/RPCCallQueue.h"
#include "casock/rpc/protobuf/client/RPCCallController.h"
#include "casock/rpc/protobuf/client/RPCCallTimeoutHandler.h"

#include "tests/casock/rpc/protobuf/client/RPCCallHandlerFactoryStub.h"
#include "tests/casock/rpc/protobuf/client/RPCClientProxyTest.h"

TEST(casock_rpc_protobuf_client_RPCCallTimeoutHandler, Basic) {
casock::rpc::protobuf::client::RPCCallHash hash;
casock::rpc::protobuf::client::RPCCallQueue queue;
casock::rpc::protobuf::client::RPCCallTimeoutHandler handler (hash, queue);

handler.run ();

uint32 id = 0;
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;

tests::casock::rpc::protobuf::client::RPCCallHandlerFactoryStub factory;
tests::casock::rpc::protobuf::client::RPCClientProxyTest proxy (factory);
casock::rpc::protobuf::client::RPCCallController* pController = proxy.buildRPCCallController ();
casock::rpc::protobuf::client::RPCCall *pCall = new casock::rpc::protobuf::client::RPCCall (NULL, pController, NULL);
hash.push (id, pCall);

handler.registerTimeout (id, pController->timeout ());
usleep (1000000 * pController->timeoutInUSeconds ());

//EXPECT_TRUE (pController->Failed ());
}

int main (int argc, char **argv) {
::testing::InitGoogleTest (&argc, argv);
return RUN_ALL_TESTS();
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,13 @@ class test_RPCClientProxy_cxx : public CxxTest::TestSuite

tests::casock::rpc::protobuf::api::TestRequest request;
tests::casock::rpc::protobuf::api::TestResponse response;
casock::rpc::protobuf::client::RPCCallController controller;
casock::rpc::protobuf::client::RPCCallController* controller = proxy.buildRPCCallController ();
tests::casock::rpc::protobuf::client::RPCResponseHandlerMock handler;

request.set_id (1);
request.set_message (2);

pService->TestCall (&controller, &request, &response, handler.closure ());
pService->TestCall (controller, &request, &response, handler.closure ());

TS_ASSERT_EQUALS ((size_t) 1, proxy.requests.size ());

Expand All @@ -146,10 +146,12 @@ class test_RPCClientProxy_cxx : public CxxTest::TestSuite
TS_ASSERT_EQUALS (request.SerializeAsString (), proxy.requests.front ().first.request ());

TS_ASSERT_EQUALS (&response, proxy.requests.front ().second->response ());
TS_ASSERT_EQUALS (&controller, proxy.requests.front ().second->controller ());
TS_ASSERT_EQUALS (controller, proxy.requests.front ().second->controller ());

proxy.requests.front ().second->closure ()->Run ();
TS_ASSERT_EQUALS (true, handler.called);

delete controller;
}
};

Expand Down

0 comments on commit a6dd88d

Please sign in to comment.