/*
* Copyright 2004 - 2008 Christian Sprajc, Dennis Waldherr. All rights reserved.
*
* This file is part of PowerFolder.
*
* PowerFolder 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.
*
* PowerFolder 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 PowerFolder. If not, see <http://www.gnu.org/licenses/>.
*
* $Id$
*/
package de.dal33t.powerfolder.util.delta;
import de.dal33t.powerfolder.util.Partitions;
import de.dal33t.powerfolder.util.Range;
import java.io.Serializable;
/**
* Manages the parts of a file which contain data or not.
* This class is Thread-safe.
*
* @author Dennis "Dante" Waldherr
* @version $Revision: 4280 $
*
*/
public class FilePartsState implements Serializable {
private static final long serialVersionUID = 1L;
public static enum PartState {
NEEDED, // Not available and not yet requested
PENDING, // Requested for download but not yet received
AVAILABLE // Available for own upload
}
private Partitions<PartState> parts;
/**
* Creates a new instance with the given length.
* All elements are set to NEEDED initially.
* @param fileLength
*/
public FilePartsState(long fileLength) {
parts = new Partitions<PartState>(Range.getRangeByLength(0, fileLength), PartState.NEEDED);
}
/**
* Returns the first range that lies within "in", which is marked with the given state.
* @param in
* @param state
* @return a Range or null if if no range was found
*/
public synchronized Range findPart(Range in, PartState state) {
return parts.search(in, state);
}
/**
* Returns the first range that is marked with the state.
* @param state
* @return
*/
public synchronized Range findFirstPart(PartState state) {
return findPart(parts.getPartionedRange(), state);
}
/**
* Marks a range of data with a given state
* @param range
* @param state
*/
public synchronized void setPartState(Range range, PartState state) {
parts.insert(range, state);
}
/**
* Counts the number of PartStates in the given range that match the given PartState.
* @param r
* @param s
* @return
*/
public synchronized long countPartStates(Range r, PartState s) {
return parts.count(r, s);
}
/**
* Resets all pending ranges to needed.
*/
public synchronized void purgePending() {
Range r = Range.getRangeByNumbers(0, parts.getPartionedRange().getEnd());
Range wr;
while ((wr = findPart(r, PartState.PENDING)) != null) {
setPartState(wr, PartState.NEEDED);
r = Range.getRangeByNumbers(wr.getEnd() + 1, r.getEnd());
}
}
public long getFileLength() {
return parts.getPartionedRange().getLength();
}
public Range getRange() {
return parts.getPartionedRange();
}
public synchronized boolean isCompleted() {
if (parts.getPartionedRange().getLength() == 0) {
return true;
}
Range r = parts.search(parts.getPartionedRange(), PartState.AVAILABLE);
if (r == null) {
return false;
}
return r.equals(parts.getPartionedRange());
}
}