mirror of
https://github.com/postgresml/pgcat.git
synced 2026-03-26 10:26:30 +00:00
once_cell is way faster
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -323,6 +323,8 @@ dependencies = [
|
|||||||
"bytes",
|
"bytes",
|
||||||
"chrono",
|
"chrono",
|
||||||
"md-5",
|
"md-5",
|
||||||
|
"num_cpus",
|
||||||
|
"once_cell",
|
||||||
"rand",
|
"rand",
|
||||||
"regex",
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
|
|||||||
@@ -18,3 +18,5 @@ toml = "0.5"
|
|||||||
serde = "1"
|
serde = "1"
|
||||||
serde_derive = "1"
|
serde_derive = "1"
|
||||||
regex = "1"
|
regex = "1"
|
||||||
|
num_cpus = "1"
|
||||||
|
once_cell = "1"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
/// We are pretending to the server in this scenario,
|
/// We are pretending to the server in this scenario,
|
||||||
/// and this module implements that.
|
/// and this module implements that.
|
||||||
use bytes::{Buf, BufMut, BytesMut};
|
use bytes::{Buf, BufMut, BytesMut};
|
||||||
|
use once_cell::sync::OnceCell;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use tokio::io::{AsyncReadExt, BufReader};
|
use tokio::io::{AsyncReadExt, BufReader};
|
||||||
use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
|
use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
|
||||||
@@ -14,8 +15,11 @@ use crate::pool::{ClientServerMap, ConnectionPool};
|
|||||||
use crate::server::Server;
|
use crate::server::Server;
|
||||||
use crate::sharding::Sharder;
|
use crate::sharding::Sharder;
|
||||||
|
|
||||||
const SHARDING_REGEX: &str = r"SET SHARDING KEY TO '[0-9]+';";
|
pub const SHARDING_REGEX: &str = r"SET SHARDING KEY TO '[0-9]+';";
|
||||||
const ROLE_REGEX: &str = r"SET SERVER ROLE TO '(PRIMARY|REPLICA)';";
|
pub const ROLE_REGEX: &str = r"SET SERVER ROLE TO '(PRIMARY|REPLICA)';";
|
||||||
|
|
||||||
|
pub static SHARDING_REGEX_RE: OnceCell<Regex> = OnceCell::new();
|
||||||
|
pub static ROLE_REGEX_RE: OnceCell<Regex> = OnceCell::new();
|
||||||
|
|
||||||
/// The client state. One of these is created per client.
|
/// The client state. One of these is created per client.
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
@@ -44,12 +48,6 @@ pub struct Client {
|
|||||||
// Clients are mapped to servers while they use them. This allows a client
|
// Clients are mapped to servers while they use them. This allows a client
|
||||||
// to connect and cancel a query.
|
// to connect and cancel a query.
|
||||||
client_server_map: ClientServerMap,
|
client_server_map: ClientServerMap,
|
||||||
|
|
||||||
// sharding regex
|
|
||||||
sharding_regex: Regex,
|
|
||||||
|
|
||||||
// role detection regex
|
|
||||||
role_regex: Regex,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
@@ -61,9 +59,6 @@ impl Client {
|
|||||||
client_server_map: ClientServerMap,
|
client_server_map: ClientServerMap,
|
||||||
transaction_mode: bool,
|
transaction_mode: bool,
|
||||||
) -> Result<Client, Error> {
|
) -> Result<Client, Error> {
|
||||||
let sharding_regex = Regex::new(SHARDING_REGEX).unwrap();
|
|
||||||
let role_regex = Regex::new(ROLE_REGEX).unwrap();
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// Could be StartupMessage or SSLRequest
|
// Could be StartupMessage or SSLRequest
|
||||||
// which makes this variable length.
|
// which makes this variable length.
|
||||||
@@ -119,8 +114,6 @@ impl Client {
|
|||||||
process_id: process_id,
|
process_id: process_id,
|
||||||
secret_key: secret_key,
|
secret_key: secret_key,
|
||||||
client_server_map: client_server_map,
|
client_server_map: client_server_map,
|
||||||
sharding_regex: sharding_regex,
|
|
||||||
role_regex: role_regex,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,8 +133,6 @@ impl Client {
|
|||||||
process_id: process_id,
|
process_id: process_id,
|
||||||
secret_key: secret_key,
|
secret_key: secret_key,
|
||||||
client_server_map: client_server_map,
|
client_server_map: client_server_map,
|
||||||
sharding_regex: sharding_regex,
|
|
||||||
role_regex: role_regex,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,8 +405,12 @@ impl Client {
|
|||||||
|
|
||||||
let len = buf.get_i32();
|
let len = buf.get_i32();
|
||||||
let query = String::from_utf8_lossy(&buf[..len as usize - 4 - 1]).to_ascii_uppercase(); // Don't read the ternminating null
|
let query = String::from_utf8_lossy(&buf[..len as usize - 4 - 1]).to_ascii_uppercase(); // Don't read the ternminating null
|
||||||
|
let rgx = match SHARDING_REGEX_RE.get() {
|
||||||
|
Some(r) => r,
|
||||||
|
None => return None,
|
||||||
|
};
|
||||||
|
|
||||||
if self.sharding_regex.is_match(&query) {
|
if rgx.is_match(&query) {
|
||||||
let shard = query.split("'").collect::<Vec<&str>>()[1];
|
let shard = query.split("'").collect::<Vec<&str>>()[1];
|
||||||
match shard.parse::<i64>() {
|
match shard.parse::<i64>() {
|
||||||
Ok(shard) => {
|
Ok(shard) => {
|
||||||
@@ -441,10 +436,14 @@ impl Client {
|
|||||||
|
|
||||||
let len = buf.get_i32();
|
let len = buf.get_i32();
|
||||||
let query = String::from_utf8_lossy(&buf[..len as usize - 4 - 1]).to_ascii_uppercase();
|
let query = String::from_utf8_lossy(&buf[..len as usize - 4 - 1]).to_ascii_uppercase();
|
||||||
|
let rgx = match ROLE_REGEX_RE.get() {
|
||||||
|
Some(r) => r,
|
||||||
|
None => return None,
|
||||||
|
};
|
||||||
|
|
||||||
// Copy / paste from above. If we get one more of these use cases,
|
// Copy / paste from above. If we get one more of these use cases,
|
||||||
// it'll be time to abstract :).
|
// it'll be time to abstract :).
|
||||||
if self.role_regex.is_match(&query) {
|
if rgx.is_match(&query) {
|
||||||
let role = query.split("'").collect::<Vec<&str>>()[1];
|
let role = query.split("'").collect::<Vec<&str>>()[1];
|
||||||
match role {
|
match role {
|
||||||
"PRIMARY" => Some(Role::Primary),
|
"PRIMARY" => Some(Role::Primary),
|
||||||
|
|||||||
10
src/main.rs
10
src/main.rs
@@ -17,11 +17,14 @@ extern crate async_trait;
|
|||||||
extern crate bb8;
|
extern crate bb8;
|
||||||
extern crate bytes;
|
extern crate bytes;
|
||||||
extern crate md5;
|
extern crate md5;
|
||||||
|
extern crate num_cpus;
|
||||||
|
extern crate once_cell;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
extern crate tokio;
|
extern crate tokio;
|
||||||
extern crate toml;
|
extern crate toml;
|
||||||
|
|
||||||
|
use regex::Regex;
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@@ -44,6 +47,13 @@ use pool::{ClientServerMap, ConnectionPool};
|
|||||||
async fn main() {
|
async fn main() {
|
||||||
println!("> Welcome to PgCat! Meow.");
|
println!("> Welcome to PgCat! Meow.");
|
||||||
|
|
||||||
|
client::SHARDING_REGEX_RE
|
||||||
|
.set(Regex::new(client::SHARDING_REGEX).unwrap())
|
||||||
|
.unwrap();
|
||||||
|
client::ROLE_REGEX_RE
|
||||||
|
.set(Regex::new(client::ROLE_REGEX).unwrap())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let config = match config::parse("pgcat.toml").await {
|
let config = match config::parse("pgcat.toml").await {
|
||||||
Ok(config) => config,
|
Ok(config) => config,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user