All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jaeksoft.searchlib.process.ThreadAbstract Maven / Gradle / Ivy

/**   
 * License Agreement for OpenSearchServer
 *
 * Copyright (C) 2010-2014 Emmanuel Keller / Jaeksoft
 * 
 * http://www.open-search-server.com
 * 
 * This file is part of OpenSearchServer.
 *
 * OpenSearchServer is free software: you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 * OpenSearchServer is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with OpenSearchServer. 
 *  If not, see .
 **/

package com.jaeksoft.searchlib.process;

import java.lang.Thread.State;
import java.util.Date;

import com.jaeksoft.searchlib.Logging;
import com.jaeksoft.searchlib.config.Config;
import com.jaeksoft.searchlib.scheduler.TaskLog;
import com.jaeksoft.searchlib.streamlimiter.LimitException;
import com.jaeksoft.searchlib.util.InfoCallback;
import com.jaeksoft.searchlib.util.ReadWriteLock;
import com.jaeksoft.searchlib.util.ThreadUtils;
import com.jaeksoft.searchlib.web.StartStopListener.ShutdownWaitInterface;

public abstract class ThreadAbstract> implements
		Runnable, InfoCallback {

	final private ReadWriteLock rwl = new ReadWriteLock();

	private final Config config;

	private final ThreadMasterAbstract threadMaster;

	private final ThreadItem threadItem;

	private volatile String info;

	private volatile boolean abort;

	private volatile Thread thread;

	private volatile long startTime;

	private volatile long idleTime;

	private volatile long endTime;

	private volatile Exception exception;

	protected final InfoCallback infoCallback;

	protected final TaskLog taskLog;

	protected ThreadAbstract(Config config,
			ThreadMasterAbstract threadMaster,
			ThreadItem threadItem, InfoCallback infoCallback) {
		this.config = config;
		this.threadItem = threadItem;
		this.threadMaster = threadMaster;
		this.infoCallback = infoCallback;
		taskLog = infoCallback != null && infoCallback instanceof TaskLog ? (TaskLog) infoCallback
				: null;
		exception = null;
		abort = false;
		thread = null;
		info = null;
		startTime = 0;
		idleTime = 0;
		endTime = 0;
	}

	public Config getConfig() {
		return config;
	}

	@Override
	public String getInfo() {
		rwl.r.lock();
		try {
			return info;
		} finally {
			rwl.r.unlock();
		}
	}

	@Override
	public void setInfo(String info) {
		rwl.w.lock();
		try {
			this.info = info;
		} finally {
			rwl.w.unlock();
		}
	}

	public boolean isAborted() {
		rwl.w.lock();
		try {
			if (!abort && taskLog != null)
				if (taskLog.isAbortRequested())
					abort = true;
			return abort;
		} finally {
			rwl.w.unlock();
		}
	}

	public void abort() {
		rwl.w.lock();
		try {
			abort = true;
		} finally {
			rwl.w.unlock();
		}
	}

	public Exception getException() {
		rwl.r.lock();
		try {
			return exception;
		} finally {
			rwl.r.unlock();
		}
	}

	protected void setException(Exception e) {
		rwl.w.lock();
		try {
			this.exception = e;
		} finally {
			rwl.w.unlock();
		}
	}

	public boolean isAborting() {
		return isRunning() && isAborted();

	}

	private class StartInterface extends ShutdownWaitInterface {

		@Override
		public boolean done() {
			return getStartTime() != 0;
		}

	}

	private class EndInterface extends ShutdownWaitInterface {

		@Override
		public boolean done() {
			return !isRunning();
		}

	}

	public boolean waitForStart(long secTimeOut) {
		return ThreadUtils.waitUntil(secTimeOut, new StartInterface());
	}

	public boolean waitForEnd(long secTimeOut) {
		return ThreadUtils.waitUntil(secTimeOut, new EndInterface());
	}

	protected void sleepMs(long ms) {
		try {
			while (ms > 0 && !isAborted()) {
				Thread.sleep(1000);
				ms -= 1000;
			}
		} catch (InterruptedException e) {
			Logging.warn(e.getMessage(), e);
		}
	}

	protected void sleepSec(int sec) {
		if (sec == 0)
			return;
		sleepMs(sec * 1000);
	}

	protected void idle() {
		rwl.w.lock();
		try {
			idleTime = System.currentTimeMillis();
		} finally {
			rwl.w.unlock();
		}
	}

	protected boolean isIdleTimeExhausted(long seconds) {
		rwl.r.lock();
		try {
			if (seconds == 0)
				return false;
			long timeElapsed = (System.currentTimeMillis() - idleTime) / 1000;
			return timeElapsed > seconds;
		} finally {
			rwl.r.unlock();
		}

	}

	public String getCurrentMethod() {
		rwl.r.lock();
		try {
			if (thread == null)
				return "No thread";
			StackTraceElement[] ste = thread.getStackTrace();
			if (ste == null)
				return "No stack";
			if (ste.length == 0)
				return "Empty stack";
			StackTraceElement element = ste[0];
			for (StackTraceElement e : ste) {
				if (e.getClassName().contains("jaeksoft")) {
					element = e;
					break;
				}
			}
			return element.getClassName() + '.' + element.getMethodName()
					+ " (" + element.getLineNumber() + ")";
		} finally {
			rwl.r.unlock();
		}
	}

	protected abstract void runner() throws Exception;

	public abstract void release();

	final private String getThreadName() {
		StringBuilder sb = new StringBuilder();
		if (config != null) {
			sb.append("Index: ");
			sb.append(config.getIndexName());
			sb.append(' ');
		}
		sb.append(getClass().getSimpleName());
		sb.append(' ');
		sb.append(new Date(startTime));
		return sb.toString();
	}

	final private void initStart() {
		rwl.w.lock();
		try {
			exception = null;
			abort = false;
			info = null;
			endTime = 0;
			startTime = System.currentTimeMillis();
			thread = Thread.currentThread();
			thread.setName(getThreadName());
			idleTime = startTime;
		} finally {
			rwl.w.unlock();
		}
	}

	final private void initEnd() {
		rwl.w.lock();
		try {
			thread = null;
			endTime = System.currentTimeMillis();
		} finally {
			rwl.w.unlock();
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	final public void run() {
		initStart();
		try {
			runner();
		} catch (Exception e) {
			setException(e);
			setInfo(e.getMessage());
			if (!(e instanceof LimitException))
				Logging.error(e.getMessage(), e);
		} finally {
			initEnd();
			if (threadMaster != null) {
				threadMaster.remove((T) this);
				synchronized (threadMaster) {
					threadMaster.notify();
				}
			}
		}
		release();
	}

	final public boolean isRunning() {
		rwl.r.lock();
		try {
			if (thread == null)
				return false;
			switch (thread.getState()) {
			case NEW:
				return false;
			case BLOCKED:
				return true;
			case RUNNABLE:
				return true;
			case TERMINATED:
				return false;
			case TIMED_WAITING:
				return true;
			case WAITING:
				return true;
			}
			return false;
		} finally {
			rwl.r.unlock();
		}
	}

	final public State getThreadState() {
		rwl.r.lock();
		try {
			if (thread == null)
				return null;
			return thread.getState();
		} finally {
			rwl.r.unlock();
		}
	}

	final public String getThreadStatus() {
		rwl.r.lock();
		try {
			StringBuilder sb = new StringBuilder();
			sb.append(this.hashCode());
			if (thread == null)
				return sb.toString();
			sb.append('/');
			sb.append(thread.hashCode());
			sb.append(' ');
			sb.append(thread.getState().toString());
			return sb.toString();
		} finally {
			rwl.r.unlock();
		}
	}

	protected ThreadItem getThreadItem() {
		return threadItem;
	}

	final public void execute(int secTimeOut) {
		rwl.w.lock();
		try {
			startTime = 0;
		} finally {
			rwl.w.unlock();
		}
		config.getThreadPool().execute(this);
		waitForStart(secTimeOut);
	}

	protected ThreadMasterAbstract getThreadMaster() {
		return threadMaster;
	}

	/**
	 * @return the startTime
	 */
	public long getStartTime() {
		rwl.r.lock();
		try {
			return startTime;
		} finally {
			rwl.r.unlock();
		}
	}

	public long getDuration() {
		rwl.r.lock();
		try {
			if (startTime == 0)
				return 0;
			if (endTime != 0)
				return endTime - startTime;
			return System.currentTimeMillis() - startTime;
		} finally {
			rwl.r.unlock();
		}
	}

	public long getEndTime() {
		rwl.r.lock();
		try {
			return endTime;
		} finally {
			rwl.r.unlock();
		}
	}

	@Override
	public String toString() {
		return super.toString() + " " + getClass().getSimpleName();
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy