@@ -15,7 +15,7 @@ use tokio::net::TcpStream;
15
15
use tokio_rustls:: rustls:: { OwnedTrustAnchor , RootCertStore } ;
16
16
use tokio_rustls:: { client:: TlsStream , TlsConnector } ;
17
17
18
- use crate :: config:: { get_config, Address , User } ;
18
+ use crate :: config:: { get_config, get_prepared_statements_cache_size , Address , User } ;
19
19
use crate :: constants:: * ;
20
20
use crate :: dns_cache:: { AddrSet , CACHED_RESOLVER } ;
21
21
use crate :: errors:: { Error , ServerIdentifier } ;
@@ -914,12 +914,16 @@ impl Server {
914
914
Ok ( bytes)
915
915
}
916
916
917
+ /// Add the prepared statement to being tracked by this server.
918
+ /// The client is processing data that will create a prepared statement on this server.
917
919
pub fn will_prepare ( & mut self , name : & str ) {
918
920
debug ! ( "Will prepare `{}`" , name) ;
919
921
920
922
self . prepared_statements . insert ( name. to_string ( ) ) ;
923
+ self . stats . prepared_cache_add ( ) ;
921
924
}
922
925
926
+ /// Check if we should prepare a statement on the server.
923
927
pub fn should_prepare ( & self , name : & str ) -> bool {
924
928
let should_prepare = !self . prepared_statements . contains ( name) ;
925
929
@@ -934,6 +938,7 @@ impl Server {
934
938
should_prepare
935
939
}
936
940
941
+ /// Create a prepared statement on the server.
937
942
pub async fn prepare ( & mut self , parse : & Parse ) -> Result < ( ) , Error > {
938
943
debug ! ( "Preparing `{}`" , parse. name) ;
939
944
@@ -942,15 +947,82 @@ impl Server {
942
947
self . send ( & flush ( ) ) . await ?;
943
948
944
949
// Read and discard ParseComplete (B)
945
- let _ = read_message ( & mut self . stream ) . await ?;
950
+ match read_message ( & mut self . stream ) . await {
951
+ Ok ( _) => ( ) ,
952
+ Err ( err) => {
953
+ self . bad = true ;
954
+ return Err ( err) ;
955
+ }
956
+ }
946
957
947
958
self . prepared_statements . insert ( parse. name . to_string ( ) ) ;
959
+ self . stats . prepared_cache_add ( ) ;
948
960
949
961
debug ! ( "Prepared `{}`" , parse. name) ;
950
962
951
963
Ok ( ( ) )
952
964
}
953
965
966
+ /// Maintain adequate cache size on the server.
967
+ pub async fn maintain_cache ( & mut self ) -> Result < ( ) , Error > {
968
+ debug ! ( "Cache maintenance run" ) ;
969
+
970
+ let max_cache_size = get_prepared_statements_cache_size ( ) ;
971
+ let mut names = Vec :: new ( ) ;
972
+
973
+ while self . prepared_statements . len ( ) >= max_cache_size {
974
+ // The prepared statmeents are alphanumerically sorted by the BTree.
975
+ // FIFO.
976
+ if let Some ( name) = self . prepared_statements . pop_last ( ) {
977
+ names. push ( name) ;
978
+ }
979
+ }
980
+
981
+ self . deallocate ( names) . await ?;
982
+
983
+ Ok ( ( ) )
984
+ }
985
+
986
+ /// Remove the prepared statement from being tracked by this server.
987
+ /// The client is processing data that will cause the server to close the prepared statement.
988
+ pub fn will_close ( & mut self , name : & str ) {
989
+ debug ! ( "Will close `{}`" , name) ;
990
+
991
+ self . prepared_statements . remove ( name) ;
992
+ }
993
+
994
+ /// Close a prepared statement on the server.
995
+ pub async fn deallocate ( & mut self , names : Vec < String > ) -> Result < ( ) , Error > {
996
+ for name in & names {
997
+ debug ! ( "Deallocating prepared statement `{}`" , name) ;
998
+
999
+ let close = Close :: new ( name) ;
1000
+ let bytes: BytesMut = close. try_into ( ) ?;
1001
+
1002
+ self . send ( & bytes) . await ?;
1003
+ }
1004
+
1005
+ self . send ( & flush ( ) ) . await ?;
1006
+
1007
+ // Read and discard CloseComplete (3)
1008
+ for name in & names {
1009
+ match read_message ( & mut self . stream ) . await {
1010
+ Ok ( _) => {
1011
+ self . prepared_statements . remove ( name) ;
1012
+ self . stats . prepared_cache_remove ( ) ;
1013
+ debug ! ( "Closed `{}`" , name) ;
1014
+ }
1015
+
1016
+ Err ( err) => {
1017
+ self . bad = true ;
1018
+ return Err ( err) ;
1019
+ }
1020
+ } ;
1021
+ }
1022
+
1023
+ Ok ( ( ) )
1024
+ }
1025
+
954
1026
/// If the server is still inside a transaction.
955
1027
/// If the client disconnects while the server is in a transaction, we will clean it up.
956
1028
pub fn in_transaction ( & self ) -> bool {
0 commit comments