/* * Copyright 2015 the original author or authors. * @https://github.com/scouter-project/scouter * * Licensed 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. */ package scouter.server.db.io.zip; import java.io.File; import java.io.IOException; import java.util.Enumeration; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import scouter.server.ConfObserver; import scouter.server.Configure; import scouter.server.Logger; import scouter.util.CacheTable; import scouter.util.CompressUtil; import scouter.util.FileUtil; import scouter.util.IShutdown; import scouter.util.LinkedMap; import scouter.util.StopWatch; public class IOChannel implements IShutdown { private static IOChannel instance = null; public final static synchronized IOChannel getInstance() { if (instance == null) { instance = new IOChannel(); } return instance; } public IOChannel() { ConfObserver.put(IOChannel.class.getName(), new Runnable() { public void run() { readCache.setMaxRow(conf._compress_read_cache_block_count); } }); } private Configure conf = Configure.getInstance(); private LinkedMap<String, CountBoard> headers = new LinkedMap<String, CountBoard>(); public Block getLastWriteBlock(String date) throws IOException { CountBoard uc = headers.get(date); if (uc == null) { check(); uc = new CountBoard(date); headers.put(date, uc); } long n = uc.getCount(); int start = (int) (n % GZipCtr.BLOCK_MAX_SIZE); Block bk = new Block(date, new byte[128], start, start, GZipCtr.BLOCK_MAX_SIZE); bk.blockNum = (int) (n / GZipCtr.BLOCK_MAX_SIZE); return bk; } private void check() { while (headers.size() >= conf._compress_dailycount_header_cache_size - 1) { try { headers.removeFirst().close(); } catch (Exception e) { } } } public CountBoard getCountBoard(String date) { CountBoard uc = headers.get(date); if (uc == null) { check(); try { uc = new CountBoard(date); } catch (IOException e) { e.printStackTrace(); } headers.put(date, uc); } return uc; } public synchronized void store(Block bk) { if (bk.dirty == false) return; bk.dirty = false; int mgtime = 0; StopWatch w = new StopWatch(); if (bk.START > 0) { StopWatch w2 = new StopWatch(); w2.start(); Block old = getReadBlock(bk.date, bk.blockNum); if (old != null) { bk = bk.merge(old); readCache.put(new BKey(bk.date, bk.blockNum), bk, conf._compress_read_cache_expired_ms); } mgtime = (int) w2.getTime(); } getCountBoard(bk.date).set(bk.getOffset()); try { byte[] org = bk.getBlockBytes(); String date = bk.date; int blockNum = bk.blockNum; saveBlockBytes(getFile(date, blockNum), org); // byte[] out = CompressUtil.doZip(org); // FileUtil.save(getFile(date, blockNum), out); } catch (Exception e) { e.printStackTrace(); } long tm = w.getTime(); if (tm > 1000) { Logger.println("S130", "Store " + tm + " ms " + (mgtime > 0 ? " old-load=" + mgtime + "ms" : "")); } } private static ExecutorService exec = Executors .newFixedThreadPool(Configure.getInstance()._compress_write_thread); static int old_block_thread = Configure.getInstance()._compress_write_thread; static { ConfObserver.put("_compress_write_thread", new Runnable() { public void run() { if (Configure.getInstance()._compress_write_thread != old_block_thread) { ExecutorService oldExec = exec; exec = Executors.newFixedThreadPool(Configure.getInstance()._compress_write_thread); old_block_thread = Configure.getInstance()._compress_write_thread; oldExec.shutdown(); } } }); } protected static void saveBlockBytes(final File file, final byte[] block) { exec.execute(new Runnable() { public void run() { try { byte[] out = CompressUtil.doZip(block); FileUtil.save(file, out); } catch (Exception e) { Logger.println("S209", e.getMessage()); } } }); } private File getFile(String date, int blockNum) { String filename = (GZipCtr.createPath(date) + "/xlog." + blockNum); return new File(filename); } private CacheTable<BKey, Block> readCache = new CacheTable<BKey, Block>().setMaxRow(conf._compress_read_cache_block_count); public Block getReadBlock(String date, int blockNum) { Block b = readCache.get(new BKey(date, blockNum)); if (b != null) return b; File f = getFile(date, blockNum); if (f.exists() == false) return null; try { byte[] gz = FileUtil.readAll(f); gz = CompressUtil.unZip(gz); Block bk = new Block(date, gz, 0, gz.length, GZipCtr.BLOCK_MAX_SIZE); bk.blockNum = blockNum; readCache.put(new BKey(date, blockNum), bk, conf._compress_read_cache_expired_ms); return bk; } catch (Throwable e) { e.printStackTrace(); } return null; } public void shutdown() { } public void close(String date) { try { Enumeration<BKey> en = readCache.keys(); while (en.hasMoreElements()) { BKey k = en.nextElement(); if (date.equals(k.date)) { readCache.remove(k); } } } catch (Throwable t) { t.printStackTrace(); } } }