package edu.brown.designer.mappers;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import org.json.JSONException;
import org.json.JSONString;
import org.json.JSONStringer;
import org.voltdb.catalog.Column;
import org.voltdb.catalog.Database;
import org.voltdb.catalog.Host;
import org.voltdb.catalog.Table;
import edu.brown.catalog.CatalogKey;
import edu.brown.designer.MemoryEstimator;
import edu.brown.hashing.AbstractHasher;
import edu.brown.statistics.WorkloadStatistics;
public class PartitionMapping implements JSONString {
private static final String SPACER = " ";
private final Set<FragmentEntry> fragments = new HashSet<FragmentEntry>();
private transient final Map<FragmentEntry, SiteEntry> fragment_site_xref = new HashMap<FragmentEntry, SiteEntry>();
private transient final Map<String, Set<FragmentEntry>> table_fragment_xref = new HashMap<String, Set<FragmentEntry>>();
private final SortedSet<SiteEntry> sites = new TreeSet<SiteEntry>();
private transient final Map<String, SortedSet<SiteEntry>> host_site_xref = new HashMap<String, SortedSet<SiteEntry>>();
private transient final Map<Integer, SiteEntry> site_id_xref = new HashMap<Integer, SiteEntry>();
/**
* Constructor
*
* @param catalogContext
* @param pplan
*/
public PartitionMapping() {
// Do nothing...
}
public void initialize() {
for (SiteEntry site : this.sites) {
String host_key = site.getHostKey();
if (!this.host_site_xref.containsKey(host_key)) {
this.host_site_xref.put(host_key, new TreeSet<SiteEntry>());
}
this.host_site_xref.get(host_key).add(site);
for (FragmentEntry fragment : site.getFragments()) {
this.fragments.add(fragment);
this.fragment_site_xref.put(fragment, site);
String table_key = fragment.getTableKey();
if (!this.table_fragment_xref.containsKey(table_key)) {
this.table_fragment_xref.put(table_key, new HashSet<FragmentEntry>());
}
this.table_fragment_xref.get(table_key).add(fragment);
} // FOR
} // FOR
}
public void apply(Database catalog_db, WorkloadStatistics stats, AbstractHasher hasher) {
//
// We need to estimate how big each partition is
//
MemoryEstimator estimator = new MemoryEstimator(stats, hasher);
for (SiteEntry site : this.sites) {
long site_size = 0l;
for (FragmentEntry fragment : site.getFragments()) {
Table catalog_tbl = fragment.getTable(catalog_db);
Column partition_col = catalog_tbl.getPartitioncolumn();
long size = estimator.estimate(catalog_tbl, partition_col, fragment.getHashKey());
site_size += size;
fragment.setEstimatedSize(size);
} // FOR
site.setEstimatedSize(site_size);
} // FOR
}
public long getTotalSize(Host catalog_host) {
long total = 0;
for (SiteEntry site : this.host_site_xref.get(catalog_host)) {
total += site.getEstimatedSize();
} // FOR
return (total);
}
/**
* Assign the SiteEntry to a particular Host
*
* @param catalog_host
* @param site
*/
public void assign(Host catalog_host, SiteEntry site) {
assert (catalog_host != null);
assert (site != null);
if (site.getHostKey() != null) {
this.host_site_xref.get(site.getHostKey()).remove(site);
}
String host_key = CatalogKey.createKey(catalog_host);
site.setHostKey(host_key);
if (!this.host_site_xref.containsKey(host_key)) {
this.host_site_xref.put(host_key, new TreeSet<SiteEntry>());
}
this.host_site_xref.get(host_key).add(site);
this.site_id_xref.put(site.getId(), site);
this.sites.add(site);
}
/**
* Assign the FragmentEntry to a particular SiteEntry
*
* @param site
* @param fragment
*/
public void assign(SiteEntry site, FragmentEntry fragment) {
assert (site != null);
assert (fragment != null);
site.add(fragment);
this.fragment_site_xref.put(fragment, site);
this.fragments.add(fragment);
}
/**
* Merge the source SiteEntry into the target SiteEntry
*
* @param source
* @param target
*/
public void merge(SiteEntry source, SiteEntry target) {
// Copy over all the fragments
for (FragmentEntry fragment : source.getFragments()) {
this.assign(target, fragment);
} // FOR
// Remove all references to the source SiteEntry
this.site_id_xref.remove(source.getId());
this.host_site_xref.get(source.getHostKey()).remove(source);
}
public FragmentEntry getFragment(Table catalog_tbl, int hash) {
String table_key = CatalogKey.createKey(catalog_tbl);
for (FragmentEntry fragment : this.fragments) {
if (fragment.getTableKey().equals(table_key) && fragment.getHashKey() == hash) {
return (fragment);
}
} // FOR
return (null);
}
public SiteEntry getSite(Table catalog_tbl, int hash) {
FragmentEntry fragment = this.getFragment(catalog_tbl, hash);
return (this.fragment_site_xref.get(fragment));
}
public SiteEntry getSite(int id) {
return (this.site_id_xref.get(id));
}
public Set<String> getHosts() {
return (this.host_site_xref.keySet());
}
public Set<Host> getHosts(Database catalog_db) {
Set<Host> hosts = new HashSet<Host>();
for (String host_key : this.getHosts()) {
Host catalog_host = CatalogKey.getFromKey(catalog_db, host_key, Host.class);
assert (catalog_host != null);
hosts.add(catalog_host);
} // FOR
return (hosts);
}
/**
*
*/
@Override
public String toJSONString() {
JSONStringer stringer = new JSONStringer();
try {
stringer.object();
this.toJSONString(stringer);
stringer.endObject();
} catch (JSONException e) {
e.printStackTrace();
System.exit(-1);
}
return stringer.toString();
}
public void toJSONString(JSONStringer stringer) throws JSONException {
// TODO
}
public String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append("Hosts: ").append(this.getHosts().size()).append("\n");
buffer.append("Sites: ").append(this.sites.size()).append("\n");
buffer.append("Fragments: ").append(this.fragments.size()).append("\n");
SortedSet<String> hosts = new TreeSet<String>();
hosts.addAll(this.getHosts());
for (String host_key : hosts) {
buffer.append("\nHost ").append(CatalogKey.getNameFromKey(host_key)).append("\n");
for (SiteEntry site : this.host_site_xref.get(host_key)) {
buffer.append(SPACER).append("Site ").append(site.getId()).append("\n");
for (FragmentEntry fragment : site.getFragments()) {
buffer.append(SPACER).append(SPACER).append("Fragment ").append(fragment).append(" Size=").append(fragment.getEstimatedSize()).append(" Heat=").append(fragment.getEstimatedHeat())
.append("\n");
} // FOR
} // FOR
buffer.append("--------------------");
} // FOR
return (buffer.toString());
}
}