use of org.voltdb.client.ProcedureCallback in project voltdb by VoltDB.
the class SnapshotDaemon method initiateSnapshotScan.
/**
* Invoke the @SnapshotScan system procedure to discover
* snapshots on disk that are managed by this daemon
* @return
*/
private void initiateSnapshotScan() {
m_lastSysprocInvocation = System.currentTimeMillis();
Object[] params = new Object[1];
params[0] = m_path;
setState(State.SCANNING);
long handle = m_nextCallbackHandle++;
m_procedureCallbacks.put(handle, new ProcedureCallback() {
@Override
public void clientCallback(final ClientResponse clientResponse) throws Exception {
processClientResponsePrivate(clientResponse);
}
});
SNAP_LOG.info("Initiating snapshot scan of " + m_path);
m_initiator.initiateSnapshotDaemonWork("@SnapshotScan", handle, params);
}
use of org.voltdb.client.ProcedureCallback in project voltdb by VoltDB.
the class SnapshotDaemon method scanTruncationSnapshots.
/*
* Search for truncation snapshots, after a failure there may be
* ones we don't know about, there may be ones from a previous instance etc.
* Do this every five minutes as an easy hack to make sure we don't leak them.
* Next time groom is called it will delete the old ones after a success.
*/
private void scanTruncationSnapshots() {
if (m_truncationSnapshotPath == null) {
try {
m_truncationSnapshotPath = new String(m_zk.getData(VoltZK.test_scan_path, false, null), "UTF-8");
} catch (Exception e) {
return;
}
}
Object[] params = new Object[1];
params[0] = m_truncationSnapshotPath;
long handle = m_nextCallbackHandle++;
m_procedureCallbacks.put(handle, new ProcedureCallback() {
@Override
public void clientCallback(final ClientResponse clientResponse) throws Exception {
if (clientResponse.getStatus() != ClientResponse.SUCCESS) {
SNAP_LOG.error(clientResponse.getStatusString());
return;
}
final VoltTable[] results = clientResponse.getResults();
if (results.length == 1) {
final VoltTable result = results[0];
boolean advanced = result.advanceRow();
assert (advanced);
assert (result.getColumnCount() == 1);
assert (result.getColumnType(0) == VoltType.STRING);
loggingLog.error("Snapshot scan failed with failure response: " + result.getString("ERR_MSG"));
return;
}
assert (results.length == 3);
final VoltTable snapshots = results[0];
assert (snapshots.getColumnCount() == 10);
TreeMap<Long, TruncationSnapshotAttempt> foundSnapshots = new TreeMap<Long, TruncationSnapshotAttempt>();
while (snapshots.advanceRow()) {
final String path = snapshots.getString("PATH");
final String pathType = snapshots.getString("PATHTYPE");
final String nonce = snapshots.getString("NONCE");
final Long txnId = snapshots.getLong("TXNID");
TruncationSnapshotAttempt snapshotAttempt = new TruncationSnapshotAttempt();
snapshotAttempt.path = path;
snapshotAttempt.pathType = pathType;
snapshotAttempt.nonce = nonce;
foundSnapshots.put(txnId, snapshotAttempt);
}
for (Map.Entry<Long, TruncationSnapshotAttempt> entry : foundSnapshots.entrySet()) {
if (!m_truncationSnapshotAttempts.containsKey(entry.getKey())) {
loggingLog.info("Truncation snapshot scan discovered new snapshot txnid " + entry.getKey() + " path " + entry.getValue().path + " nonce " + entry.getValue().nonce);
m_truncationSnapshotAttempts.put(entry.getKey(), entry.getValue());
}
}
}
});
m_initiator.initiateSnapshotDaemonWork("@SnapshotScan", handle, params);
}
use of org.voltdb.client.ProcedureCallback in project voltdb by VoltDB.
the class SnapshotDaemon method deleteExtraSnapshots.
/**
* Check if there are extra snapshots and initiate deletion
* @return
*/
private void deleteExtraSnapshots() {
if (m_snapshots.size() <= m_retain) {
setState(State.WAITING);
} else {
m_lastSysprocInvocation = System.currentTimeMillis();
setState(State.DELETING);
final int numberToDelete = m_snapshots.size() - m_retain;
String[] pathsToDelete = new String[numberToDelete];
String[] noncesToDelete = new String[numberToDelete];
for (int ii = 0; ii < numberToDelete; ii++) {
final Snapshot s = m_snapshots.poll();
pathsToDelete[ii] = s.path;
noncesToDelete[ii] = s.nonce;
SNAP_LOG.info("Snapshot daemon deleting " + s.nonce);
}
Object[] params = new Object[] { pathsToDelete, noncesToDelete, SnapshotPathType.SNAP_AUTO.toString() };
long handle = m_nextCallbackHandle++;
m_procedureCallbacks.put(handle, new ProcedureCallback() {
@Override
public void clientCallback(final ClientResponse clientResponse) throws Exception {
processClientResponsePrivate(clientResponse);
}
});
m_initiator.initiateSnapshotDaemonWork("@SnapshotDelete", handle, params);
}
}
use of org.voltdb.client.ProcedureCallback in project voltdb by VoltDB.
the class SnapshotDaemon method scheduleSnapshotForLater.
/*
* Schedule a user snapshot request for later since the database was busy.
* Continue doing this as long as the error response returned by the DB is snapshot in progress.
* Since the snapshot is being scheduled for later we will send an immediate response to the client
* via ZK relay.
*/
private void scheduleSnapshotForLater(final String requestObj, final String requestId, final boolean isFirstAttempt) throws Exception {
/*
* Only need to send the queue response the first time we attempt to schedule the snapshot
* for later. It may be necessary to reschedule via this function multiple times.
*/
if (isFirstAttempt) {
SNAP_LOG.info("A user snapshot request could not be immediately fulfilled and will be reattempted later");
/*
* Construct a result to send to the client right now via ZK
* saying we queued it to run later
*/
VoltTable result = SnapshotUtil.constructNodeResultsTable();
result.addRow(-1, CoreUtils.getHostnameOrAddress(), "", "SUCCESS", "SNAPSHOT REQUEST QUEUED");
final ClientResponseImpl queuedResponse = new ClientResponseImpl(ClientResponseImpl.SUCCESS, new VoltTable[] { result }, "Snapshot request could not be fulfilled because a snapshot " + "is in progress. It was queued for execution", 0);
ByteBuffer buf = ByteBuffer.allocate(queuedResponse.getSerializedSize());
m_zk.create(VoltZK.user_snapshot_response + requestId, queuedResponse.flattenToBuffer(buf).array(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
/*
* Now queue the request for later
*/
final Runnable r = new Runnable() {
@Override
public void run() {
try {
/*
* Construct a callback to handle the response to the
* @SnapshotSave invocation that will reattempt the user snapshot
*/
final long handle = m_nextCallbackHandle++;
m_procedureCallbacks.put(handle, new ProcedureCallback() {
@Override
public void clientCallback(ClientResponse clientResponse) {
m_lastInitiationTs = null;
try {
/*
* If there is an error then we are done
* attempting this user snapshot. The params must be bad
* or things are broken.
*/
if (clientResponse.getStatus() != ClientResponse.SUCCESS) {
SNAP_LOG.error(clientResponse.getStatusString());
//Reset the watch, in case this is recoverable
userSnapshotRequestExistenceCheck(true);
return;
}
VoltTable[] results = clientResponse.getResults();
//Do this check to avoid an NPE
if (results == null || results.length == 0 || results[0].getRowCount() < 1) {
SNAP_LOG.error("Queued user snapshot request reattempt received an unexpected response" + " and will not be reattempted. The client response is (status: " + clientResponse.getStatus() + " " + clientResponse.getStatusString() + " result: " + (results != null && results.length > 0 ? results[0] : "null") + ")");
/*
* Don't think this should happen, reset the watch to allow later requests
*/
userSnapshotRequestExistenceCheck(true);
return;
}
VoltTable result = results[0];
boolean snapshotInProgress = false;
boolean haveFailure = false;
while (result.advanceRow()) {
if (result.getString("RESULT").equals("FAILURE")) {
if (result.getString("ERR_MSG").equals("SNAPSHOT IN PROGRESS")) {
snapshotInProgress = true;
} else {
haveFailure = true;
}
}
}
/*
* If a snapshot was in progress, reattempt later, otherwise,
* if there was a failure, abort the attempt and log.
*/
if (snapshotInProgress) {
SNAP_LOG.info("Queued user snapshot was reattempted, but a snapshot was " + " still in progress. It will be reattempted.");
//Turtles all the way down
scheduleSnapshotForLater(requestObj, requestId, false);
} else if (haveFailure) {
SNAP_LOG.info("Queued user snapshot was attempted, but there was a failure.");
try {
ClientResponseImpl rimpl = (ClientResponseImpl) clientResponse;
saveResponseToZKAndReset(requestId, rimpl);
} catch (NodeExistsException e) {
// used to pass null as request ID to avoid this check if the request ID
// already existed, this gives us the same behavior with a pre-existing
// request ID
}
//Log the details of the failure, after resetting the watch in case of some odd NPE
result.resetRowPosition();
SNAP_LOG.info(result);
} else {
try {
SNAP_LOG.debug("Queued user snapshot was successfully requested, saving to path " + VoltZK.user_snapshot_response + requestId);
/*
* Snapshot was started no problem, reset the watch for new requests
*/
ClientResponseImpl rimpl = (ClientResponseImpl) clientResponse;
saveResponseToZKAndReset(requestId, rimpl);
} catch (NodeExistsException e) {
// used to pass null as request ID to avoid this check if the request ID
// already existed, this gives us the same behavior with a pre-existing
// request ID
}
return;
}
} catch (Exception e) {
SNAP_LOG.error("Error processing procedure callback for user snapshot", e);
try {
userSnapshotRequestExistenceCheck(true);
} catch (Exception e1) {
VoltDB.crashLocalVoltDB("Error resetting watch for user snapshot requests", true, e1);
}
}
}
});
initiateSnapshotSave(handle, new Object[] { requestObj }, false);
} catch (Exception e) {
try {
userSnapshotRequestExistenceCheck(true);
} catch (Exception e1) {
VoltDB.crashLocalVoltDB("Error checking for existence of user snapshots", true, e1);
}
}
}
};
m_es.schedule(r, m_userSnapshotRetryInterval, TimeUnit.SECONDS);
}
use of org.voltdb.client.ProcedureCallback in project voltdb by VoltDB.
the class PerPartitionTable method reinsertFailed.
private void reinsertFailed(List<VoltBulkLoaderRow> rows) throws Exception {
VoltTable tmpTable = new VoltTable(m_columnInfo);
for (final VoltBulkLoaderRow row : rows) {
// previously successful.
try {
Object[] row_args = new Object[row.m_rowData.length];
for (int i = 0; i < row_args.length; i++) {
final VoltType type = m_columnTypes[i];
row_args[i] = ParameterConverter.tryToMakeCompatible(type.classFromType(), row.m_rowData[i]);
}
tmpTable.addRow(row_args);
} catch (VoltTypeException ex) {
// should have caught this
continue;
}
ProcedureCallback callback = new ProcedureCallback() {
@Override
public void clientCallback(ClientResponse response) throws Exception {
row.m_loader.m_loaderCompletedCnt.incrementAndGet();
row.m_loader.m_outstandingRowCount.decrementAndGet();
//one insert at a time callback
if (response.getStatus() != ClientResponse.SUCCESS) {
row.m_loader.m_notificationCallBack.failureCallback(row.m_rowHandle, row.m_rowData, response);
}
}
};
loadTable(callback, tmpTable);
}
}
Aggregations