// This software is released into the Public Domain. See copying.txt for details. package org.openstreetmap.osmosis.replication.common; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.openstreetmap.osmosis.core.OsmosisRuntimeException; import org.openstreetmap.osmosis.core.time.DateFormatter; import org.openstreetmap.osmosis.core.time.DateParser; /** * Contains the state to be remembered between replication invocations. This * state ensures that no data is missed during replication, and ensures that * none is repeated except after certain failure situations. */ public class ReplicationState { /** * The key used when passing an instance through the pipeline as metadata. */ public static final String META_DATA_KEY = "replication.state"; private Date timestamp; private long sequenceNumber; /** * Creates a new instance with all values set to defaults. */ public ReplicationState() { this.timestamp = new Date(0); this.sequenceNumber = 0; } /** * Creates a new instance. * * @param timestamp * The maximum timestamp of data currently read from the database. * @param sequenceNumber * The replication sequence number. */ public ReplicationState(Date timestamp, long sequenceNumber) { this.timestamp = timestamp; this.sequenceNumber = sequenceNumber; } /** * Creates a new instance. * * @param properties * The properties to load state from. */ public ReplicationState(Map<String, String> properties) { load(properties); } private String loadProperty(Map<String, String> properties, String key) { if (!properties.containsKey(key)) { throw new OsmosisRuntimeException("The replication state doesn't contain a " + key + " property."); } return properties.get(key); } /** * Loads all state from the provided properties object. * * @param properties * The properties to be read. */ public void load(Map<String, String> properties) { timestamp = new DateParser().parse(loadProperty(properties, "timestamp")); sequenceNumber = Long.parseLong(loadProperty(properties, "sequenceNumber")); } /** * Writes all state into the provided properties object. * * @param properties * The properties to be updated. */ public void store(Map<String, String> properties) { properties.put("timestamp", new DateFormatter().format(timestamp)); properties.put("sequenceNumber", Long.toString(sequenceNumber)); } /** * Writes all state into a new properties object. * * @return The properties. */ public Map<String, String> store() { Map<String, String> properties = new HashMap<String, String>(); store(properties); return properties; } /** * Gets the maximum timestamp of data currently read from the database. * * @return The timestamp. */ public Date getTimestamp() { return timestamp; } /** * Sets the maximum timestamp of data currently read from the database. * * @param timestamp * The timestamp. */ public void setTimestamp(Date timestamp) { this.timestamp = timestamp; } /** * Gets the replication sequence number. * * @return The sequence number. */ public long getSequenceNumber() { return sequenceNumber; } /** * Sets the replication sequence number. * * @param sequenceNumber * The sequence number. */ public void setSequenceNumber(long sequenceNumber) { this.sequenceNumber = sequenceNumber; } /** * {@inheritDoc} */ @Override public boolean equals(Object obj) { boolean result; if (obj instanceof ReplicationState) { ReplicationState compareState = (ReplicationState) obj; if (timestamp.equals(compareState.timestamp) && sequenceNumber == compareState.sequenceNumber) { result = true; } else { result = false; } } else { result = false; } return result; } /** * {@inheritDoc} */ @Override public int hashCode() { return (int) sequenceNumber + (int) timestamp.getTime(); } /** * {@inheritDoc} */ @Override public String toString() { return "ReplicationState(timestamp=" + timestamp + ", sequenceNumber=" + sequenceNumber + ")"; } }