@@ -2,6 +2,8 @@ use bytes::{Buf, BufMut, BytesMut};
22use log:: { info, trace} ;
33use tokio:: net:: tcp:: OwnedWriteHalf ;
44
5+ use std:: collections:: HashMap ;
6+
57use crate :: config:: { get_config, parse} ;
68use crate :: constants:: { OID_NUMERIC , OID_TEXT } ;
79use crate :: errors:: Error ;
@@ -27,6 +29,9 @@ pub async fn handle_admin(stream: &mut OwnedWriteHalf, mut query: BytesMut) -> R
2729 } else if query. starts_with ( "RELOAD" ) {
2830 trace ! ( "RELOAD" ) ;
2931 reload ( stream) . await
32+ } else if query. starts_with ( "SHOW CONFIG" ) {
33+ trace ! ( "SHOW CONFIG" ) ;
34+ show_config ( stream) . await
3035 } else {
3136 Err ( Error :: ProtocolSyncError )
3237 }
@@ -61,6 +66,92 @@ pub async fn reload(stream: &mut OwnedWriteHalf) -> Result<(), Error> {
6166 write_all_half ( stream, res) . await
6267}
6368
69+ pub async fn show_config ( stream : & mut OwnedWriteHalf ) -> Result < ( ) , Error > {
70+ let guard = get_config ( ) ;
71+ let config = & * guard. clone ( ) ;
72+ let config: HashMap < String , String > = config. into ( ) ;
73+ drop ( guard) ;
74+
75+ // Configs that cannot be changed dynamically.
76+ let immutables = [ "host" , "port" , "connect_timeout" ] ;
77+
78+ // Columns
79+ let columns = [ "key" , "value" , "default" , "changeable" ] ;
80+
81+ // RowDescription
82+ let mut row_desc = BytesMut :: new ( ) ;
83+ row_desc. put_i16 ( 4 as i16 ) ; // key, value, default, changeable
84+
85+ for column in columns {
86+ row_desc. put_slice ( & format ! ( "{}\0 " , column) . as_bytes ( ) ) ;
87+
88+ // Doesn't belong to any table
89+ row_desc. put_i32 ( 0 ) ;
90+
91+ // Doesn't belong to any table
92+ row_desc. put_i16 ( 0 ) ;
93+
94+ // Data type
95+ row_desc. put_i32 ( OID_TEXT ) ;
96+
97+ // text size = variable (-1)
98+ row_desc. put_i16 ( -1 ) ;
99+
100+ // Type modifier: none that I know
101+ row_desc. put_i32 ( -1 ) ;
102+
103+ // Format being used: text (0), binary (1)
104+ row_desc. put_i16 ( 0 ) ;
105+ }
106+
107+ // Response data
108+ let mut res = BytesMut :: new ( ) ;
109+ res. put_u8 ( b'T' ) ;
110+ res. put_i32 ( row_desc. len ( ) as i32 + 4 ) ;
111+ res. put ( row_desc) ;
112+
113+ // DataRow rows
114+ for ( key, value) in config {
115+ let mut data_row = BytesMut :: new ( ) ;
116+
117+ data_row. put_i16 ( 4 as i16 ) ; // key, value, default, changeable
118+
119+ let key_bytes = key. as_bytes ( ) ;
120+ let value = value. as_bytes ( ) ;
121+
122+ data_row. put_i32 ( key_bytes. len ( ) as i32 ) ;
123+ data_row. put_slice ( & key_bytes) ;
124+
125+ data_row. put_i32 ( value. len ( ) as i32 ) ;
126+ data_row. put_slice ( & value) ;
127+
128+ data_row. put_i32 ( 1 as i32 ) ;
129+ data_row. put_slice ( & "-" . as_bytes ( ) ) ;
130+
131+ let changeable = if immutables. iter ( ) . filter ( |col| * col == & key) . count ( ) == 1 {
132+ "no" . as_bytes ( )
133+ } else {
134+ "yes" . as_bytes ( )
135+ } ;
136+ data_row. put_i32 ( changeable. len ( ) as i32 ) ;
137+ data_row. put_slice ( & changeable) ;
138+
139+ res. put_u8 ( b'D' ) ;
140+ res. put_i32 ( data_row. len ( ) as i32 + 4 ) ;
141+ res. put ( data_row) ;
142+ }
143+
144+ res. put_u8 ( b'C' ) ;
145+ res. put_i32 ( "SHOW CONFIG\0 " . as_bytes ( ) . len ( ) as i32 + 4 ) ;
146+ res. put_slice ( & "SHOW CONFIG\0 " . as_bytes ( ) ) ;
147+
148+ res. put_u8 ( b'Z' ) ;
149+ res. put_i32 ( 5 ) ;
150+ res. put_u8 ( b'I' ) ;
151+
152+ write_all_half ( stream, res) . await
153+ }
154+
64155/// SHOW STATS
65156pub async fn show_stats ( stream : & mut OwnedWriteHalf ) -> Result < ( ) , Error > {
66157 let columns = [
0 commit comments