@@ -2505,6 +2505,52 @@ impl PageServiceCmd {
2505
2505
}
2506
2506
}
2507
2507
2508
+ fn parse_options ( options : & str ) -> ( Vec < ( String , String ) > , bool ) {
2509
+ let mut parsing_config = false ;
2510
+ let mut has_error = false ;
2511
+ let mut config = Vec :: new ( ) ;
2512
+ for item in options. split_whitespace ( ) {
2513
+ if item == "-c" {
2514
+ if !parsing_config {
2515
+ parsing_config = true ;
2516
+ } else {
2517
+ // "-c" followed with another "-c"
2518
+ tracing:: warn!( "failed to parse the startup options: {options}" ) ;
2519
+ has_error = true ;
2520
+ break ;
2521
+ }
2522
+ } else if item. starts_with ( "-c" ) || parsing_config {
2523
+ let Some ( ( mut key, value) ) = item. split_once ( '=' ) else {
2524
+ // "-c" followed with an invalid option
2525
+ tracing:: warn!( "failed to parse the startup options: {options}" ) ;
2526
+ has_error = true ;
2527
+ break ;
2528
+ } ;
2529
+ if !parsing_config {
2530
+ // Parse "-coptions=X"
2531
+ let Some ( stripped_key) = key. strip_prefix ( "-c" ) else {
2532
+ tracing:: warn!( "failed to parse the startup options: {options}" ) ;
2533
+ has_error = true ;
2534
+ break ;
2535
+ } ;
2536
+ key = stripped_key;
2537
+ }
2538
+ config. push ( ( key. to_string ( ) , value. to_string ( ) ) ) ;
2539
+ parsing_config = false ;
2540
+ } else {
2541
+ tracing:: warn!( "failed to parse the startup options: {options}" ) ;
2542
+ has_error = true ;
2543
+ break ;
2544
+ }
2545
+ }
2546
+ if parsing_config {
2547
+ // "-c" without the option
2548
+ tracing:: warn!( "failed to parse the startup options: {options}" ) ;
2549
+ has_error = true ;
2550
+ }
2551
+ ( config, has_error)
2552
+ }
2553
+
2508
2554
impl < IO > postgres_backend:: Handler < IO > for PageServerHandler
2509
2555
where
2510
2556
IO : AsyncRead + AsyncWrite + Send + Sync + Unpin + ' static ,
@@ -2550,46 +2596,12 @@ where
2550
2596
Span :: current ( ) . record ( "application_name" , field:: display ( app_name) ) ;
2551
2597
}
2552
2598
if let Some ( options) = params. get ( "options" ) {
2553
- let mut parsing_config = false ;
2554
- for item in options. split_whitespace ( ) {
2555
- if item == "-c" {
2556
- if !parsing_config {
2557
- parsing_config = true ;
2558
- } else {
2559
- // "-c" followed with another "-c"
2560
- tracing:: warn!( "failed to parse the startup options: {options}" ) ;
2561
- break ;
2562
- }
2563
- } else if item. starts_with ( "-c" ) || parsing_config {
2564
- let Some ( ( mut key, value) ) = item. split_once ( '=' ) else {
2565
- // "-c" followed with an invalid option
2566
- tracing:: warn!( "failed to parse the startup options: {options}" ) ;
2567
- break ;
2568
- } ;
2569
- if !parsing_config {
2570
- // Parse "-coptions=X"
2571
- let Some ( stripped_key) = key. strip_prefix ( "-c" ) else {
2572
- tracing:: warn!( "failed to parse the startup options: {options}" ) ;
2573
- break ;
2574
- } ;
2575
- key = stripped_key;
2576
- }
2577
- if key == "neon.endpoint_type" {
2578
- Span :: current ( ) . record ( "endpoint_type" , field:: display ( value) ) ;
2579
- } else {
2580
- tracing:: warn!( "failed to parse the startup options: {options}" ) ;
2581
- break ;
2582
- }
2583
- parsing_config = false ;
2584
- } else {
2585
- tracing:: warn!( "failed to parse the startup options: {options}" ) ;
2586
- break ;
2599
+ let ( config, _) = parse_options ( options) ;
2600
+ for ( key, value) in config {
2601
+ if key == "neon.endpoint_type" {
2602
+ Span :: current ( ) . record ( "endpoint_type" , field:: display ( value) ) ;
2587
2603
}
2588
2604
}
2589
- if parsing_config {
2590
- // "-c" without the option
2591
- tracing:: warn!( "failed to parse the startup options: {options}" ) ;
2592
- }
2593
2605
}
2594
2606
} ;
2595
2607
@@ -2979,4 +2991,46 @@ mod tests {
2979
2991
let cmd = PageServiceCmd :: parse ( & format ! ( "lease {tenant_id} {timeline_id} gzip 0/16ABCDE" ) ) ;
2980
2992
assert ! ( cmd. is_err( ) ) ;
2981
2993
}
2994
+
2995
+ #[ test]
2996
+ fn test_parse_options ( ) {
2997
+ let ( config, has_error) = parse_options ( " -c neon.endpoint_type=primary " ) ;
2998
+ assert ! ( !has_error) ;
2999
+ assert_eq ! (
3000
+ config,
3001
+ vec![ ( "neon.endpoint_type" . to_string( ) , "primary" . to_string( ) ) ]
3002
+ ) ;
3003
+
3004
+ let ( config, has_error) = parse_options ( " -c neon.endpoint_type=primary -c foo=bar " ) ;
3005
+ assert ! ( !has_error) ;
3006
+ assert_eq ! (
3007
+ config,
3008
+ vec![
3009
+ ( "neon.endpoint_type" . to_string( ) , "primary" . to_string( ) ) ,
3010
+ ( "foo" . to_string( ) , "bar" . to_string( ) ) ,
3011
+ ]
3012
+ ) ;
3013
+
3014
+ let ( config, has_error) = parse_options ( " -c neon.endpoint_type=primary -cfoo=bar" ) ;
3015
+ assert ! ( !has_error) ;
3016
+ assert_eq ! (
3017
+ config,
3018
+ vec![
3019
+ ( "neon.endpoint_type" . to_string( ) , "primary" . to_string( ) ) ,
3020
+ ( "foo" . to_string( ) , "bar" . to_string( ) ) ,
3021
+ ]
3022
+ ) ;
3023
+
3024
+ let ( _, has_error) = parse_options ( "-c" ) ;
3025
+ assert ! ( has_error) ;
3026
+
3027
+ let ( _, has_error) = parse_options ( "-c foo=bar -c -c" ) ;
3028
+ assert ! ( has_error) ;
3029
+
3030
+ let ( _, has_error) = parse_options ( " " ) ;
3031
+ assert ! ( !has_error) ;
3032
+
3033
+ let ( config, has_error) = parse_options ( " -c neon.endpoint_type" ) ;
3034
+ assert ! ( has_error) ;
3035
+ }
2982
3036
}
0 commit comments