/* This file is part of VoltDB. * Copyright (C) 2008-2010 VoltDB Inc. * * VoltDB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * VoltDB 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with VoltDB. If not, see <http://www.gnu.org/licenses/>. */ package org.voltdb.sysprocs; import java.util.HashMap; import java.util.TreeSet; import java.util.Iterator; import org.voltdb.sysprocs.saverestore.SnapshotUtil; /** * The snapshot registry contains information about snapshots that executed * while the system was running. * */ public class SnapshotRegistry { private static final int m_maxStatusHistory = 10; private static final TreeSet<Snapshot> m_snapshots = new TreeSet<Snapshot>( new java.util.Comparator<Snapshot>() { @Override public int compare(Snapshot o1, Snapshot o2) { return new Long(o1.timeStarted).compareTo(o2.timeStarted); } }); public static class Snapshot { public final long timeStarted; public final long timeFinished; public final String path; public final String nonce; public final boolean result; //true success, false failure public final long bytesWritten; private final HashMap< String, Table> tables = new HashMap< String, Table>(); private Snapshot(long startTime, int hostId, int siteId, int partitionId, String path, String nonce, org.voltdb.catalog.Table tables[]) { timeStarted = startTime; this.path = path; this.nonce = nonce; timeFinished = 0; synchronized (this.tables) { for (org.voltdb.catalog.Table table : tables) { String filename = SnapshotUtil.constructFilenameForTable(table, nonce, Integer.toString(hostId), Integer.toString(siteId), Integer.toString(partitionId) ); this.tables.put(table.getTypeName(), new Table(table.getTypeName(), filename)); } } result = false; bytesWritten = 0; } private Snapshot(Snapshot incomplete, long timeFinished) { timeStarted = incomplete.timeStarted; path = incomplete.path; nonce = incomplete.nonce; this.timeFinished = timeFinished; synchronized (tables) { tables.putAll(incomplete.tables); } long bytesWritten = 0; boolean result = true; for (Table t : tables.values()) { bytesWritten += t.size; if (t.error != null) { result = false; } } this.bytesWritten = bytesWritten; this.result = result; } public interface TableUpdater { public Table update(Table t); } public interface TableIterator { public void next(Table t); } public void iterateTables(TableIterator ti) { synchronized (tables) { for (Table t : tables.values()) { ti.next(t); } } } public void updateTable(String name, TableUpdater tu) { synchronized (tables) { assert(tables.get(name) != null); tables.put(name, tu.update(tables.get(name))); } } public class Table { public final String name; public final String filename; public final long size; public final Exception error; private Table(String name, String filename) { this.name = name; this.filename = filename; size = 0; error = null; } public Table(Table t, long size, Exception error) { this.name = t.name; this.filename = t.filename; this.size = size; this.error = error; } } } public static synchronized Snapshot startSnapshot(long startTime, int hostId, int siteId, int partitionId, String path, String nonce, org.voltdb.catalog.Table tables[]) { final Snapshot s = new Snapshot(startTime, hostId, siteId, partitionId, path, nonce, tables); m_snapshots.add(s); if (m_snapshots.size() > m_maxStatusHistory) { Iterator<Snapshot> iter = m_snapshots.iterator(); iter.next(); iter.remove(); } return s; } public static synchronized void discardSnapshot(Snapshot s) { m_snapshots.remove(s); } public static synchronized Snapshot finishSnapshot(Snapshot incomplete) { boolean removed = m_snapshots.remove(incomplete); assert(removed); final Snapshot completed = new Snapshot(incomplete, System.currentTimeMillis()); m_snapshots.add(completed); return completed; } public static synchronized TreeSet<Snapshot> getSnapshotHistory() { return new TreeSet<Snapshot>(m_snapshots); } public static synchronized void clear() { m_snapshots.clear(); } }