rpc connection patch

Ove Kaaven ovek at arcticnet.no
Sat Apr 19 07:44:01 CDT 2003


Connection caching improves the speed at which RPC calls can be made
drastically, since a new connection no longer needs to be established
for every call. Cache cleaning not implemented yet, but cached stuff
tend to go away when the involved processes shut down anyway...

Since this patch may hide named pipe race condition bugs exposed by
heavy RPC traffic (although not COM yet, which still uses its own
framework), apply at your discretion.

Log:
Ove Kaaven <ovek at transgaming.com>
Implemented simple caching of client connections.

Index: dlls/rpcrt4/rpc_binding.c
===================================================================
RCS file: /cvsroot/rewind/rewind/dlls/rpcrt4/rpc_binding.c,v
retrieving revision 1.11
diff -u -r1.11 rpc_binding.c
--- dlls/rpcrt4/rpc_binding.c	18 Apr 2003 02:04:18 -0000	1.11
+++ dlls/rpcrt4/rpc_binding.c	19 Apr 2003 12:32:07 -0000
@@ -26,6 +26,9 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(ole);
 
+static RpcConnection* conn_cache;
+static CRITICAL_SECTION conn_cache_cs = CRITICAL_SECTION_INIT("conn_cache_cs");
+
 LPSTR RPCRT4_strndupA(LPSTR src, INT slen)
 {
   DWORD len;
@@ -79,7 +82,7 @@
   if (src) HeapFree(GetProcessHeap(), 0, src);
 }
 
-RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPSTR Protseq, LPSTR NetworkAddr, LPSTR Endpoint, LPSTR NetworkOptions)
+RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPSTR Protseq, LPSTR NetworkAddr, LPSTR Endpoint, LPSTR NetworkOptions, RpcBinding* Binding)
 {
   RpcConnection* NewConnection;
 
@@ -88,6 +91,12 @@
   NewConnection->Protseq = RPCRT4_strdupA(Protseq);
   NewConnection->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
   NewConnection->Endpoint = RPCRT4_strdupA(Endpoint);
+  NewConnection->Used = Binding;
+
+  EnterCriticalSection(&conn_cache_cs);
+  NewConnection->Next = conn_cache;
+  conn_cache = NewConnection;
+  LeaveCriticalSection(&conn_cache_cs);
 
   TRACE("connection: %p\n", NewConnection);
   *Connection = NewConnection;
@@ -97,8 +106,18 @@
 
 RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection)
 {
+  RpcConnection* PrevConnection;
+
   TRACE("connection: %p\n", Connection);
   if (Connection->Used) ERR("connection is still in use\n");
+
+  EnterCriticalSection(&conn_cache_cs);
+  PrevConnection = conn_cache;
+  while (PrevConnection && PrevConnection->Next != Connection)
+    PrevConnection = PrevConnection->Next;
+  if (PrevConnection) PrevConnection->Next = Connection->Next;
+  LeaveCriticalSection(&conn_cache_cs);
+
   RPCRT4_CloseConnection(Connection);
   RPCRT4_strfree(Connection->Endpoint);
   RPCRT4_strfree(Connection->NetworkAddr);
@@ -107,6 +126,44 @@
   return RPC_S_OK;
 }
 
+RPC_STATUS RPCRT4_GetConnection(RpcConnection** Connection, BOOL server, LPSTR Protseq, LPSTR NetworkAddr, LPSTR Endpoint, LPSTR NetworkOptions, RpcBinding* Binding)
+{
+  RpcConnection* NewConnection;
+
+  if (!server) {
+    EnterCriticalSection(&conn_cache_cs);
+    for (NewConnection = conn_cache; NewConnection; NewConnection = NewConnection->Next) {
+      if (NewConnection->Used) continue;
+      if (NewConnection->server != server) continue;
+      if (Protseq && strcmp(NewConnection->Protseq, Protseq)) continue;
+      if (NetworkAddr && strcmp(NewConnection->NetworkAddr, NetworkAddr)) continue;
+      if (Endpoint && strcmp(NewConnection->Endpoint, Endpoint)) continue;
+      /* this connection fits the bill */
+      NewConnection->Used = Binding;
+      break;
+    }
+    LeaveCriticalSection(&conn_cache_cs);
+    if (NewConnection) {
+      TRACE("cached connection: %p\n", NewConnection);
+      *Connection = NewConnection;
+      return RPC_S_OK;
+    }
+  }
+  return RPCRT4_CreateConnection(Connection, server, Protseq, NetworkAddr, Endpoint, NetworkOptions, Binding);
+}
+
+RPC_STATUS RPCRT4_ReleaseConnection(RpcConnection* Connection)
+{
+  TRACE("connection: %p\n", Connection);
+  Connection->Used = NULL;
+  if (!Connection->server) {
+    /* cache the open connection for reuse later */
+    /* FIXME: we should probably clean the cache someday */
+    return RPC_S_OK;
+  }
+  return RPCRT4_DestroyConnection(Connection);
+}
+
 RPC_STATUS RPCRT4_OpenConnection(RpcConnection* Connection)
 {
   TRACE("(Connection == ^%p)\n", Connection);
@@ -250,7 +307,7 @@
 {
   RpcConnection* NewConnection;
   RPC_STATUS err = RPCRT4_CreateConnection(&NewConnection, OldConnection->server, OldConnection->Protseq,
-                                           OldConnection->NetworkAddr, OldConnection->Endpoint, NULL);
+                                           OldConnection->NetworkAddr, OldConnection->Endpoint, NULL, NULL);
   if (err == RPC_S_OK) {
     /* because of the way named pipes work, we'll transfer the connected pipe
      * to the child, then reopen the server binding to continue listening */
@@ -404,9 +461,7 @@
     return RPC_S_OK;
   }
 
-  /* FIXME: cache connections */
-  RPCRT4_CreateConnection(&NewConnection, Binding->server, Binding->Protseq, Binding->NetworkAddr, Binding->Endpoint, NULL);
-  NewConnection->Used = Binding;
+  RPCRT4_GetConnection(&NewConnection, Binding->server, Binding->Protseq, Binding->NetworkAddr, Binding->Endpoint, NULL, Binding);
   *Connection = NewConnection;
   return RPCRT4_OpenConnection(NewConnection);
 }
@@ -416,8 +471,7 @@
   TRACE("(Binding == ^%p)\n", Binding);
   if (!Connection) return RPC_S_OK;
   if (Binding->FromConn == Connection) return RPC_S_OK;
-  Connection->Used = NULL;
-  return RPCRT4_DestroyConnection(Connection);
+  return RPCRT4_ReleaseConnection(Connection);
 }
 
 /* utility functions for string composing and parsing */
Index: dlls/rpcrt4/rpc_binding.h
===================================================================
RCS file: /cvsroot/rewind/rewind/dlls/rpcrt4/rpc_binding.h,v
retrieving revision 1.4
diff -u -r1.4 rpc_binding.h
--- dlls/rpcrt4/rpc_binding.h	18 Apr 2003 02:04:18 -0000	1.4
+++ dlls/rpcrt4/rpc_binding.h	19 Apr 2003 12:32:07 -0000
@@ -46,7 +46,7 @@
 #define RPCRT4_strdupA(x) RPCRT4_strndupA((x),-1)
 #define RPCRT4_strdupW(x) RPCRT4_strndupW((x),-1)
 
-RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPSTR Protseq, LPSTR NetworkAddr, LPSTR Endpoint, LPSTR NetworkOptions);
+RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPSTR Protseq, LPSTR NetworkAddr, LPSTR Endpoint, LPSTR NetworkOptions, RpcBinding* Binding);
 RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection);
 RPC_STATUS RPCRT4_OpenConnection(RpcConnection* Connection);
 RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection);
Index: dlls/rpcrt4/rpc_server.c
===================================================================
RCS file: /cvsroot/rewind/rewind/dlls/rpcrt4/rpc_server.c,v
retrieving revision 1.13
diff -u -r1.13 rpc_server.c
--- dlls/rpcrt4/rpc_server.c	19 Apr 2003 12:20:28 -0000	1.13
+++ dlls/rpcrt4/rpc_server.c	19 Apr 2003 12:32:07 -0000
@@ -419,7 +420,7 @@
 
 static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps)
 {
-  RPCRT4_CreateConnection(&ps->conn, TRUE, ps->Protseq, NULL, ps->Endpoint, NULL);
+  RPCRT4_CreateConnection(&ps->conn, TRUE, ps->Protseq, NULL, ps->Endpoint, NULL, NULL);
 
   EnterCriticalSection(&server_cs);
   ps->Next = protseqs;






More information about the wine-patches mailing list