/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.github.geophile.erdo.forest;
import com.github.geophile.erdo.apiimpl.DatabaseImpl;
import com.github.geophile.erdo.consolidate.ConsolidationSetSnapshot;
import com.github.geophile.erdo.map.SealedMap;
import com.github.geophile.erdo.transaction.TransactionOwners;
import java.util.ArrayList;
import java.util.List;
import static com.github.geophile.erdo.consolidate.Consolidation.Element;
import static com.github.geophile.erdo.util.Math.log2;
public class ForestSnapshot
{
public String toString()
{
StringBuilder buffer = new StringBuilder();
List<Element> elements = trees.elements();
int n = elements.size();
for (int e = 0; e < n; e++) {
Element tree = elements.get(e);
if (buffer.length() > 0) {
buffer.append(", ");
}
buffer.append(tree.timestamps().toString());
}
return buffer.toString();
}
// TODO: This is a snapshot. Is synchronized needed?
public synchronized SealedMap mapContainingTransaction(long timestamp)
{
return (SealedMap) transactionOwners.find(timestamp);
}
public List<SealedMap> smallTrees()
{
ensureSmallAndBigTrees();
return smallTrees;
}
public List<SealedMap> bigTrees()
{
ensureSmallAndBigTrees();
return bigTrees;
}
public void cleanup()
{
trees.cleanup();
}
public DatabaseImpl database()
{
return database;
}
public int population()
{
ensureSmallAndBigTrees();
return smallTrees.size() + bigTrees.size();
}
public long recordCount()
{
ensureSmallAndBigTrees();
return recordCount;
}
public double complexity()
{
ensureSmallAndBigTrees();
double sumLog = 0;
for (SealedMap tree : smallTrees) {
long n = tree.recordCount();
if (n > 0) {
sumLog += log2(n);
}
}
for (SealedMap tree : bigTrees) {
long n = tree.recordCount();
if (n > 0) {
sumLog += log2(n);
}
}
return sumLog;
}
public ForestSnapshot(DatabaseImpl database,
TransactionOwners transactionOwners,
ConsolidationSetSnapshot trees)
{
this.database = database;
this.transactionOwners = transactionOwners;
this.trees = trees;
}
// For use by this class
private void ensureSmallAndBigTrees()
{
if (smallTrees == null) {
// TODO: This is a snapshot. Synchronization needed?
synchronized (this) {
if (smallTrees == null) {
List<Element> elements = trees.elements();
int n = elements.size();
smallTrees = new ArrayList<>(n);
bigTrees = new ArrayList<>(n);
recordCount = 0;
for (int e = 0; e < n; e++) {
SealedMap map = (SealedMap) elements.get(e);
if (map.recordCount() > 0) {
if (map.keysInMemory()) {
smallTrees.add(map);
} else {
bigTrees.add(map);
}
}
recordCount += map.recordCount();
}
}
}
}
}
// Object state
private final DatabaseImpl database;
private final TransactionOwners transactionOwners;
private final ConsolidationSetSnapshot trees;
private List<SealedMap> smallTrees;
private List<SealedMap> bigTrees;
private long recordCount;
}