/* * * * Copyright 2014 Orient Technologies LTD (info(at)orientechnologies.com) * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * * limitations under the License. * * * * For more information: http://www.orientechnologies.com * */ package com.orientechnologies.orient.server.distributed; import com.orientechnologies.orient.core.exception.OSerializationException; import com.orientechnologies.orient.core.storage.impl.local.paginated.wal.OLogSequenceNumber; import java.io.*; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * Immutable class to store and handle information about synchronization between nodes. * * @author Luca Garulli (l.garulli--at--orientechnologies.com) */ public class ODistributedSyncConfiguration { private final ODistributedServerManager dManager; private final Map<String, OLogSequenceNumber> lastLSN = new ConcurrentHashMap<String, OLogSequenceNumber>(); private final String databaseName; private ODistributedMomentum momentum; private File file; private long lastOperationTimestamp = -1; private long lastLSNWrittenOnDisk = 0l; public ODistributedSyncConfiguration(final ODistributedServerManager manager, final String databaseName, final File file) throws IOException { this.dManager = manager; this.databaseName = databaseName; momentum = new ODistributedMomentum(); this.file = file; if (!file.exists()) { file.getParentFile().mkdirs(); file.createNewFile(); return; } load(); } public ODistributedMomentum getMomentum() { updateInternalDocument(); return momentum; } public OLogSequenceNumber getLastLSN(final String server) { return lastLSN.get(server); } public void setLastLSN(final String server, final OLogSequenceNumber lsn, final boolean updateLastOperationTimestamp) throws IOException { lastLSN.put(server, lsn); if (updateLastOperationTimestamp) { final long clusterTime = dManager.getClusterTime(); if (clusterTime > -1) lastOperationTimestamp = clusterTime; } // if (updateLastOperationTimestamp) // ODistributedServerLog.debug(this, dManager.getLocalNodeName(), server, ODistributedServerLog.DIRECTION.IN, // "Updating LSN %s lastOperationTimestamp=%d", lsn, lastOperationTimestamp); if (System.currentTimeMillis() - lastLSNWrittenOnDisk > 2000) save(); } public void load() throws IOException { final InputStream is = new FileInputStream(file); try { synchronized (momentum) { momentum.fromJSON(is); lastOperationTimestamp = momentum.getLastOperationTimestamp(); lastLSN.clear(); for (String server : momentum.getServers()) { lastLSN.put(server, momentum.getLSN(server)); } } } catch (OSerializationException e) { // CORRUPTED: RECREATE IT file.getParentFile().mkdirs(); file.createNewFile(); } finally { is.close(); } } public void save() throws IOException { updateInternalDocument(); lastLSNWrittenOnDisk = System.currentTimeMillis(); if (!file.exists()) { file.getParentFile().mkdirs(); file.createNewFile(); } final OutputStream os = new FileOutputStream(file, false); try { momentum.toJSON(os); } finally { os.close(); } } public long getLastOperationTimestamp() { return lastOperationTimestamp; } protected void updateInternalDocument() { momentum.setLastOperationTimestamp(lastOperationTimestamp); for (Map.Entry<String, OLogSequenceNumber> entry : lastLSN.entrySet()) momentum.setLSN(entry.getKey(), entry.getValue()); } public void removeServer(final String nodeName) throws IOException { if (lastLSN.remove(nodeName) != null) save(); } }