/*******************************************************************************
* Copyright (c) 2012, 2015 Wind River Systems, Inc. and others. All rights reserved.
* This program and the accompanying materials are made available under the terms
* of the Eclipse Public License v1.0 which accompanies this distribution, and is
* available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.tcf.te.tcf.filesystem.core.internal.utils;
import java.beans.PropertyChangeEvent;
import java.io.File;
import org.eclipse.tcf.te.tcf.filesystem.core.internal.FSTreeNode;
import org.eclipse.tcf.te.tcf.filesystem.core.model.CacheState;
/**
* The state object to describe a file's state.
*/
public class FileState {
/**
* The base digest of the file data.
*/
private byte[] base_digest = null;
/**
* The message digest of the file data.
*/
private byte[] target_digest = null;
/**
* The message digest of the local cache data
*/
private byte[] cache_digest = null;
/**
* The cache file's modification time.
*/
private long cache_mtime;
/**
* The cache file's modification time.
*/
private long target_mtime;
/**
* If the job that computes the local cache's digest is running.
*/
transient boolean cache_digest_running = false;
/**
* If the job that computes the target file's digest is running.
*/
transient boolean target_digest_running = false;
/**
* The file system node whose state is described.
*/
private transient FSTreeNode node;
/**
* Create a file state using the node.
*
* @param node The file system node.
*/
public FileState(FSTreeNode node) {
this.node = node;
}
/**
* Create a file state using the specified state data.
*
* @param mtime The cache file's modification time.
* @param cache_digest The cache file's digest.
* @param target_digest The target file's digest.
* @param base_digest The baseline digest.
*/
public FileState(long mtime, long target_mtime, byte[] cache_digest, byte[] target_digest, byte[]base_digest) {
this.cache_mtime = mtime;
this.target_mtime = target_mtime;
this.cache_digest = cache_digest;
this.target_digest = target_digest;
this.base_digest = base_digest;
}
/**
* Set the file system node.
*
* @param node The file system node.
*/
void setNode(FSTreeNode node) {
this.node = node;
}
/**
* Get the node's target file digest.
*
* @return The target file digest.
*/
public byte[] getTargetDigest() {
return target_digest;
}
/**
* Get the node's baseline digest.
*
* @return The baseline digest.
*/
public byte[] getBaseDigest() {
return base_digest;
}
/**
* Get the node's cache file modification time.
*
* @return The cache file's modification time.
*/
public long getCacheMTime() {
return cache_mtime;
}
public long getTargetMTime() {
return target_mtime;
}
/**
* Get the node's cache file digest.
*
* @return The cache file digest.
*/
public byte[] getCacheDigest() {
return cache_digest;
}
/**
* Get this node's cache state using the current state data.
*
* @return The state expressed in a CacheState enum value.
*/
public synchronized CacheState getCacheState() {
File file = CacheManager.getCacheFile(node);
if (!file.exists())
return CacheState.consistent;
if (cache_digest == null || target_digest == null)
return CacheState.consistent;
if (isUnchanged(target_digest, cache_digest)) {
base_digest = target_digest;
return CacheState.consistent;
}
if(isUnchanged(base_digest, cache_digest)){
return CacheState.outdated;
}
if (isUnchanged(target_digest, base_digest)) {
return CacheState.modified;
}
return CacheState.conflict;
}
/**
* Update the node's target digest and fire an event.
*
* @param target_digest The new target digest data.
*/
public void updateTargetDigest(byte[] target_digest, long mtime) {
// System.out.println("targt: " + mtime + " " + PersistenceManagerDelegate.digest2string(target_digest));
this.target_digest = target_digest;
this.target_mtime = mtime;
PropertyChangeEvent event = new PropertyChangeEvent(this, "target_digest", null, target_digest); //$NON-NLS-1$
node.getRuntimeModel().firePropertyChanged(event);
}
/**
* Compare the two digests to see if they are equal to each other.
*
* @param digest1 The first digest.
* @param digest2 The second digest.
* @return true if they are equal.
*/
private boolean isUnchanged(byte[] digest1, byte[] digest2){
if(digest1 != null && digest2 != null && digest1.length == digest2.length) {
for (int i = 0; i < digest1.length; i++) {
if(digest1[i] != digest2[i]) return false;
}
return true;
}
return false;
}
/**
* Update the cache file digest data and fire an event.
*
* @param cache_digest The new cache file digest data.
*/
public void updateCacheDigest(byte[] cache_digest, long mtime) {
// System.out.println("cache: " + mtime + " " + PersistenceManagerDelegate.digest2string(cache_digest));
byte[] old_digest = cache_digest;
this.cache_digest = cache_digest;
this.cache_mtime = mtime;
PropertyChangeEvent event = new PropertyChangeEvent(node, "cache_digest", old_digest, cache_digest); //$NON-NLS-1$
node.getRuntimeModel().firePropertyChanged(event);
}
/**
* Reset all of the node's digest data to a new digest data.
*
* @param digest The new digest data.
*/
public void reset(byte[] digest, long cache_mtime, long target_mtime) {
// System.out.println("reset: " + cache_mtime + " " + target_mtime + " " + PersistenceManagerDelegate.digest2string(digest));
cache_digest = digest;
target_digest = digest;
base_digest = digest;
this.cache_mtime = cache_mtime;
this.target_mtime = target_mtime;
PropertyChangeEvent event = new PropertyChangeEvent(node, "reset_digest", null, digest); //$NON-NLS-1$
node.getRuntimeModel().firePropertyChanged(event);
}
}