16dbb5987Sopenharmony_ci// Copyright (c) 2023 Huawei Device Co., Ltd.
26dbb5987Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
36dbb5987Sopenharmony_ci// you may not use this file except in compliance with the License.
46dbb5987Sopenharmony_ci// You may obtain a copy of the License at
56dbb5987Sopenharmony_ci//
66dbb5987Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
76dbb5987Sopenharmony_ci//
86dbb5987Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
96dbb5987Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
106dbb5987Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
116dbb5987Sopenharmony_ci// See the License for the specific language governing permissions and
126dbb5987Sopenharmony_ci// limitations under the License.
136dbb5987Sopenharmony_ci
146dbb5987Sopenharmony_ci//! Connection pool implementation.
156dbb5987Sopenharmony_ci
166dbb5987Sopenharmony_ciuse std::collections::hash_map::Entry;
176dbb5987Sopenharmony_ciuse std::collections::HashMap;
186dbb5987Sopenharmony_ciuse std::hash::Hash;
196dbb5987Sopenharmony_ciuse std::sync::{Arc, Mutex};
206dbb5987Sopenharmony_ci
216dbb5987Sopenharmony_ciuse ylong_http::request::uri::{Authority, Scheme};
226dbb5987Sopenharmony_ci
236dbb5987Sopenharmony_cipub(crate) struct Pool<K, V> {
246dbb5987Sopenharmony_ci    pool: Arc<Mutex<HashMap<K, V>>>,
256dbb5987Sopenharmony_ci}
266dbb5987Sopenharmony_ci
276dbb5987Sopenharmony_ciimpl<K, V> Pool<K, V> {
286dbb5987Sopenharmony_ci    pub(crate) fn new() -> Self {
296dbb5987Sopenharmony_ci        Self {
306dbb5987Sopenharmony_ci            pool: Arc::new(Mutex::new(HashMap::new())),
316dbb5987Sopenharmony_ci        }
326dbb5987Sopenharmony_ci    }
336dbb5987Sopenharmony_ci}
346dbb5987Sopenharmony_ci
356dbb5987Sopenharmony_ciimpl<K: Eq + Hash, V: Clone> Pool<K, V> {
366dbb5987Sopenharmony_ci    pub(crate) fn get<F>(&self, key: K, create_fn: F) -> V
376dbb5987Sopenharmony_ci    where
386dbb5987Sopenharmony_ci        F: FnOnce() -> V,
396dbb5987Sopenharmony_ci    {
406dbb5987Sopenharmony_ci        let mut inner = self.pool.lock().unwrap();
416dbb5987Sopenharmony_ci        match (*inner).entry(key) {
426dbb5987Sopenharmony_ci            Entry::Occupied(conns) => conns.get().clone(),
436dbb5987Sopenharmony_ci            Entry::Vacant(e) => e.insert(create_fn()).clone(),
446dbb5987Sopenharmony_ci        }
456dbb5987Sopenharmony_ci    }
466dbb5987Sopenharmony_ci}
476dbb5987Sopenharmony_ci
486dbb5987Sopenharmony_ci#[derive(Debug, PartialEq, Eq, Hash, Clone)]
496dbb5987Sopenharmony_cipub(crate) struct PoolKey(Scheme, Authority);
506dbb5987Sopenharmony_ci
516dbb5987Sopenharmony_ciimpl PoolKey {
526dbb5987Sopenharmony_ci    pub(crate) fn new(scheme: Scheme, authority: Authority) -> Self {
536dbb5987Sopenharmony_ci        Self(scheme, authority)
546dbb5987Sopenharmony_ci    }
556dbb5987Sopenharmony_ci}
566dbb5987Sopenharmony_ci
576dbb5987Sopenharmony_ci#[cfg(test)]
586dbb5987Sopenharmony_cimod ut_pool {
596dbb5987Sopenharmony_ci    use ylong_http::request::uri::Uri;
606dbb5987Sopenharmony_ci
616dbb5987Sopenharmony_ci    use crate::pool::{Pool, PoolKey};
626dbb5987Sopenharmony_ci
636dbb5987Sopenharmony_ci    /// UT test cases for `Pool::get`.
646dbb5987Sopenharmony_ci    ///
656dbb5987Sopenharmony_ci    /// # Brief
666dbb5987Sopenharmony_ci    /// 1. Creates a `pool` by calling `Pool::new()`.
676dbb5987Sopenharmony_ci    /// 2. Uses `pool::get` to get connection.
686dbb5987Sopenharmony_ci    /// 3. Checks if the results are correct.
696dbb5987Sopenharmony_ci    #[test]
706dbb5987Sopenharmony_ci    fn ut_pool_get() {
716dbb5987Sopenharmony_ci        let uri = Uri::from_bytes(b"http://example1.com:80/foo?a=1").unwrap();
726dbb5987Sopenharmony_ci        let key = PoolKey::new(
736dbb5987Sopenharmony_ci            uri.scheme().unwrap().clone(),
746dbb5987Sopenharmony_ci            uri.authority().unwrap().clone(),
756dbb5987Sopenharmony_ci        );
766dbb5987Sopenharmony_ci        let data = String::from("Data info");
776dbb5987Sopenharmony_ci        let consume_and_return_data = move || data;
786dbb5987Sopenharmony_ci        let pool = Pool::new();
796dbb5987Sopenharmony_ci        let res = pool.get(key, consume_and_return_data);
806dbb5987Sopenharmony_ci        assert_eq!(res, "Data info".to_string());
816dbb5987Sopenharmony_ci    }
826dbb5987Sopenharmony_ci}
83