rpcrt4: Implement a process-wide connection pool for client connections,

rather than relying on the restriction of one connection per
binding. This also avoids the problem of two threads using the same
connection at the same time.
This commit is contained in:
Robert Shearman 2006-06-07 20:12:34 +01:00 committed by Alexandre Julliard
parent 1412c47a50
commit 58ec282bfb
3 changed files with 73 additions and 13 deletions

View File

@ -237,16 +237,15 @@ RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
TRACE("(Binding == ^%p)\n", Binding);
/* if we try to bind a new interface and the connection is already opened,
* close the current connection and create a new with the new binding. */
if (!Binding->server && Binding->FromConn &&
(Binding->AuthInfo == Binding->FromConn->AuthInfo) &&
memcmp(&Binding->FromConn->ActiveInterface, InterfaceId,
sizeof(RPC_SYNTAX_IDENTIFIER))) {
TRACE("releasing pre-existing connection\n");
RPCRT4_DestroyConnection(Binding->FromConn);
Binding->FromConn = NULL;
if (!Binding->server) {
/* try to find a compatible connection from the connection pool */
NewConnection = RPCRT4_GetIdleConnection(InterfaceId, TransferSyntax,
Binding->Protseq, Binding->NetworkAddr, Binding->Endpoint,
Binding->AuthInfo);
if (NewConnection) {
*Connection = NewConnection;
return RPC_S_OK;
}
} else {
/* we already have a connection with acceptable binding, so use it */
if (Binding->FromConn) {
@ -307,7 +306,8 @@ RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
RPCRT4_FreeHeader(response_hdr);
}
Binding->FromConn = NewConnection;
if (Binding->server)
Binding->FromConn = NewConnection;
*Connection = NewConnection;
return RPC_S_OK;
@ -317,8 +317,16 @@ RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
{
TRACE("(Binding == ^%p)\n", Binding);
if (!Connection) return RPC_S_OK;
if (Binding->FromConn == Connection) return RPC_S_OK;
return RPCRT4_DestroyConnection(Connection);
if (Binding->server) {
/* don't destroy a connection that is cached in the binding */
if (Binding->FromConn == Connection)
return RPC_S_OK;
return RPCRT4_DestroyConnection(Connection);
}
else {
RPCRT4_ReleaseIdleConnection(Connection);
return RPC_S_OK;
}
}
/* utility functions for string composing and parsing */

View File

@ -23,6 +23,7 @@
#include "wine/rpcss_shared.h"
#include "security.h"
#include "wine/list.h"
typedef struct _RpcAuthInfo
@ -55,6 +56,9 @@ typedef struct _RpcConnection
TimeStamp exp;
ULONG attr;
RpcAuthInfo *AuthInfo;
/* client-only */
struct list conn_pool_entry;
} RpcConnection;
struct protseq_ops {
@ -101,6 +105,8 @@ void RPCRT4_strfree(LPSTR src);
ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo);
ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo);
RpcConnection *RPCRT4_GetIdleConnection(const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, RpcAuthInfo* AuthInfo);
void RPCRT4_ReleaseIdleConnection(RpcConnection *Connection);
RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcBinding* Binding);
RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection);
RPC_STATUS RPCRT4_OpenConnection(RpcConnection* Connection);

View File

@ -68,6 +68,17 @@
WINE_DEFAULT_DEBUG_CHANNEL(rpc);
static CRITICAL_SECTION connection_pool_cs;
static CRITICAL_SECTION_DEBUG connection_pool_cs_debug =
{
0, 0, &connection_pool_cs,
{ &connection_pool_cs_debug.ProcessLocksList, &connection_pool_cs_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": connection_pool") }
};
static CRITICAL_SECTION connection_pool_cs = { &connection_pool_cs_debug, -1, 0, 0, 0, 0 };
static struct list connection_pool = LIST_INIT(connection_pool);
/**** ncacn_np support ****/
typedef struct _RpcConnection_np
@ -777,6 +788,7 @@ RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server,
NewConnection->NextCallId = 1;
if (AuthInfo) RpcAuthInfo_AddRef(AuthInfo);
NewConnection->AuthInfo = AuthInfo;
list_init(&NewConnection->conn_pool_entry);
TRACE("connection: %p\n", NewConnection);
*Connection = NewConnection;
@ -784,6 +796,40 @@ RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server,
return RPC_S_OK;
}
RpcConnection *RPCRT4_GetIdleConnection(const RPC_SYNTAX_IDENTIFIER *InterfaceId,
const RPC_SYNTAX_IDENTIFIER *TransferSyntax, LPCSTR Protseq, LPCSTR NetworkAddr,
LPCSTR Endpoint, RpcAuthInfo* AuthInfo)
{
RpcConnection *Connection;
/* try to find a compatible connection from the connection pool */
EnterCriticalSection(&connection_pool_cs);
LIST_FOR_EACH_ENTRY(Connection, &connection_pool, RpcConnection, conn_pool_entry)
if ((Connection->AuthInfo == AuthInfo) &&
!memcmp(&Connection->ActiveInterface, InterfaceId,
sizeof(RPC_SYNTAX_IDENTIFIER)) &&
!strcmp(rpcrt4_conn_get_name(Connection), Protseq) &&
!strcmp(Connection->NetworkAddr, NetworkAddr) &&
!strcmp(Connection->Endpoint, Endpoint))
{
list_remove(&Connection->conn_pool_entry);
LeaveCriticalSection(&connection_pool_cs);
TRACE("got connection from pool %p\n", Connection);
return Connection;
}
LeaveCriticalSection(&connection_pool_cs);
return NULL;
}
void RPCRT4_ReleaseIdleConnection(RpcConnection *Connection)
{
assert(!Connection->server);
EnterCriticalSection(&connection_pool_cs);
list_add_head(&connection_pool, &Connection->conn_pool_entry);
LeaveCriticalSection(&connection_pool_cs);
}
RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection)
{
RPC_STATUS err;