@@ -2,6 +2,8 @@ use bytes::{Buf, BufMut, BytesMut};
2
2
use log:: { info, trace} ;
3
3
use tokio:: net:: tcp:: OwnedWriteHalf ;
4
4
5
+ use std:: collections:: HashMap ;
6
+
5
7
use crate :: config:: { get_config, parse} ;
6
8
use crate :: constants:: { OID_NUMERIC , OID_TEXT } ;
7
9
use crate :: errors:: Error ;
@@ -27,6 +29,9 @@ pub async fn handle_admin(stream: &mut OwnedWriteHalf, mut query: BytesMut) -> R
27
29
} else if query. starts_with ( "RELOAD" ) {
28
30
trace ! ( "RELOAD" ) ;
29
31
reload ( stream) . await
32
+ } else if query. starts_with ( "SHOW CONFIG" ) {
33
+ trace ! ( "SHOW CONFIG" ) ;
34
+ show_config ( stream) . await
30
35
} else {
31
36
Err ( Error :: ProtocolSyncError )
32
37
}
@@ -61,6 +66,92 @@ pub async fn reload(stream: &mut OwnedWriteHalf) -> Result<(), Error> {
61
66
write_all_half ( stream, res) . await
62
67
}
63
68
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
+
64
155
/// SHOW STATS
65
156
pub async fn show_stats ( stream : & mut OwnedWriteHalf ) -> Result < ( ) , Error > {
66
157
let columns = [
0 commit comments