001/** 002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package io.jboot.db.driver; 017 018import com.google.common.collect.MapMaker; 019import org.slf4j.Logger; 020import org.slf4j.LoggerFactory; 021import ru.yandex.clickhouse.ClickHouseConnection; 022import ru.yandex.clickhouse.ClickHouseDriver; 023import ru.yandex.clickhouse.settings.ClickHouseProperties; 024import ru.yandex.clickhouse.util.LogProxy; 025 026import java.sql.DriverManager; 027import java.sql.SQLException; 028import java.util.concurrent.*; 029 030public class OfficialClickHouseDriver extends ClickHouseDriver { 031 032 private static final Logger logger = LoggerFactory.getLogger(ClickHouseDriver.class); 033 private static final ConcurrentMap<OfficialClickHouseConnection, Boolean> connections = new MapMaker().weakKeys().makeMap(); 034 035 static { 036 try { 037 DriverManager.registerDriver(new OfficialClickHouseDriver()); 038 } catch (SQLException e) { 039 throw new RuntimeException(e); 040 } 041 } 042 043 public OfficialClickHouseDriver() { 044 // 10 seconds 045 scheduleConnectionsCleaning(10, TimeUnit.SECONDS); 046 } 047 048 049 @Override 050 public ClickHouseConnection connect(String url, ClickHouseProperties properties) throws SQLException { 051 if (!acceptsURL(url)) { 052 return null; 053 } 054 OfficialClickHouseConnection connection = new OfficialClickHouseConnection(url, properties); 055 registerConnection(connection); 056 return LogProxy.wrap(ClickHouseConnection.class, connection); 057 } 058 059 private void registerConnection(OfficialClickHouseConnection connection) { 060 connections.put(connection, Boolean.TRUE); 061 } 062 063 064 /** 065 * Schedules connections cleaning at a rate. Turned off by default. 066 * See https://hc.apache.org/httpcomponents-client-4.5.x/tutorial/html/connmgmt.html#d5e418 067 * 068 * @param rate period when checking would be performed 069 * @param timeUnit time unit of rate 070 */ 071 @Override 072 public void scheduleConnectionsCleaning(int rate, TimeUnit timeUnit) { 073 ScheduledConnectionCleaner.INSTANCE.scheduleAtFixedRate(() -> { 074 try { 075 for (OfficialClickHouseConnection connection : connections.keySet()) { 076 connection.cleanConnections(); 077 } 078 } catch (Exception e) { 079 logger.error("error evicting connections: " + e); 080 } 081 }, 0, rate, timeUnit); 082 } 083 084 085 static class ScheduledConnectionCleaner { 086 static final ScheduledExecutorService INSTANCE = Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory()); 087 088 static class DaemonThreadFactory implements ThreadFactory { 089 @Override 090 public Thread newThread(Runnable r) { 091 Thread thread = Executors.defaultThreadFactory().newThread(r); 092 thread.setDaemon(true); 093 return thread; 094 } 095 } 096 } 097 098 099}