* @throws TimeoutException
* @throws PersistitException
*/
void prune() throws TimeoutException, PersistitException {
final List<Entry> entriesToPrune = new ArrayList<Entry>();
PrunableVersion versionToVacate = null;
final TransactionIndex ti = _persistit.getTransactionIndex();
synchronized (this) {
try {
Entry newer = null;
Entry latest = null;
boolean isPrimordial = true;
long lastCommit = UNCOMMITTED;
for (Entry entry = _first; entry != null; entry = entry.getPrevious()) {
boolean keepIt = false;
final long versionHandle = entry.getVersion();
final long tc = ti.commitStatus(versionHandle, UNCOMMITTED, 0);
if (tc >= PRIMORDIAL) {
if (tc == UNCOMMITTED) {
keepIt = true;
isPrimordial = false;
} else {
final boolean hasConcurrent = ti.hasConcurrentTransaction(tc, lastCommit);
if (latest == null || hasConcurrent) {
keepIt = true;
if (latest == null) {
latest = entry;
}
}
if (keepIt && ti.hasConcurrentTransaction(0, tc)) {
isPrimordial = false;
}
}
lastCommit = tc;
} else {
assert tc == ABORTED;
}
if (keepIt) {
newer = entry;
} else {
if (tc == ABORTED ^ entry.isDeleted()) {
entriesToPrune.add(entry);
}
if (newer == null) {
_first = entry.getPrevious();
} else {
newer.setPrevious(entry.getPrevious());
}
}
}
if (isPrimordial && _first != null) {
assert _first.getPrevious() == null;
if (_first.isDeleted()) {
final V version = _first.getResource();
if (version instanceof PrunableVersion) {
versionToVacate = (PrunableVersion) version;
}
entriesToPrune.add(_first);
_first = null;
} else {
_first.setPrimordial();
}
}
} catch (final InterruptedException ie) {
throw new PersistitInterruptedException(ie);
}
}
for (final Entry e : entriesToPrune) {
if (versionToVacate != null) {
versionToVacate.vacate();
}
e.prune();
}
}