Skip to content

Commit

Permalink
Mark a cleared timetable snapshot as dirty.
Browse files Browse the repository at this point in the history
  • Loading branch information
jkoelewijn committed Apr 1, 2015
1 parent 817f352 commit f0ff7d2
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 15 deletions.
Expand Up @@ -95,7 +95,7 @@ public boolean equals(Object obj) {
} }


private static final Logger LOG = LoggerFactory.getLogger(TimetableSnapshot.class); private static final Logger LOG = LoggerFactory.getLogger(TimetableSnapshot.class);

// Use HashMap not Map so we can clone. // Use HashMap not Map so we can clone.
// if this turns out to be slow/spacious we can use an array with integer pattern indexes // if this turns out to be slow/spacious we can use an array with integer pattern indexes
// The SortedSet members are copy-on-write // The SortedSet members are copy-on-write
Expand All @@ -114,12 +114,24 @@ public boolean equals(Object obj) {
* </p> * </p>
*/ */
private HashMap<TripIdAndServiceDate, TripPattern> lastAddedTripPattern = new HashMap<>(); private HashMap<TripIdAndServiceDate, TripPattern> lastAddedTripPattern = new HashMap<>();

/**
* Boolean value indicating that timetable snapshot is read only if true. Once it is true, it shouldn't
* be possible to change it to false anymore.
*/
private boolean readOnly = false;


/**
* Boolean value indicating that this timetable snapshot contains changes compared to the state
* of the last commit if true.
*/
private boolean dirty = false;

/** /**
* A set of all timetables which have been modified and are waiting to be indexed. When * A set of all timetables which have been modified and are waiting to be indexed. When
* <code>dirty</code> is <code>null</code>, it indicates that the snapshot is read-only. * <code>dirty</code> is <code>null</code>, it indicates that the snapshot is read-only.
*/ */
private Set<Timetable> dirty = new HashSet<Timetable>(); private Set<Timetable> dirtyTimetables = new HashSet<Timetable>();


/** /**
* Returns an updated timetable for the specified pattern if one is available in this snapshot, * Returns an updated timetable for the specified pattern if one is available in this snapshot,
Expand Down Expand Up @@ -169,14 +181,14 @@ public boolean update(TripPattern pattern, TripTimes updatedTripTimes, ServiceDa
Preconditions.checkNotNull(pattern); Preconditions.checkNotNull(pattern);
Preconditions.checkNotNull(serviceDate); Preconditions.checkNotNull(serviceDate);


if (dirty == null) { if (readOnly) {
throw new ConcurrentModificationException("This TimetableSnapshot is read-only."); throw new ConcurrentModificationException("This TimetableSnapshot is read-only.");
} }


Timetable tt = resolve(pattern, serviceDate); Timetable tt = resolve(pattern, serviceDate);
// we need to perform the copy of Timetable here rather than in Timetable.update() // we need to perform the copy of Timetable here rather than in Timetable.update()
// to avoid repeatedly copying in case several updates are applied to the same timetable // to avoid repeatedly copying in case several updates are applied to the same timetable
if ( ! dirty.contains(tt)) { if ( ! dirtyTimetables.contains(tt)) {
Timetable old = tt; Timetable old = tt;
tt = new Timetable(tt, serviceDate); tt = new Timetable(tt, serviceDate);
SortedSet<Timetable> sortedTimetables = timetables.get(pattern); SortedSet<Timetable> sortedTimetables = timetables.get(pattern);
Expand All @@ -192,7 +204,8 @@ public boolean update(TripPattern pattern, TripTimes updatedTripTimes, ServiceDa
sortedTimetables.remove(old); sortedTimetables.remove(old);
sortedTimetables.add(tt); sortedTimetables.add(tt);
timetables.put(pattern, sortedTimetables); timetables.put(pattern, sortedTimetables);
dirty.add(tt); dirtyTimetables.add(tt);
dirty = true;
} }


// Assume all trips in a pattern are from the same feed, which should be the case. // Assume all trips in a pattern are from the same feed, which should be the case.
Expand Down Expand Up @@ -231,32 +244,38 @@ public TimetableSnapshot commit() {


@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public TimetableSnapshot commit(boolean force) { public TimetableSnapshot commit(boolean force) {
if (dirty == null) { if (readOnly) {
throw new ConcurrentModificationException("This TimetableSnapshot is read-only."); throw new ConcurrentModificationException("This TimetableSnapshot is read-only.");
} }


TimetableSnapshot ret = new TimetableSnapshot(); TimetableSnapshot ret = new TimetableSnapshot();
if (!force && !this.isDirty()) return null; if (!force && !this.isDirty()) return null;
for (Timetable tt : dirty) { for (Timetable tt : dirtyTimetables) {
tt.finish(); // summarize, index, etc. the new timetables tt.finish(); // summarize, index, etc. the new timetables
} }
ret.timetables = (HashMap<TripPattern, SortedSet<Timetable>>) this.timetables.clone(); ret.timetables = (HashMap<TripPattern, SortedSet<Timetable>>) this.timetables.clone();
ret.lastAddedTripPattern = (HashMap<TripIdAndServiceDate, TripPattern>) ret.lastAddedTripPattern = (HashMap<TripIdAndServiceDate, TripPattern>)
this.lastAddedTripPattern.clone(); this.lastAddedTripPattern.clone();
this.dirty.clear(); this.dirtyTimetables.clear();
this.dirty = false;


ret.dirty = null; // mark the snapshot as henceforth immutable ret.readOnly = true; // mark the snapshot as henceforth immutable
return ret; return ret;
} }


/** /**
* Clear all data from snapshot * Clear all data of snapshot
*/ */
public void clear() { public void clear() {
if (dirty == null) { if (readOnly) {
throw new ConcurrentModificationException("This TimetableSnapshot is read-only."); throw new ConcurrentModificationException("This TimetableSnapshot is read-only.");
} }


// If this snapshot is not empty, it will be dirty after the clear action
if (!timetables.isEmpty() || !lastAddedTripPattern.isEmpty()) {
dirty = true;
}

// Clear all data from snapshot // Clear all data from snapshot
timetables.clear(); timetables.clear();
lastAddedTripPattern.clear(); lastAddedTripPattern.clear();
Expand All @@ -266,7 +285,7 @@ public void clear() {
* Removes all Timetables which are valid for a ServiceDate on-or-before the one supplied. * Removes all Timetables which are valid for a ServiceDate on-or-before the one supplied.
*/ */
public boolean purgeExpiredData(ServiceDate serviceDate) { public boolean purgeExpiredData(ServiceDate serviceDate) {
if (dirty == null) { if (readOnly) {
throw new ConcurrentModificationException("This TimetableSnapshot is read-only."); throw new ConcurrentModificationException("This TimetableSnapshot is read-only.");
} }


Expand Down Expand Up @@ -305,12 +324,12 @@ public boolean purgeExpiredData(ServiceDate serviceDate) {
} }


public boolean isDirty() { public boolean isDirty() {
if (dirty == null) return false; if (readOnly) return false;
return dirty.size() > 0; return dirty;
} }


public String toString() { public String toString() {
String d = dirty == null ? "committed" : String.format("%d dirty", dirty.size()); String d = readOnly ? "committed" : String.format("%d dirty", dirtyTimetables.size());
return String.format("Timetable snapshot: %d timetables (%s)", timetables.size(), d); return String.format("Timetable snapshot: %d timetables (%s)", timetables.size(), d);
} }
} }
Expand Up @@ -676,6 +676,7 @@ private boolean addTripToGraphAndBuffer(final Graph graph, Trip trip,
TripTimes newTripTimes = new TripTimes(trip, stopTimes, graph.deduplicator); TripTimes newTripTimes = new TripTimes(trip, stopTimes, graph.deduplicator);


// Update all times to mark trip times as realtime // Update all times to mark trip times as realtime
// TODO: should we incorporate the delay field if present?
for (int stopIndex = 0; stopIndex < newTripTimes.getNumStops(); stopIndex++) { for (int stopIndex = 0; stopIndex < newTripTimes.getNumStops(); stopIndex++) {
newTripTimes.updateArrivalTime(stopIndex, newTripTimes.getScheduledArrivalTime(stopIndex)); newTripTimes.updateArrivalTime(stopIndex, newTripTimes.getScheduledArrivalTime(stopIndex));
newTripTimes.updateDepartureTime(stopIndex, newTripTimes.getScheduledDepartureTime(stopIndex)); newTripTimes.updateDepartureTime(stopIndex, newTripTimes.getScheduledDepartureTime(stopIndex));
Expand Down

0 comments on commit f0ff7d2

Please sign in to comment.