/*
* Copyright (C) 2012 Glencoe Software, Inc. All rights reserved.
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package ome.services.blitz.repo;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.MapMaker;
import omero.grid.ImportProcessPrx;
import omero.model.Fileset;
/**
* Helper class for holding the individual {@link ManagedImportProcessI}
* instances created by {@link ManagedRepositoryI}. Responsible for providing
* lookups as well as keep-alive and reap methods which will be called by
* background threads.
*
* @author Josh Moore, josh at glencoesoftware.com
* @since 4.5
*/
public class ProcessContainer {
private final static Logger log = LoggerFactory.getLogger(ProcessContainer.class);
public interface Process {
ImportProcessPrx getProxy();
Fileset getFileset();
long getGroup();
void ping();
void shutdown();
}
private final static class Data {
private static final MapMaker mapMaker = new MapMaker();
private final Map<Process, Object> processes = mapMaker.makeMap();
void add(Process process) {
processes.put(process, process);
}
void remove(Process process) {
processes.remove(process);
}
void fill(List<Process> toFill) {
for (Process process : processes.keySet()) {
toFill.add(process);
}
}
}
private final LoadingCache<Long, Data> perGroup = CacheBuilder.newBuilder().build(
new CacheLoader<Long, Data>() {
@Override
public Data load(Long group) {
return new Data();
}
});
private Data getOrCreate(Long group) {
try {
return perGroup.get(group);
} catch (ExecutionException e) {
/* cannot occur unless loading thread is interrupted */
return null;
}
}
/**
* Called once the {@link ManagedImportProcessI} service is created.
* @param process The process to handle.
*/
public void addProcess(Process process) {
Data data = getOrCreate(process.getGroup());
data.add(process);
}
/**
* Removes the process.
* @param process The process to remove.
*/
public void removeProcess(Process process) {
final Data data = getOrCreate(process.getGroup());
if (data != null) {
data.remove(process);
}
}
public List<Process> listProcesses(Collection<Long> groups) {
if (groups == null) {
groups = perGroup.asMap().keySet();
}
final List<Process> rv
= new ArrayList<Process>();
for (Long group : groups) {
final Data d = getOrCreate(group);
if (d != null) {
d.fill(rv);
}
}
return rv;
}
/**
* Called periodically by quartz to keep the sessions alive.
*/
public int pingAll() {
// Use listImports since it's the fastest copy method we have.
List<Process> processes = listProcesses(null);
int errors = 0;
for (Process process: processes) {
try {
process.ping();
} catch (Throwable t) {
errors++;
log.info(String.format("Removing process [%s] due to error: %s",
process, t));
log.debug(t.toString()); // slf4j migration: toString()
}
}
return errors;
}
/**
* Called on shutdown of the server.
*/
public int shutdownAll() {
// Use listImports since it's the fastest copy method we have.
final List<Process> processes = listProcesses(null);
int errors = 0;
for (Process process: processes) {
try {
process.shutdown();
} catch (Throwable t) {
errors++;
log.error("Ignoring error on process shutdown", t);
}
}
return errors;
}
}