InstanceId instanceId,
long timestamp,
int newPartitionCount)
throws IOException
{
final File f = new VoltFile(path, constructDigestFilenameForNonce(nonce, hostId));
if (f.exists()) {
if (!f.delete()) {
throw new IOException("Unable to write table list file " + f);
}
}
boolean success = false;
try {
final FileOutputStream fos = new FileOutputStream(f);
StringWriter sw = new StringWriter();
JSONStringer stringer = new JSONStringer();
try {
stringer.object();
stringer.key("version").value(1);
stringer.key("txnId").value(txnId);
stringer.key("timestamp").value(timestamp);
stringer.key("timestampString").value(SnapshotUtil.formatHumanReadableDate(timestamp));
stringer.key("newPartitionCount").value(newPartitionCount);
stringer.key("tables").array();
for (int ii = 0; ii < tables.size(); ii++) {
stringer.value(tables.get(ii).getTypeName());
}
stringer.endArray();
stringer.key("exportSequenceNumbers").array();
for (Map.Entry<String, Map<Integer, Pair<Long, Long>>> entry : exportSequenceNumbers.entrySet()) {
stringer.object();
stringer.key("exportTableName").value(entry.getKey());
stringer.key("sequenceNumberPerPartition").array();
for (Map.Entry<Integer, Pair<Long,Long>> sequenceNumber : entry.getValue().entrySet()) {
stringer.object();
stringer.key("partition").value(sequenceNumber.getKey());
//First value is the ack offset which matters for pauseless rejoin, but not persistence
stringer.key("exportSequenceNumber").value(sequenceNumber.getValue().getSecond());
stringer.endObject();
}
stringer.endArray();
stringer.endObject();
}
stringer.endArray();
stringer.key("partitionTransactionIds").object();
for (Map.Entry<Integer, Long> entry : partitionTransactionIds.entrySet()) {
stringer.key(entry.getKey().toString()).value(entry.getValue());
}
stringer.endObject();
stringer.key("catalogCRC").value(catalogCRC);
stringer.key("instanceId").value(instanceId.serializeToJSONObject());
stringer.endObject();
} catch (JSONException e) {
throw new IOException(e);
}
sw.append(stringer.toString());
final byte tableListBytes[] = sw.getBuffer().toString().getBytes("UTF-8");
final PureJavaCrc32 crc = new PureJavaCrc32();
crc.update(tableListBytes);
ByteBuffer fileBuffer = ByteBuffer.allocate(tableListBytes.length + 4);
fileBuffer.putInt((int)crc.getValue());
fileBuffer.put(tableListBytes);
fileBuffer.flip();
fos.getChannel().write(fileBuffer);
success = true;
return new Runnable() {
@Override
public void run() {
try {
fos.getChannel().force(true);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
};
} finally {
if (!success) {
f.delete();
}
}
}