org.voltdb.sysprocs.saverestore.ReplicatedTableSaveFileState Maven / Gradle / Ivy
/* This file is part of VoltDB.
* Copyright (C) 2008-2018 VoltDB Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with VoltDB. If not, see .
*/
package org.voltdb.sysprocs.saverestore;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
import org.voltdb.ParameterSet;
import org.voltdb.VoltSystemProcedure.SynthesizedPlanFragment;
import org.voltdb.VoltTableRow;
import org.voltdb.catalog.Table;
import org.voltdb.dtxn.SiteTracker;
import org.voltdb.sysprocs.SysProcFragmentId;
public class ReplicatedTableSaveFileState extends TableSaveFileState
{
ReplicatedTableSaveFileState(String tableName, long txnId)
{
super(tableName, txnId);
}
@Override
void addHostData(VoltTableRow row) throws IOException
{
assert(row.getString("TABLE").equals(getTableName()));
checkSiteConsistency(row); // throws if inconsistent
// this cast should be safe; site_ids are ints but get
// promoted to long in the VoltTable.row.getLong return
m_hostsWithThisTable.add((int) row.getLong("CURRENT_HOST_ID"));
}
@Override
public boolean isConsistent()
{
// right now there is nothing to check across all rows
m_consistencyResult = "Table: " + getTableName() +
" has consistent savefile state.";
return true;
}
public Set getHostsWithThisTable() {
return m_hostsWithThisTable;
}
@Override
public SynthesizedPlanFragment[]
generateRestorePlan(Table catalogTable, SiteTracker st)
{
for (int hostId : m_hostsWithThisTable) {
m_sitesWithThisTable.addAll(st.getSitesForHost(hostId));
}
SynthesizedPlanFragment[] restore_plan = null;
if (catalogTable.getIsreplicated())
{
restore_plan = generateReplicatedToReplicatedPlan(st);
}
else
{
restore_plan = generateReplicatedToPartitionedPlan(st);
}
return restore_plan;
}
private void checkSiteConsistency(VoltTableRow row) throws IOException
{
if (!row.getString("IS_REPLICATED").equals("TRUE"))
{
String error = "Table: " + getTableName() + " was replicated " +
"but has a savefile which indicates partitioning at site: " +
row.getLong("CURRENT_HOST_ID");
m_consistencyResult = error;
throw new IOException(error);
}
}
private SynthesizedPlanFragment[]
generateReplicatedToPartitionedPlan(SiteTracker st)
{
SynthesizedPlanFragment[] restore_plan = null;
Integer host = m_hostsWithThisTable.iterator().next();
// replicated table is small enough for only one site to distribute the task
restore_plan = new SynthesizedPlanFragment[2];
int restore_plan_index = 0;
assert(st.getSitesForHost(host).size() > 0);
long site = st.getSitesForHost(host).get(0);
restore_plan[restore_plan_index] = constructDistributeReplicatedTableAsPartitionedFragment(site);
++restore_plan_index;
restore_plan[restore_plan_index] = constructLoadReplicatedTableAggregatorFragment(true);
return restore_plan;
}
private SynthesizedPlanFragment
constructDistributeReplicatedTableAsPartitionedFragment(long siteId)
{
int result_dependency_id = getNextDependencyId();
SynthesizedPlanFragment plan_fragment = new SynthesizedPlanFragment();
plan_fragment.fragmentId =
SysProcFragmentId.PF_restoreDistributeReplicatedTableAsPartitioned;
plan_fragment.multipartition = false;
plan_fragment.siteId = siteId;
plan_fragment.outputDepId = result_dependency_id;
plan_fragment.inputDepIds = new int[] {};
addPlanDependencyId(result_dependency_id);
plan_fragment.parameters = ParameterSet.fromArrayNoCopy(
getTableName(),
result_dependency_id,
getIsRecoverParam());
return plan_fragment;
}
private SynthesizedPlanFragment[]
generateReplicatedToReplicatedPlan(SiteTracker st)
{
SynthesizedPlanFragment[] restore_plan = null;
Set execution_site_ids =
st.getAllSites();
Set sites_missing_table =
getSitesMissingTable(execution_site_ids);
// not sure we want to deal with handling expected load failures,
// so let's send an individual load to each site with the table
// and then pick sites to send the table to those without it
restore_plan =
new SynthesizedPlanFragment[execution_site_ids.size() + 1];
int restore_plan_index = 0;
for (Long site_id : m_sitesWithThisTable)
{
restore_plan[restore_plan_index] =
constructLoadReplicatedTableFragment();
restore_plan[restore_plan_index].siteId = site_id;
++restore_plan_index;
}
for (Long site_id : sites_missing_table)
{
long source_site_id =
m_sitesWithThisTable.iterator().next();
restore_plan[restore_plan_index] =
constructDistributeReplicatedTableAsReplicatedFragment(source_site_id,
site_id);
++restore_plan_index;
}
assert(restore_plan_index == execution_site_ids.size());
restore_plan[restore_plan_index] =
constructLoadReplicatedTableAggregatorFragment(false);
return restore_plan;
}
private Set getSitesMissingTable(Set clusterSiteIds)
{
Set sites_missing_table = new HashSet();
for (long site_id : clusterSiteIds)
{
if (!m_sitesWithThisTable.contains(site_id))
{
sites_missing_table.add(site_id);
}
}
return sites_missing_table;
}
private SynthesizedPlanFragment
constructLoadReplicatedTableFragment()
{
int result_dependency_id = getNextDependencyId();
SynthesizedPlanFragment plan_fragment = new SynthesizedPlanFragment();
plan_fragment.fragmentId =
SysProcFragmentId.PF_restoreLoadReplicatedTable;
plan_fragment.multipartition = false;
plan_fragment.outputDepId = result_dependency_id;
plan_fragment.inputDepIds = new int[] {};
addPlanDependencyId(result_dependency_id);
plan_fragment.parameters = ParameterSet.fromArrayNoCopy(
getTableName(),
result_dependency_id,
getIsRecoverParam());
return plan_fragment;
}
private SynthesizedPlanFragment
constructDistributeReplicatedTableAsReplicatedFragment(long sourceSiteId,
long destinationSiteId)
{
int result_dependency_id = getNextDependencyId();
SynthesizedPlanFragment plan_fragment = new SynthesizedPlanFragment();
plan_fragment.fragmentId =
SysProcFragmentId.PF_restoreDistributeReplicatedTableAsReplicated;
plan_fragment.multipartition = false;
plan_fragment.siteId = sourceSiteId;
plan_fragment.outputDepId = result_dependency_id;
plan_fragment.inputDepIds = new int[] {};
addPlanDependencyId(result_dependency_id);
plan_fragment.parameters = ParameterSet.fromArrayNoCopy(
getTableName(),
destinationSiteId,
result_dependency_id,
getIsRecoverParam());
return plan_fragment;
}
private SynthesizedPlanFragment
constructLoadReplicatedTableAggregatorFragment(boolean asPartitioned)
{
int result_dependency_id = getNextDependencyId();
SynthesizedPlanFragment plan_fragment = new SynthesizedPlanFragment();
plan_fragment.fragmentId =
SysProcFragmentId.PF_restoreReceiveResultTables;
plan_fragment.multipartition = false;
plan_fragment.outputDepId = result_dependency_id;
plan_fragment.inputDepIds = getPlanDependencyIds();
setRootDependencyId(result_dependency_id);
plan_fragment.parameters = ParameterSet.fromArrayNoCopy(result_dependency_id,
(asPartitioned ? "Aggregating replicated-to-partitioned table restore results"
: "Aggregating replicated table restore results"),
getIsRecoverParam());
return plan_fragment;
}
private final Set m_hostsWithThisTable = new HashSet();
private final Set m_sitesWithThisTable = new TreeSet();
}