// ============================================================================ // // Copyright (C) 2006-2016 Talend Inc. - www.talend.com // // This source code is available under agreement available at // %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt // // You should have received a copy of the agreement // along with this program; if not, write to Talend SA // 9 rue Pages 92150 Suresnes, France // // ============================================================================ package org.talend.dataquality.indicators.mapdb; import java.io.File; import java.util.HashMap; import java.util.Map; import java.util.Timer; import org.mapdb.DB; import org.mapdb.StoreDirect; import org.talend.cwm.helper.ResourceHelper; import org.talend.dataquality.analysis.Analysis; import org.talend.resource.ResourceManager; /** * created by talend on Aug 19, 2014 Detailled comment * */ public class MapDBManager { private Map<File, DB> dbMap = new HashMap<File, DB>(); // store the times the mapdb has been used. private Map<DB, Integer> dbRefCountMap = new HashMap<DB, Integer>(); // store all of task which used to close db private Map<DB, CloseDBTimeTask> closeTaskMap = new HashMap<DB, CloseDBTimeTask>(); private Timer timer = new Timer(); private static MapDBManager instance = null; public static MapDBManager getInstance() { if (instance == null) { instance = new MapDBManager(); } return instance; } public DB getDB(File filePath) { return dbMap.get(filePath); } public DB putDB(File filePath, DB db) { return dbMap.put(filePath, db); } public void removeDB(File filePath) { dbMap.remove(filePath); } /** * * If MapDB file is not exist or has been closed then this method will not do anything else will create new task to * close it. * * @param analysis */ public void closeDB(File filePath) { DB db = dbMap.get(filePath); closeDB(db, filePath); } /** * * If MapDB file is not exist or has been closed then this method will not do anything else will create new task to * close it. * * @param analysis */ public void closeDB(Analysis analysis) { File filePath = getMapDBFile(analysis); closeDB(filePath); } /** * * Delete mapDB file * * @param analysis */ public void deleteDB(Analysis analysis) { File mapDBFile = getMapDBFile(analysis); DB db = this.getDB(mapDBFile); // if db is in used close it first if (db != null) { this.removeDB(mapDBFile); dbRefCountMap.remove(db); db.close(); while (!db.isClosed()) { try { Thread.currentThread().wait(1000); } catch (InterruptedException e) { } } } // delete data file and index file if (mapDBFile.exists()) { mapDBFile.delete(); new File(mapDBFile.getAbsolutePath() + StoreDirect.DATA_FILE_EXT).delete(); } } /** * Get MapDB file by analysis * * @param analysis * @return */ private File getMapDBFile(Analysis analysis) { String analysisUUID = null; if (analysis != null) { analysisUUID = ResourceHelper.getUUID(analysis); } if (analysisUUID == null) { return null; } return MapDBUtils.createPath(ResourceManager.getMapDBFilePath(), analysisUUID); } /** * * If MapDB file is not exist or has been closed then this method will not do anything else will create new task to * close it. * * @param analysis */ public void closeDB(String parentPathStr, String fileName) { File filePath = MapDBUtils.createPath(parentPathStr, fileName); closeDB(filePath); } private void closeDB(DB db, File filePath) { if (db == null || db.isClosed()) { return; } scheduleCloseTask(db, filePath); } /** * Create a new close db task and schedule it. If same task has been schedule or the db is used by other drill down * editor then will do nothing * * @param db */ protected void scheduleCloseTask(DB db, File filePath) { if (hasBeenSchedule(db)) { // current db has been schedule return; } if (isUsedByDrillDown(db)) { // current db is in use by other drilldownEditor return; } CloseDBTimeTask closeDBTimeTask = new CloseDBTimeTask(db, filePath); timer.schedule(closeDBTimeTask, MapDBContent.getDelayTime());// close db after 5 minute 5*60*1000 closeTaskMap.put(db, closeDBTimeTask); } /** * Whether the db has been contain by schduel * * @param db * @return */ private boolean hasBeenSchedule(DB db) { return closeTaskMap.containsKey(db); } /** * Whether the db is used by other drill down editor * * @return */ private boolean isUsedByDrillDown(DB db) { return dbRefCountMap.containsKey(db); } /** * * Record one db have been used how many times * * @param filePath */ public void addDBRef(File filePath) { DB db = dbMap.get(filePath); if (db == null) { return; } cancelCloseTask(db); Integer refConut = dbRefCountMap.get(db); if (refConut == null) { refConut = 0; } refConut++; dbRefCountMap.put(db, refConut); } /** * Cancel the close db task if special db has a task exist * * @param db */ protected void cancelCloseTask(DB db) { CloseDBTimeTask closeDBTimeTask = closeTaskMap.get(db); if (closeDBTimeTask != null) { closeDBTimeTask.cancel(); timer.purge(); closeTaskMap.remove(db); } } /** * * Reduce the times which one db be used. When the count of times is 0 we will close this db. * * @param filePath */ public void removeDBRef(File filePath) { DB db = dbMap.get(filePath); if (db == null) { return; } Integer refConut = dbRefCountMap.get(db); if (refConut == null) { return; } refConut--; if (refConut > 0) { dbRefCountMap.put(db, refConut); } else { dbRefCountMap.remove(db); closeDB(db, filePath); } } }