| /** |
| * |
| * Copyright (c) 2011, 2018 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany) |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation |
| * |
| */ |
| package org.eclipse.osbp.xtext.signal.common; |
| |
| import java.io.IOException; |
| import java.nio.file.FileAlreadyExistsException; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.sql.Date; |
| import java.text.SimpleDateFormat; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Locale; |
| import java.util.concurrent.ExecutorService; |
| import java.util.concurrent.LinkedBlockingQueue; |
| import java.util.concurrent.ThreadPoolExecutor; |
| import java.util.concurrent.TimeUnit; |
| import java.util.concurrent.atomic.AtomicBoolean; |
| |
| import org.eclipse.osbp.xtext.signal.SignalScheduler; |
| import org.eclipse.osbp.xtext.signal.WatcherWithFileMask; |
| import org.eclipse.osbp.xtext.signal.WatcherWithFileName; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import com.google.common.util.concurrent.ThreadFactoryBuilder; |
| |
| /** |
| * This class contains all common data to be used either from |
| * {@link WatcherWithFileMask} or {@link WatcherWithFileName} or |
| * {@link SignalScheduler}. |
| */ |
| public abstract class SignalCommonData { |
| /** the log */ |
| public static Logger log = LoggerFactory.getLogger("signal"); |
| /** the number of maximum task to be run simultaneously */ |
| private static ArrayList<Integer> maxthreadcountinputs = new ArrayList<>(); |
| /** the maximum thread count for parallel task execution */ |
| private static int maxthreadcount = -1; |
| /** the number of thread count for parallel task execution */ |
| public static int signalcount = 0; |
| /** needed for proper synchronization */ |
| private static AtomicBoolean threadCountReady = new AtomicBoolean(false); |
| /** date formatter for renaming files */ |
| private SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddhhmmssa", Locale.US); |
| |
| /** |
| * Returns the {@link #maxthreadcount} value. |
| * @return {@link Integer} the maximum parallel thread count |
| */ |
| public int getMaxParallelThreadsCount() { |
| return maxthreadcount; |
| } |
| |
| /** |
| * Reads and initializes the highest number of parallel thread processing |
| * allowed during the execution of watcher or a scheduler task. |
| */ |
| public void initMaxThreadCount() { |
| synchronized (threadCountReady) { |
| if(!threadCountReady.get()){ |
| while (true) { |
| if (maxthreadcountinputs.size() == signalcount) { |
| Collections.sort(maxthreadcountinputs); |
| maxthreadcount = maxthreadcountinputs.get(maxthreadcountinputs.size() - 1); |
| threadCountReady.set(true); |
| break; |
| } |
| try { |
| Thread.sleep(SignalConstants.WAITINGTIME_FOR_WATCHER_INIT); |
| } catch (InterruptedException e) { |
| // NOSONAR |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Sets a maximum value for the count of parallel threads to be executed. |
| * |
| * @param maxthrcount |
| * the max count |
| */ |
| public synchronized void setMaxParallelThreadsCount(String maxthrcount) { |
| try { |
| int value = Integer.valueOf(maxthrcount); |
| if (value >= 0 && value <= SignalConstants.MAXPARALLELTHREADCOUNT) { |
| maxthreadcountinputs.add(value); |
| } else if (value > SignalConstants.MAXPARALLELTHREADCOUNT) { |
| maxthreadcountinputs.add(SignalConstants.MAXPARALLELTHREADCOUNT); |
| } else { |
| maxthreadcountinputs.add(SignalConstants.DEFAULT_PARALLEL_THREADCOUNT); |
| } |
| } catch (NumberFormatException e) { |
| // log.error(String.format("getMaxParallelThreadsCount - the given |
| // maximum parallel threads count value [%s] is not valid.", maxthrcount)); |
| maxthreadcountinputs.add(SignalConstants.DEFAULT_PARALLEL_THREADCOUNT); |
| } |
| } |
| |
| /** |
| * Make sure that the given file is deleted. |
| * |
| * @param file |
| * the file to be deleted |
| * @param logidinfo |
| * log information from the caller |
| */ |
| public void deleteFile(final Path file, String logidinfo) { |
| try { |
| if (Files.deleteIfExists(file)) { |
| if (log.isDebugEnabled()) { |
| log.info(logidinfo + " [" + file + "] successfuly removed."); |
| } |
| } else { |
| if (log.isDebugEnabled()) { |
| log.info(logidinfo + " [" + file + "] doesn't exist and could not be removed."); |
| } |
| } |
| } catch (IOException e) { |
| log.error(logidinfo + " [" + file + "] could not be deleted.\n" + e.getMessage()); |
| } |
| } |
| |
| /** |
| * Renames the given file with the given new name. If a file with the given |
| * new name already exists then a number offset will be added to it. |
| * @param file the file to rename |
| * @param logidinfo information on the caller of this function |
| */ |
| public void renameFile(final Path file, String logidinfo) { |
| try { |
| if(Files.exists(file)){ |
| String filename = file.getFileName().toString(); |
| String newname = ("FAILEDIMPORT"+ formatter.format(new Date(System.currentTimeMillis())) + filename + ".LOCKED"); |
| int renameTry = 0; |
| boolean done = false; |
| String tempname = newname; |
| String extension = newname.substring(newname.length()-4); |
| do{ |
| try{ |
| Files.move(file, file.resolveSibling(tempname)); |
| done = true; |
| }catch (FileAlreadyExistsException ae) { |
| renameTry ++; |
| tempname = newname.replace(extension, renameTry+extension); |
| } |
| }while(!done); |
| log.info(String.format("%s file [%s] renamed to %s.", logidinfo, filename, tempname)); |
| |
| } |
| else{ |
| log.info(String.format("%s file [%s] doesn't exist and could not be renamed.", logidinfo, file)); |
| } |
| } catch (IOException e) { |
| log.error(String.format("%s file [%s] could not be renamed.\n%s", logidinfo, file, e.getMessage())); |
| } |
| } |
| |
| /** |
| * Creates an executor service with the given maximum amount of thread that |
| * can run in parallel, with no idle thread allowed. |
| * |
| * @param poolname |
| * - the name of the thread pool |
| * @param maxparallelthreadcount |
| * - the maximum number of threads to allow in thepool |
| * @param keepAliveTime |
| * - when the number of threads is greater thanthe core, this is |
| * the maximum time that excess idle threadswill wait for new |
| * tasks before terminating |
| * @return {@link ExecutorService} the executor service |
| */ |
| @SuppressWarnings({ "unchecked", "rawtypes" }) |
| public ExecutorService createCustomExecutorService(String poolname, int maxparallelthreadcount, long keepAliveTime) { |
| ThreadPoolExecutor pool = new ThreadPoolExecutor(maxparallelthreadcount, maxparallelthreadcount, keepAliveTime, |
| TimeUnit.MILLISECONDS, new LinkedBlockingQueue(),new ThreadFactoryBuilder().setNameFormat(poolname + "Pool-Thread-%d").build()); |
| return pool; |
| } |
| |
| /** |
| * Gives the {@link #formatter}. |
| * @return {@link SimpleDateFormat} |
| */ |
| public SimpleDateFormat getFormatter(){ |
| return formatter; |
| } |
| } |