use of org.voltdb.client.ClientResponse in project voltdb by VoltDB.
the class InvocationDispatcher method useSnapshotCatalogToRestoreSnapshotSchema.
private final ClientResponseImpl useSnapshotCatalogToRestoreSnapshotSchema(final StoredProcedureInvocation task, final InvocationClientHandler handler, final Connection ccxn, final AuthUser user, OverrideCheck bypass) {
CatalogContext catalogContext = m_catalogContext.get();
if (!catalogContext.cluster.getUseddlschema()) {
return gracefulFailureResponse("Cannot restore catalog from snapshot when schema is set to catalog in the deployment.", task.clientHandle);
}
log.info("No schema found. Restoring schema and procedures from snapshot.");
try {
JSONObject jsObj = new JSONObject(task.getParams().getParam(0).toString());
final File catalogFH = getSnapshotCatalogFile(jsObj);
final byte[] catalog;
try {
catalog = MiscUtils.fileToBytes(catalogFH);
} catch (IOException e) {
log.warn("Unable to access catalog file " + catalogFH, e);
return unexpectedFailureResponse("Unable to access catalog file " + catalogFH, task.clientHandle);
}
final String dep = new String(catalogContext.getDeploymentBytes(), StandardCharsets.UTF_8);
final StoredProcedureInvocation catalogUpdateTask = new StoredProcedureInvocation();
catalogUpdateTask.setProcName("@UpdateApplicationCatalog");
catalogUpdateTask.setParams(catalog, dep);
//A connection with positive id will be thrown into live client statistics. The connection does not support stats.
//Thus make the connection id as a negative constant to skip the stats collection.
final SimpleClientResponseAdapter alternateAdapter = new SimpleClientResponseAdapter(ClientInterface.RESTORE_SCHEMAS_CID, "Empty database snapshot restore catalog update");
final InvocationClientHandler alternateHandler = new InvocationClientHandler() {
@Override
public boolean isAdmin() {
return handler.isAdmin();
}
@Override
public long connectionId() {
return ClientInterface.RESTORE_SCHEMAS_CID;
}
};
final long sourceHandle = task.clientHandle;
SimpleClientResponseAdapter.SyncCallback restoreCallback = new SimpleClientResponseAdapter.SyncCallback();
final ListenableFuture<ClientResponse> onRestoreComplete = restoreCallback.getResponseFuture();
onRestoreComplete.addListener(new Runnable() {
@Override
public void run() {
ClientResponse r;
try {
r = onRestoreComplete.get();
} catch (ExecutionException | InterruptedException e) {
VoltDB.crashLocalVoltDB("Should never happen", true, e);
return;
}
transmitResponseMessage(r, ccxn, sourceHandle);
}
}, CoreUtils.SAMETHREADEXECUTOR);
task.setClientHandle(alternateAdapter.registerCallback(restoreCallback));
SimpleClientResponseAdapter.SyncCallback catalogUpdateCallback = new SimpleClientResponseAdapter.SyncCallback();
final ListenableFuture<ClientResponse> onCatalogUpdateComplete = catalogUpdateCallback.getResponseFuture();
onCatalogUpdateComplete.addListener(new Runnable() {
@Override
public void run() {
ClientResponse r;
try {
r = onCatalogUpdateComplete.get();
} catch (ExecutionException | InterruptedException e) {
VoltDB.crashLocalVoltDB("Should never happen", true, e);
return;
}
if (r.getStatus() != ClientResponse.SUCCESS) {
transmitResponseMessage(r, ccxn, sourceHandle);
log.error("Received error response for updating catalog " + r.getStatusString());
return;
}
m_catalogContext.set(VoltDB.instance().getCatalogContext());
dispatch(task, alternateHandler, alternateAdapter, user, bypass, false);
}
}, CoreUtils.SAMETHREADEXECUTOR);
catalogUpdateTask.setClientHandle(alternateAdapter.registerCallback(catalogUpdateCallback));
VoltDB.instance().getClientInterface().bindAdapter(alternateAdapter, null);
// dispatch the catalog update
dispatchNTProcedure(alternateHandler, catalogUpdateTask, user, alternateAdapter, System.nanoTime(), false);
} catch (JSONException e) {
return unexpectedFailureResponse("Unable to parse parameters.", task.clientHandle);
}
return null;
}
use of org.voltdb.client.ClientResponse in project voltdb by VoltDB.
the class InvocationDispatcher method takeShutdownSaveSnapshot.
private final ClientResponseImpl takeShutdownSaveSnapshot(final StoredProcedureInvocation task, final InvocationClientHandler handler, final Connection ccxn, final AuthUser user, OverrideCheck bypass) {
// shutdown save snapshot is available for Pro edition only
if (!MiscUtils.isPro()) {
task.setParams();
return dispatch(task, handler, ccxn, user, bypass, false);
}
Object p0 = task.getParams().getParam(0);
final long zkTxnId;
if (p0 instanceof Long) {
zkTxnId = ((Long) p0).longValue();
} else if (p0 instanceof String) {
try {
zkTxnId = Long.parseLong((String) p0);
} catch (NumberFormatException e) {
return gracefulFailureResponse("Incorrect argument type", task.clientHandle);
}
} else {
return gracefulFailureResponse("Incorrect argument type", task.clientHandle);
}
VoltDBInterface voltdb = VoltDB.instance();
if (!voltdb.isPreparingShuttingdown()) {
log.warn("Ignoring shutdown save snapshot request as VoltDB is not shutting down");
return unexpectedFailureResponse("Ignoring shutdown save snapshot request as VoltDB is not shutting down", task.clientHandle);
}
final ZooKeeper zk = voltdb.getHostMessenger().getZK();
// network threads are blocked from making zookeeper calls
Future<Long> fut = voltdb.getSES(true).submit(new Callable<Long>() {
@Override
public Long call() {
try {
Stat stat = zk.exists(VoltZK.operationMode, false);
if (stat == null) {
VoltDB.crashLocalVoltDB("cluster operation mode zookeeper node does not exist");
return Long.MIN_VALUE;
}
return stat.getMzxid();
} catch (KeeperException | InterruptedException e) {
VoltDB.crashLocalVoltDB("Failed to stat the cluster operation zookeeper node", true, e);
return Long.MIN_VALUE;
}
}
});
try {
if (fut.get().longValue() != zkTxnId) {
return unexpectedFailureResponse("Internal error: cannot write a startup snapshot because the " + "current system state is not consistent with an orderly shutdown. " + "Please try \"voltadmin shutdown --save\" again.", task.clientHandle);
}
} catch (InterruptedException | ExecutionException e1) {
VoltDB.crashLocalVoltDB("Failed to stat the cluster operation zookeeper node", true, e1);
return null;
}
NodeSettings paths = m_catalogContext.get().getNodeSettings();
String data;
try {
data = new JSONStringer().object().keySymbolValuePair(SnapshotUtil.JSON_TERMINUS, zkTxnId).endObject().toString();
} catch (JSONException e) {
VoltDB.crashLocalVoltDB("Failed to create startup snapshot save command", true, e);
return null;
}
log.info("Saving startup snapshot");
consoleLog.info("Taking snapshot to save database contents");
final SimpleClientResponseAdapter alternateAdapter = new SimpleClientResponseAdapter(ClientInterface.SHUTDONW_SAVE_CID, "Blocking Startup Snapshot Save");
final InvocationClientHandler alternateHandler = new InvocationClientHandler() {
@Override
public boolean isAdmin() {
return handler.isAdmin();
}
@Override
public long connectionId() {
return ClientInterface.SHUTDONW_SAVE_CID;
}
};
final long sourceHandle = task.clientHandle;
task.setClientHandle(alternateAdapter.registerCallback(SimpleClientResponseAdapter.NULL_CALLBACK));
SnapshotUtil.SnapshotResponseHandler savCallback = new SnapshotUtil.SnapshotResponseHandler() {
@Override
public void handleResponse(ClientResponse r) {
if (r == null) {
String msg = "Snapshot save failed. The database is paused and the shutdown has been cancelled";
transmitResponseMessage(gracefulFailureResponse(msg, sourceHandle), ccxn, sourceHandle);
}
if (r.getStatus() != ClientResponse.SUCCESS) {
String msg = "Snapshot save failed: " + r.getStatusString() + ". The database is paused and the shutdown has been cancelled";
ClientResponseImpl resp = new ClientResponseImpl(ClientResponse.GRACEFUL_FAILURE, r.getResults(), msg, sourceHandle);
transmitResponseMessage(resp, ccxn, sourceHandle);
}
consoleLog.info("Snapshot taken successfully");
task.setParams();
dispatch(task, alternateHandler, alternateAdapter, user, bypass, false);
}
};
// network threads are blocked from making zookeeper calls
final byte[] guardContent = data.getBytes(StandardCharsets.UTF_8);
Future<Boolean> guardFuture = voltdb.getSES(true).submit(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
try {
ZKUtil.asyncMkdirs(zk, VoltZK.shutdown_save_guard, guardContent).get();
} catch (NodeExistsException itIsOk) {
return false;
} catch (InterruptedException | KeeperException e) {
VoltDB.crashLocalVoltDB("Failed to create shutdown save guard zookeeper node", true, e);
return false;
}
return true;
}
});
boolean created;
try {
created = guardFuture.get().booleanValue();
} catch (InterruptedException | ExecutionException e) {
VoltDB.crashLocalVoltDB("Failed to create shutdown save guard zookeeper node", true, e);
return null;
}
if (!created) {
return unexpectedFailureResponse("Internal error: detected concurrent invocations of \"voltadmin shutdown --save\"", task.clientHandle);
}
voltdb.getClientInterface().bindAdapter(alternateAdapter, null);
SnapshotUtil.requestSnapshot(sourceHandle, paths.resolve(paths.getSnapshoth()).toPath().toUri().toString(), SnapshotUtil.getShutdownSaveNonce(zkTxnId), true, SnapshotFormat.NATIVE, SnapshotPathType.SNAP_AUTO, data, savCallback, true);
return null;
}
use of org.voltdb.client.ClientResponse in project voltdb by VoltDB.
the class HealthMonitor method checkDRRole.
private void checkDRRole() {
SyncCallback cb = new SyncCallback();
if (getConnectionHadler().callProcedure(getInternalUser(), false, BatchTimeoutOverrideType.NO_TIMEOUT, cb, "@Statistics", "DRROLE", 0)) {
try {
cb.waitForResponse();
} catch (InterruptedException e) {
m_logger.error("Interrupted while retrieving cluster for DRROLE STATS", e);
return;
}
ClientResponse r = cb.getResponse();
if (r.getStatus() != ClientResponse.SUCCESS) {
// timeout could happen if hostdown
if (m_logger.isDebugEnabled()) {
m_logger.debug("Unable to retrieve DRROLE STATS: " + r.getStatusString());
}
return;
}
VoltTable result = r.getResults()[0];
while (result.advanceRow()) {
DrRoleType drRole = DrRoleType.fromValue(result.getString(DRRoleStats.CN_ROLE).toLowerCase());
DRRoleStats.State state = DRRoleStats.State.valueOf(result.getString(DRRoleStats.CN_STATE));
byte remoteCluster = (byte) result.getLong(DRRoleStats.CN_REMOTE_CLUSTER_ID);
if (m_logger.isDebugEnabled()) {
m_logger.debug("DRROLE stats: Role:" + drRole + " State:" + state + " Remote Cluster ID:" + remoteCluster);
}
if (drRole == DrRoleType.NONE) {
continue;
}
if (DRRoleStats.State.STOPPED == state) {
if (!m_snmpDRTrapSent.getOrDefault(remoteCluster, false)) {
m_snmpTrapSender.statistics(FaultFacility.DR, String.format("Database Replication ROLE: %s break with Remote Cluster %d.", drRole, remoteCluster));
m_snmpDRTrapSent.put(remoteCluster, true);
}
} else {
// reset
if (m_snmpDRTrapSent.getOrDefault(remoteCluster, false)) {
m_snmpDRTrapSent.put(remoteCluster, false);
}
}
}
} else {
m_logger.error("Unable to retrieve DRROLE STATS:: failed to invoke @Statistics DRROLE, 0.");
}
}
use of org.voltdb.client.ClientResponse in project voltdb by VoltDB.
the class TableHelper method fillTableWithBigintPkey.
/**
* Load random data into a partitioned table in VoltDB that has a bigint pkey.
*
* If the VoltTable indicates which column is its pkey, then it will use it, but otherwise it will
* assume the first column is the bigint pkey. Note, this works with other integer keys, but
* your keyspace is pretty small.
*
* If mb == 0, then maxRows is used. If maxRows == 0, then mb is used.
*
* @param table Table with or without schema metadata.
* @param mb Target RSS (approximate)
* @param maxRows Target maximum rows
* @param client To load with.
* @param offset Generated pkey values start here.
* @param jump Generated pkey values increment by this value.
* @throws Exception
*/
public void fillTableWithBigintPkey(VoltTable table, int mb, long maxRows, final Client client, long offset, long jump) throws Exception {
// make sure some kind of limit is set
assert ((maxRows > 0) || (mb > 0));
assert (maxRows >= 0);
assert (mb >= 0);
final int mbTarget = mb > 0 ? mb : Integer.MAX_VALUE;
if (maxRows == 0) {
maxRows = Long.MAX_VALUE;
}
System.out.printf("Filling table %s with rows starting with pkey id %d (every %d rows) until either RSS=%dmb or rowcount=%d\n", table.m_extraMetadata.name, offset, jump, mbTarget, maxRows);
// find the primary key, assume first col if not found
int pkeyColIndex = getBigintPrimaryKeyIndexIfExists(table);
if (pkeyColIndex == -1) {
pkeyColIndex = 0;
assert (table.getColumnType(0).isBackendIntegerType());
}
final AtomicLong rss = new AtomicLong(0);
ProcedureCallback insertCallback = new ProcedureCallback() {
@Override
public void clientCallback(ClientResponse clientResponse) throws Exception {
if (clientResponse.getStatus() != ClientResponse.SUCCESS) {
System.out.println("Error in loader callback:");
System.out.println(((ClientResponseImpl) clientResponse).toJSONString());
assert (false);
}
}
};
// update the rss value asynchronously
final AtomicBoolean rssThreadShouldStop = new AtomicBoolean(false);
Thread rssThread = new Thread() {
@Override
public void run() {
long tempRss = rss.get();
long rssPrev = tempRss;
while (!rssThreadShouldStop.get()) {
tempRss = MiscUtils.getMBRss(client);
if (tempRss != rssPrev) {
rssPrev = tempRss;
rss.set(tempRss);
System.out.printf("RSS=%dmb\n", tempRss);
// bail when done
if (tempRss > mbTarget) {
return;
}
}
try {
Thread.sleep(2000);
} catch (Exception e) {
}
}
}
};
// load rows until RSS goal is met (status print every 100k)
long i = offset;
long rows = 0;
rssThread.start();
final String insertProcName = table.m_extraMetadata.name.toUpperCase() + ".insert";
RandomRowMaker filler = createRandomRowMaker(table, Integer.MAX_VALUE, false, false);
while (rss.get() < mbTarget) {
Object[] row = filler.randomRow();
row[pkeyColIndex] = i;
client.callProcedure(insertCallback, insertProcName, row);
rows++;
if ((rows % 100000) == 0) {
System.out.printf("Loading 100000 rows. %d inserts sent (%d max id).\n", rows, i);
}
// if row limit is set, break if it's hit
if (rows >= maxRows) {
break;
}
i += jump;
}
rssThreadShouldStop.set(true);
client.drain();
rssThread.join();
System.out.printf("Filled table %s with %d rows and now RSS=%dmb\n", table.m_extraMetadata.name, rows, rss.get());
}
use of org.voltdb.client.ClientResponse in project voltdb by VoltDB.
the class CheckReplicaConsistency method checkForCorrectness.
/**
* Core benchmark code. Connect. Initialize. Run the loop. Cleanup. Print
* Results.
*
* @throws Exception
* if anything unexpected happens.
*/
public void checkForCorrectness(int ptnOrRep) throws Exception {
// compare state of all nodes
// we're employing "short circuit" read queries to get the data on the node
// exit with nonzero if there is an error
String z = config.servers;
String[] servers = z.split(",");
String[] tblSuffix_ = new String[] { "Ptn", "Rep" };
String sPtnOrRep = tblSuffix_[ptnOrRep];
// used for catalog check
int nTables = 0;
System.out.printf("Checking data across nodes, case: %s, servers: %s ...\n", sPtnOrRep, z);
ClientConfig clientConfig = new ClientConfig(config.user, config.password);
long[] counters = null;
long[] crcs = null;
int crcCount = -1;
for (int iServer = 0; iServer < servers.length; iServer++) {
String server = servers[iServer];
Client client = ClientFactory.createClient(clientConfig);
try {
client.createConnection(server);
} catch (Exception e) {
System.err.printf("Error connecting to node %d %s\n", iServer, server);
e.printStackTrace();
throw new RuntimeException();
}
ClientResponse resp = null;
if (iServer == 0) {
// get the partition count
resp = client.callProcedure("@Statistics", "PARTITIONCOUNT", 0);
if (resp.getStatus() != ClientResponse.SUCCESS) {
System.err.printf("Get partition count failed %s\n", resp.getStatusString());
throw new RuntimeException();
}
VoltTable[] tpc = resp.getResults();
nPartitions = 0;
while (tpc[0].advanceRow()) {
nPartitions = (int) tpc[0].getLong("PARTITION_COUNT");
}
System.out.printf("partition count: %d\n", nPartitions);
if (nPartitions < 2) {
System.err.printf("Less than 2 partitions\n", nPartitions);
throw new RuntimeException();
}
counters = new long[nPartitions];
crcs = new long[nPartitions];
}
if (nPartitions == 0) {
System.err.println("Zero partitions should not happen");
throw new RuntimeException();
}
// check the catalog by comparing the number of tables
resp = client.callProcedure("@Statistics", "TABLE", 0);
int nt = resp.getResults()[0].getRowCount();
System.out.printf("table count: %d\n", nt);
if (iServer == 0)
nTables = nt;
else {
if (nTables != nt) {
System.err.printf("TEST FAILED Catalog Table count mismatch %d != %d %s %s\n", nTables, nt, server, servers[0]);
System.exit(1);
//throw new RuntimeException();
} else {
System.out.printf("Catalog test passed\n");
}
}
for (int pid = 0; pid < nPartitions; pid++) {
// techniques ie. "short circuit" read.
try {
long counter = checkAndReturnCounter(server, client, pid, sPtnOrRep);
if (iServer == 0)
counters[pid] = counter;
else if (counters[pid] != counter) {
System.err.printf("TEST FAILED Node counter datacompare mismatch %d != %d %s %s\n", counter, counters[pid], server, servers[0]);
System.exit(1);
//throw new RuntimeException();
}
} catch (Exception e) {
System.err.printf("Exception received calling checkAndReturnCounter: server: %s pid: %d\n%s\n", server, pid, e.getMessage());
e.printStackTrace();
throw new RuntimeException();
}
// short circuit read techniques) and compare the crc's.
try {
long crc = returnCRC(server, client, pid, sPtnOrRep);
if (iServer == 0)
crcs[pid] = crc;
else if (crcs[pid] != crc) {
System.err.printf("TEST FAILED Node crc datacompare mismatch %d != %d %s %s\n", crc, crcs[pid], server, servers[0]);
System.exit(1);
//throw new RuntimeException();
}
} catch (Exception e) {
System.err.printf("Exception received calling returnCRC: server: %s pid: %d\n%s\n", server, pid, e.getMessage());
e.printStackTrace();
throw new RuntimeException();
}
}
client.drain();
client.close();
}
System.out.printf("case: %s All nodes of counter identical\n", sPtnOrRep);
}
Aggregations