blob: 968599f80b8e1477c92960537be3d3d35e795711 [file]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//! Session pool walkthrough: share a [`SessionPool`] across threads, each
//! acquiring a session to insert and query concurrently; then the same idea
//! with a [`TableSessionPool`].
//!
//! Run against a local IoTDB (e.g. `docker compose up -d`):
//!
//! ```sh
//! cargo run --example session_pool
//! ```
use std::sync::Arc;
use std::thread;
use iotdb_client::{
Result, SessionPool, SessionPoolConfig, TSDataType, TableSessionPool, Tablet, Value,
};
const DB: &str = "root.rust_pool_example";
const THREADS: usize = 4;
fn main() -> Result<()> {
env_logger::init();
// --- Tree-model pool ---------------------------------------------------
let config = SessionPoolConfig {
max_size: THREADS,
min_size: 1, // one session opened eagerly
..SessionPoolConfig::default()
}
.with_node_urls(&["127.0.0.1:6667"])?;
let pool = Arc::new(SessionPool::new(config)?);
println!("pool created ({} live)", pool.live_count());
pool.execute_non_query(&format!("CREATE DATABASE {DB}"))?;
// Each thread acquires its own session, inserts a tablet for its device
// and queries the row count back. The RAII guard returns the session to
// the pool on drop.
let handles: Vec<_> = (0..THREADS)
.map(|t| {
let pool = Arc::clone(&pool);
thread::spawn(move || -> Result<usize> {
let device = format!("{DB}.d{t}");
let mut session = pool.acquire()?;
let mut tablet =
Tablet::new(&device, vec!["value".into()], vec![TSDataType::Int64])?;
let base_ts = 1_720_000_000_000i64;
for i in 0..5i64 {
tablet.add_row(base_ts + i, vec![Some(Value::Int64(t as i64 * 100 + i))])?;
}
session.insert_tablet(&tablet)?;
let mut rows = 0usize;
let mut dataset = session.execute_query(&format!("SELECT value FROM {device}"))?;
while dataset.next_row()?.is_some() {
rows += 1;
}
Ok(rows)
})
})
.collect();
for (t, handle) in handles.into_iter().enumerate() {
let rows = handle.join().expect("thread panicked")?;
println!("thread {t}: inserted and read back {rows} rows");
}
pool.execute_non_query(&format!("DELETE DATABASE {DB}"))?;
pool.close();
println!("tree pool closed");
// --- Table-model pool ----------------------------------------------------
let config = SessionPoolConfig::default().with_node_urls(&["127.0.0.1:6667"])?;
let table_pool = TableSessionPool::new(config)?;
table_pool.execute_non_query("CREATE DATABASE IF NOT EXISTS rust_pool_example")?;
table_pool.execute_non_query("USE rust_pool_example")?;
{
let mut session = table_pool.acquire()?;
let mut dataset = session.execute_query("SHOW TABLES")?;
println!("tables in rust_pool_example:");
while let Some(row) = dataset.next_row()? {
println!(" {:?}", row.values);
}
}
table_pool.execute_non_query("DROP DATABASE rust_pool_example")?;
table_pool.close();
println!("table pool closed");
Ok(())
}