use of org.voltcore.messaging.BinaryPayloadMessage in project voltdb by VoltDB.
the class OpsAgent method distributeOpsWork.
/**
* For OPS actions which run on every node, this method will distribute the
* necessary parameters to its peers on the other cluster nodes. Additionally, it will
* pre-check for excessive outstanding requests, and initialize the tracking and timeout of
* the new request. Subclasses of OpsAgent should use this when they need this service.
*/
protected void distributeOpsWork(PendingOpsRequest newRequest, JSONObject obj) throws Exception {
if (m_pendingRequests.size() > MAX_IN_FLIGHT_REQUESTS) {
/*
* Defensively check for an expired request not caught
* by timeout check. Should never happen.
*/
Iterator<Entry<Long, PendingOpsRequest>> iter = m_pendingRequests.entrySet().iterator();
final long now = System.currentTimeMillis();
boolean foundExpiredRequest = false;
while (iter.hasNext()) {
PendingOpsRequest por = iter.next().getValue();
if (now - por.startTime > OPS_COLLECTION_TIMEOUT * 2) {
iter.remove();
foundExpiredRequest = true;
}
}
if (!foundExpiredRequest) {
sendErrorResponse(newRequest.c, ClientResponse.GRACEFUL_FAILURE, "Too many pending stat requests", newRequest.clientData);
return;
}
}
final long requestId = m_nextRequestId++;
m_pendingRequests.put(requestId, newRequest);
m_es.schedule(new Runnable() {
@Override
public void run() {
checkForRequestTimeout(requestId);
}
}, OPS_COLLECTION_TIMEOUT, TimeUnit.MILLISECONDS);
// selector, subselector, interval filled in by parse...
obj.put("requestId", requestId);
obj.put("returnAddress", m_mailbox.getHSId());
int siteId = CoreUtils.getSiteIdFromHSId(m_mailbox.getHSId());
byte[] payloadBytes = CompressionService.compressBytes(obj.toString(4).getBytes("UTF-8"));
for (int hostId : m_messenger.getLiveHostIds()) {
long agentHsId = CoreUtils.getHSIdFromHostAndSite(hostId, siteId);
newRequest.expectedOpsResponses++;
BinaryPayloadMessage bpm = new BinaryPayloadMessage(new byte[] { JSON_PAYLOAD }, payloadBytes);
m_mailbox.send(agentHsId, bpm);
}
}
use of org.voltcore.messaging.BinaryPayloadMessage in project voltdb by VoltDB.
the class OpsAgent method handleMailboxMessage.
private void handleMailboxMessage(VoltMessage message) {
try {
if (message instanceof BinaryPayloadMessage) {
BinaryPayloadMessage bpm = (BinaryPayloadMessage) message;
byte[] payload = CompressionService.decompressBytes(bpm.m_payload);
if (bpm.m_metadata[0] == JSON_PAYLOAD) {
String jsonString = new String(payload, "UTF-8");
JSONObject obj = new JSONObject(jsonString);
//In early startup generate dummy responses
if (m_dummyMode) {
handleJSONMessageAsDummy(obj);
} else {
handleJSONMessage(obj);
}
} else if (bpm.m_metadata[0] == OPS_PAYLOAD) {
handleOpsResponse(payload, false);
} else if (bpm.m_metadata[0] == OPS_DUMMY) {
handleOpsResponse(payload, true);
}
}
} catch (Exception e) {
hostLog.error("Exception processing message in OpsAgent for " + m_name + ": " + message, e);
} catch (Throwable t) {
//Handle throwable because otherwise the future swallows up other exceptions
VoltDB.crashLocalVoltDB("Exception processing message in OpsAgent for " + m_name + ": " + message, true, t);
}
}
use of org.voltcore.messaging.BinaryPayloadMessage in project voltdb by VoltDB.
the class ExportDataSource method forwardAckToOtherReplicas.
private void forwardAckToOtherReplicas(long uso) {
if (m_runEveryWhere && m_replicaRunning) {
//we dont forward if we are running as replica in replicated export
return;
}
Pair<Mailbox, ImmutableList<Long>> p = m_ackMailboxRefs.get();
Mailbox mbx = p.getFirst();
if (mbx != null && p.getSecond().size() > 0) {
// partition:int(4) + length:int(4) +
// signaturesBytes.length + ackUSO:long(8) + 2 bytes for runEverywhere or not.
final int msgLen = 4 + 4 + m_signatureBytes.length + 8 + 2;
ByteBuffer buf = ByteBuffer.allocate(msgLen);
buf.putInt(m_partitionId);
buf.putInt(m_signatureBytes.length);
buf.put(m_signatureBytes);
buf.putLong(uso);
buf.putShort((m_runEveryWhere ? (short) 1 : (short) 0));
BinaryPayloadMessage bpm = new BinaryPayloadMessage(new byte[0], buf.array());
for (Long siteId : p.getSecond()) {
mbx.send(siteId, bpm);
}
}
}
use of org.voltcore.messaging.BinaryPayloadMessage in project voltdb by VoltDB.
the class ExportGeneration method createAndRegisterAckMailboxes.
private void createAndRegisterAckMailboxes(final Set<Integer> localPartitions, HostMessenger messenger) {
m_mailboxesZKPath = VoltZK.exportGenerations + "/" + m_timestamp + "/" + "mailboxes";
m_mbox = new LocalMailbox(messenger) {
@Override
public void deliver(VoltMessage message) {
if (message instanceof BinaryPayloadMessage) {
BinaryPayloadMessage bpm = (BinaryPayloadMessage) message;
ByteBuffer buf = ByteBuffer.wrap(bpm.m_payload);
final int partition = buf.getInt();
final int length = buf.getInt();
byte[] stringBytes = new byte[length];
buf.get(stringBytes);
String signature = new String(stringBytes, Constants.UTF8ENCODING);
final long ackUSO = buf.getLong();
final boolean runEveryWhere = (buf.getShort() == (short) 1);
final Map<String, ExportDataSource> partitionSources = m_dataSourcesByPartition.get(partition);
if (partitionSources == null) {
exportLog.error("Received an export ack for partition " + partition + " which does not exist on this node, partitions = " + m_dataSourcesByPartition);
return;
}
final ExportDataSource eds = partitionSources.get(signature);
if (eds == null) {
exportLog.warn("Received an export ack for partition " + partition + " source signature " + signature + " which does not exist on this node, sources = " + partitionSources);
return;
}
try {
eds.ack(ackUSO, runEveryWhere);
} catch (RejectedExecutionException ignoreIt) {
// ignore it: as it is already shutdown
}
} else {
exportLog.error("Receive unexpected message " + message + " in export subsystem");
}
}
};
messenger.createMailbox(null, m_mbox);
for (Integer partition : localPartitions) {
final String partitionDN = m_mailboxesZKPath + "/" + partition;
ZKUtil.asyncMkdirs(messenger.getZK(), partitionDN);
ZKUtil.StringCallback cb = new ZKUtil.StringCallback();
messenger.getZK().create(partitionDN + "/" + m_mbox.getHSId(), null, Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, cb, null);
}
ListenableFuture<?> fut = m_childUpdatingThread.submit(new Runnable() {
@Override
public void run() {
List<Pair<Integer, ZKUtil.ChildrenCallback>> callbacks = new ArrayList<Pair<Integer, ZKUtil.ChildrenCallback>>();
for (Integer partition : localPartitions) {
ZKUtil.ChildrenCallback callback = new ZKUtil.ChildrenCallback();
messenger.getZK().getChildren(m_mailboxesZKPath + "/" + partition, constructMailboxChildWatcher(messenger), callback, null);
callbacks.add(Pair.of(partition, callback));
}
for (Pair<Integer, ZKUtil.ChildrenCallback> p : callbacks) {
final Integer partition = p.getFirst();
List<String> children = null;
try {
children = p.getSecond().getChildren();
} catch (InterruptedException e) {
Throwables.propagate(e);
} catch (KeeperException e) {
Throwables.propagate(e);
}
ImmutableList.Builder<Long> mailboxes = ImmutableList.builder();
for (String child : children) {
if (child.equals(Long.toString(m_mbox.getHSId())))
continue;
mailboxes.add(Long.valueOf(child));
}
ImmutableList<Long> mailboxHsids = mailboxes.build();
for (ExportDataSource eds : m_dataSourcesByPartition.get(partition).values()) {
eds.updateAckMailboxes(Pair.of(m_mbox, mailboxHsids));
}
}
}
});
try {
fut.get();
} catch (Throwable t) {
Throwables.propagate(t);
}
}
use of org.voltcore.messaging.BinaryPayloadMessage in project voltdb by VoltDB.
the class TestCartographer method testSPMasterChange.
@Test
public void testSPMasterChange() throws Exception {
ZooKeeper zk = getClient(0);
VoltZK.createPersistentZKNodes(zk);
LeaderCache spwriter = new LeaderCache(zk, VoltZK.iv2masters);
HostMessenger hm = mock(HostMessenger.class);
when(hm.getZK()).thenReturn(m_messengers.get(0).getZK());
Cartographer dut = new Cartographer(hm, 0, false);
// Startup partitions
spwriter.start(true);
spwriter.put(0, 0l);
verify(hm, timeout(10000)).send(anyLong(), any(VoltMessage.class));
reset(hm);
spwriter.put(1, 1l);
verify(hm, timeout(10000)).send(anyLong(), any(VoltMessage.class));
reset(hm);
spwriter.put(2, 2l);
verify(hm, timeout(10000)).send(anyLong(), any(VoltMessage.class));
reset(hm);
// now change master for part 0
spwriter.put(0, 3l);
ArgumentCaptor<Long> hsIdCaptor = ArgumentCaptor.forClass(Long.class);
ArgumentCaptor<BinaryPayloadMessage> bpmCaptor = ArgumentCaptor.forClass(BinaryPayloadMessage.class);
verify(hm, timeout(10000)).send(hsIdCaptor.capture(), bpmCaptor.capture());
JSONObject jsObj = new JSONObject(new String(bpmCaptor.getValue().m_payload, "UTF-8"));
System.out.println("BPM: " + jsObj.toString());
final int partitionId = jsObj.getInt(Cartographer.JSON_PARTITION_ID);
final long initiatorHSId = jsObj.getLong(Cartographer.JSON_INITIATOR_HSID);
assertEquals(0, partitionId);
assertEquals(3, initiatorHSId);
spwriter.shutdown();
}
Aggregations