/* This file is part of VoltDB. * Copyright (C) 2008-2017 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 <http://www.gnu.org/licenses/>. */ package org.voltdb.sysprocs.saverestore; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.SortedMap; import org.json_voltpatches.JSONException; import org.json_voltpatches.JSONObject; import org.json_voltpatches.JSONStringer; import org.voltdb.catalog.Database; import org.voltdb.catalog.Table; import com.google_voltpatches.common.collect.ImmutableList; import com.google_voltpatches.common.collect.ImmutableSortedMap; /** * Encapsulates all the information needed to initiate the snapshot that will build the elastic * index. */ public class IndexSnapshotRequestConfig extends SnapshotRequestConfig { public static class PartitionRanges { public final int partitionId; public final SortedMap<Integer, Integer> ranges; /** * @param partitionId The partition that currently owns the ranges * @param ranges The ranges to index on this partition */ public PartitionRanges(int partitionId, Map<Integer, Integer> ranges) { this.partitionId = partitionId; this.ranges = ImmutableSortedMap.copyOf(ranges); } } public final Collection<PartitionRanges> partitionRanges; public IndexSnapshotRequestConfig(List<Table> tables, Collection<PartitionRanges> partitionRanges) { super(tables); this.partitionRanges = ImmutableList.copyOf(partitionRanges); } public IndexSnapshotRequestConfig(JSONObject jsData, Database catalogDatabase) { super(jsData, catalogDatabase); partitionRanges = parsePartitionRanges(jsData); } // parse ranges private Collection<PartitionRanges> parsePartitionRanges(JSONObject jsData) { if (jsData != null) { try { JSONObject partitionObj = jsData.getJSONObject("partitionRanges"); Iterator partitionKey = partitionObj.keys(); ImmutableList.Builder<PartitionRanges> partitionRangesBuilder = ImmutableList.builder(); while (partitionKey.hasNext()) { String pidStr = (String) partitionKey.next(); JSONObject rangeObj = partitionObj.getJSONObject(pidStr); Iterator rangeKey = rangeObj.keys(); ImmutableSortedMap.Builder<Integer, Integer> rangeBuilder = ImmutableSortedMap.naturalOrder(); while (rangeKey.hasNext()) { String rangeStartStr = (String) rangeKey.next(); int rangeStart = Integer.parseInt(rangeStartStr); int rangeEnd = rangeObj.getInt(rangeStartStr); rangeBuilder.put(rangeStart, rangeEnd); } partitionRangesBuilder.add(new PartitionRanges(Integer.parseInt(pidStr), rangeBuilder.build())); } return partitionRangesBuilder.build(); } catch (JSONException e) { SNAP_LOG.warn("Failed to parse partition ranges", e); } } return null; } // serialize request @Override public void toJSONString(JSONStringer stringer) throws JSONException { super.toJSONString(stringer); stringer.key("partitionRanges").object(); for (PartitionRanges partitionRange : partitionRanges) { stringer.key(Integer.toString(partitionRange.partitionId)).object(); for (Map.Entry<Integer, Integer> rangeEntry : partitionRange.ranges.entrySet()) { stringer.key(rangeEntry.getKey().toString()).value(rangeEntry.getValue()); } stringer.endObject(); } stringer.endObject(); } }