package cloudone.cumulonimbus.persistence;
import cloudone.C1Services;
import cloudone.cumulonimbus.ServiceRegistryService;
import cloudone.cumulonimbus.model.Cluster;
import cloudone.cumulonimbus.model.RegisteredRuntime;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* Store and load service registry data in periodical manner.
*
* @author Martin Mares (martin.mares at oracle.com)
*/
public class ServiceRegistryPersistence implements ServiceRegistryService.RegistrationListener {
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(ServiceRegistryPersistence.class);
private static final long INTERVAL = 3L; //seconds
private final File storageFile;
private final boolean manual;
private final Gson gson;
private final ServiceRegistryService serviceRegistryService;
private volatile boolean scheduled = false;
ServiceRegistryPersistence(final File storageFile,
final ServiceRegistryService serviceRegistryService,
final boolean manual) {
this.storageFile = storageFile;
this.manual = manual;
this.serviceRegistryService = serviceRegistryService;
this.gson = (new GsonBuilder())
.setPrettyPrinting()
.create();
}
public ServiceRegistryPersistence(final File storageFile,
final ServiceRegistryService serviceRegistryService) {
this(storageFile, serviceRegistryService, false);
}
private void scheduleNext() {
C1Services
.getInstance()
.getScheduledExecutorService()
.schedule(() -> {
try {
store();
} catch (IOException e) {
LOGGER.warn("Cannot store cluster data!", e);
} finally {
scheduled = false;
}
}, INTERVAL, TimeUnit.SECONDS);
}
synchronized void store() throws IOException {
LOGGER.info("Storing service registry.");
Collection<Cluster> clusters = new ArrayList<>(serviceRegistryService.getClusters());
if (clusters.isEmpty()) {
if (storageFile.exists()) {
storageFile.delete();
}
} else {
try (FileWriter writer = new FileWriter(storageFile)) {
gson.toJson(clusters, writer);
}
}
}
public synchronized Collection<Cluster> loadClusters() throws Exception {
List<Cluster> loaded = Collections.emptyList();
if (storageFile.exists()) {
LOGGER.info("Application registry storage found - loading");
try (Reader reader = new FileReader(storageFile)) {
loaded = gson.fromJson(reader, (new TypeToken<ArrayList<Cluster>>() {}).getType());
} catch (IOException e) {
throw new Exception("Cannot read persisted registry!", e);
}
if (loaded == null) {
loaded = Collections.emptyList();
}
}
return loaded;
}
@Override
public synchronized void register(RegisteredRuntime runtime, Cluster cluster) {
if (!scheduled && !manual) {
scheduleNext();
scheduled = true;
}
}
@Override
public synchronized void unregister(RegisteredRuntime runtime, Cluster cluster) {
register(runtime, cluster); //The same behavior
}
}