use of java.nio.channels.SocketChannel in project quorrabot by GloriousEggroll.
the class WebSocketServer method run.
// Runnable IMPLEMENTATION /////////////////////////////////////////////////
public void run() {
synchronized (this) {
if (selectorthread != null) {
throw new IllegalStateException(getClass().getName() + " can only be started once.");
}
selectorthread = Thread.currentThread();
if (isclosed.get()) {
return;
}
}
selectorthread.setName("WebsocketSelector" + selectorthread.getId());
try {
server = ServerSocketChannel.open();
server.configureBlocking(false);
ServerSocket socket = server.socket();
socket.setReceiveBufferSize(WebSocketImpl.RCVBUF);
socket.bind(address);
selector = Selector.open();
server.register(selector, server.validOps());
} catch (IOException ex) {
handleFatal(null, ex);
return;
}
try {
while (!selectorthread.isInterrupted()) {
SelectionKey key = null;
WebSocketImpl conn = null;
try {
selector.select();
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> i = keys.iterator();
while (i.hasNext()) {
key = i.next();
if (!key.isValid()) {
// Object o = key.attachment();
continue;
}
if (key.isAcceptable()) {
if (!onConnect(key)) {
key.cancel();
continue;
}
SocketChannel channel = server.accept();
channel.configureBlocking(false);
WebSocketImpl w = wsf.createWebSocket(this, drafts, channel.socket());
w.key = channel.register(selector, SelectionKey.OP_READ, w);
w.channel = wsf.wrapChannel(channel, w.key);
i.remove();
allocateBuffers(w);
continue;
}
if (key.isReadable()) {
conn = (WebSocketImpl) key.attachment();
ByteBuffer buf = takeBuffer();
try {
if (SocketChannelIOHelper.read(buf, conn, conn.channel)) {
if (buf.hasRemaining()) {
conn.inQueue.put(buf);
queue(conn);
i.remove();
if (conn.channel instanceof WrappedByteChannel) {
if (((WrappedByteChannel) conn.channel).isNeedRead()) {
iqueue.add(conn);
}
}
} else {
pushBuffer(buf);
}
} else {
pushBuffer(buf);
}
} catch (IOException e) {
pushBuffer(buf);
throw e;
}
}
if (key.isWritable()) {
conn = (WebSocketImpl) key.attachment();
if (SocketChannelIOHelper.batch(conn, conn.channel)) {
if (key.isValid()) {
key.interestOps(SelectionKey.OP_READ);
}
}
}
}
while (!iqueue.isEmpty()) {
conn = iqueue.remove(0);
WrappedByteChannel c = ((WrappedByteChannel) conn.channel);
ByteBuffer buf = takeBuffer();
try {
if (SocketChannelIOHelper.readMore(buf, conn, c)) {
iqueue.add(conn);
}
if (buf.hasRemaining()) {
conn.inQueue.put(buf);
queue(conn);
} else {
pushBuffer(buf);
}
} catch (IOException e) {
pushBuffer(buf);
throw e;
}
}
} catch (CancelledKeyException e) {
// an other thread may cancel the key
} catch (ClosedByInterruptException e) {
// do the same stuff as when InterruptedException is thrown
return;
} catch (IOException ex) {
if (key != null) {
key.cancel();
}
handleIOException(key, conn, ex);
} catch (InterruptedException e) {
// FIXME controlled shutdown (e.g. take care of buffermanagement)
return;
}
}
} catch (RuntimeException e) {
// should hopefully never occur
handleFatal(null, e);
} finally {
if (decoders != null) {
for (WebSocketWorker w : decoders) {
w.interrupt();
}
}
if (server != null) {
try {
server.close();
} catch (IOException e) {
onError(null, e);
}
}
}
}
use of java.nio.channels.SocketChannel in project zm-mailbox by Zimbra.
the class ZimbraSocketAcceptor method accept.
@Override
protected NioSession accept(IoProcessor<NioSession> processor, ServerSocketChannel handle) throws Exception {
SelectionKey key = handle.keyFor(selector);
if ((key == null) || (!key.isValid()) || (!key.isAcceptable())) {
return null;
}
// accept the connection from the client
SocketChannel ch = handle.accept();
if (ch == null) {
return null;
}
return new NioSocketSession(this, processor, ch);
}
use of java.nio.channels.SocketChannel in project asterixdb by apache.
the class ReplicationManager method establishTxnLogReplicationHandshake.
/**
* Opens a new connection with Active remote replicas and starts a listen thread per connection.
*/
private void establishTxnLogReplicationHandshake() {
Map<String, SocketChannel> activeRemoteReplicasSockets = getActiveRemoteReplicasSockets();
logsRepSockets = new SocketChannel[activeRemoteReplicasSockets.size()];
int i = 0;
//start a listener thread per connection
for (Entry<String, SocketChannel> entry : activeRemoteReplicasSockets.entrySet()) {
logsRepSockets[i] = entry.getValue();
replicationListenerThreads.execute(new TxnLogsReplicationResponseListener(entry.getKey(), entry.getValue()));
i++;
}
/**
* establish log replication handshake
*/
ByteBuffer handshakeBuffer = ByteBuffer.allocate(ReplicationProtocol.REPLICATION_REQUEST_TYPE_SIZE).putInt(ReplicationProtocol.ReplicationRequestType.REPLICATE_LOG.ordinal());
handshakeBuffer.flip();
//send handshake request
for (SocketChannel replicaSocket : logsRepSockets) {
try {
NetworkingUtil.transferBufferToChannel(replicaSocket, handshakeBuffer);
} catch (IOException e) {
handleReplicationFailure(replicaSocket, e);
} finally {
handshakeBuffer.position(0);
}
}
}
use of java.nio.channels.SocketChannel in project asterixdb by apache.
the class ReplicationManager method processJob.
/**
* Processes the replication job based on its specifications
*
* @param job
* The replication job
* @param replicasSockets
* The remote replicas sockets to send the request to.
* @param requestBuffer
* The buffer to use to send the request.
* @throws IOException
*/
private void processJob(IReplicationJob job, Map<String, SocketChannel> replicasSockets, ByteBuffer requestBuffer) throws IOException {
try {
//all of the job's files belong to a single storage partition.
//get any of them to determine the partition from the file path.
String jobFile = job.getJobFiles().iterator().next();
IndexFileProperties indexFileRef = localResourceRepo.getIndexFileRef(jobFile);
if (!replicationStrategy.isMatch(indexFileRef.getDatasetId())) {
return;
}
int jobPartitionId = indexFileRef.getPartitionId();
ByteBuffer responseBuffer = null;
LSMIndexFileProperties asterixFileProperties = new LSMIndexFileProperties();
if (requestBuffer == null) {
requestBuffer = ByteBuffer.allocate(INITIAL_BUFFER_SIZE);
}
boolean isLSMComponentFile = job.getJobType() == ReplicationJobType.LSM_COMPONENT;
try {
//if there isn't already a connection, establish a new one
if (replicasSockets == null) {
replicasSockets = getActiveRemoteReplicasSockets();
}
int remainingFiles = job.getJobFiles().size();
if (job.getOperation() == ReplicationOperation.REPLICATE) {
//if the replication job is an LSM_COMPONENT, its properties are sent first, then its files.
ILSMIndexReplicationJob LSMComponentJob = null;
if (job.getJobType() == ReplicationJobType.LSM_COMPONENT) {
//send LSMComponent properties
LSMComponentJob = (ILSMIndexReplicationJob) job;
LSMComponentProperties lsmCompProp = new LSMComponentProperties(LSMComponentJob, nodeId);
requestBuffer = ReplicationProtocol.writeLSMComponentPropertiesRequest(lsmCompProp, requestBuffer);
sendRequest(replicasSockets, requestBuffer);
}
for (String filePath : job.getJobFiles()) {
remainingFiles--;
Path path = Paths.get(filePath);
if (Files.notExists(path)) {
LOGGER.log(Level.SEVERE, "File deleted before replication: " + filePath);
continue;
}
LOGGER.log(Level.INFO, "Replicating file: " + filePath);
//open file for reading
try (RandomAccessFile fromFile = new RandomAccessFile(filePath, "r");
FileChannel fileChannel = fromFile.getChannel()) {
long fileSize = fileChannel.size();
if (LSMComponentJob != null) {
/**
* since this is LSM_COMPONENT REPLICATE job, the job will contain
* only the component being replicated.
*/
ILSMDiskComponent diskComponent = LSMComponentJob.getLSMIndexOperationContext().getComponentsToBeReplicated().get(0);
long lsnOffset = LSMIndexUtil.getComponentFileLSNOffset(LSMComponentJob.getLSMIndex(), diskComponent, filePath);
asterixFileProperties.initialize(filePath, fileSize, nodeId, isLSMComponentFile, lsnOffset, remainingFiles == 0);
} else {
asterixFileProperties.initialize(filePath, fileSize, nodeId, isLSMComponentFile, -1L, remainingFiles == 0);
}
requestBuffer = ReplicationProtocol.writeFileReplicationRequest(requestBuffer, asterixFileProperties, ReplicationRequestType.REPLICATE_FILE);
Iterator<Map.Entry<String, SocketChannel>> iterator = replicasSockets.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, SocketChannel> entry = iterator.next();
//if the remote replica is not interested in this partition, skip it.
if (!replica2PartitionsMap.get(entry.getKey()).contains(jobPartitionId)) {
continue;
}
SocketChannel socketChannel = entry.getValue();
//transfer request header & file
try {
NetworkingUtil.transferBufferToChannel(socketChannel, requestBuffer);
NetworkingUtil.sendFile(fileChannel, socketChannel);
if (asterixFileProperties.requiresAck()) {
ReplicationRequestType responseType = waitForResponse(socketChannel, responseBuffer);
if (responseType != ReplicationRequestType.ACK) {
throw new IOException("Could not receive ACK from replica " + entry.getKey());
}
}
} catch (IOException e) {
handleReplicationFailure(socketChannel, e);
iterator.remove();
} finally {
requestBuffer.position(0);
}
}
}
}
} else if (job.getOperation() == ReplicationOperation.DELETE) {
for (String filePath : job.getJobFiles()) {
remainingFiles--;
asterixFileProperties.initialize(filePath, -1, nodeId, isLSMComponentFile, -1L, remainingFiles == 0);
ReplicationProtocol.writeFileReplicationRequest(requestBuffer, asterixFileProperties, ReplicationRequestType.DELETE_FILE);
Iterator<Map.Entry<String, SocketChannel>> iterator = replicasSockets.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, SocketChannel> entry = iterator.next();
//if the remote replica is not interested in this partition, skip it.
if (!replica2PartitionsMap.get(entry.getKey()).contains(jobPartitionId)) {
continue;
}
SocketChannel socketChannel = entry.getValue();
try {
sendRequest(replicasSockets, requestBuffer);
if (asterixFileProperties.requiresAck()) {
waitForResponse(socketChannel, responseBuffer);
}
} catch (IOException e) {
handleReplicationFailure(socketChannel, e);
iterator.remove();
} finally {
requestBuffer.position(0);
}
}
}
}
} finally {
//if sync, close sockets with replicas since they wont be reused
if (job.getExecutionType() == ReplicationExecutionType.SYNC) {
closeReplicaSockets(replicasSockets);
}
}
} finally {
exitReplicatedLSMComponent(job);
}
}
use of java.nio.channels.SocketChannel in project asterixdb by apache.
the class ReplicaStateChecker method call.
@Override
public Void call() throws Exception {
Thread.currentThread().setName("ReplicaConnector Thread");
long startTime = System.currentTimeMillis();
InetSocketAddress replicaAddress = replica.getAddress(asterixReplicationProperties);
while (true) {
try (SocketChannel connection = SocketChannel.open()) {
connection.configureBlocking(true);
connection.connect(new InetSocketAddress(replicaAddress.getHostString(), replicaAddress.getPort()));
ByteBuffer buffer = ReplicationProtocol.getGoodbyeBuffer();
connection.write(buffer);
replicationManager.updateReplicaState(replica.getId(), ReplicaState.ACTIVE, suspendReplication);
return null;
} catch (IOException | UnresolvedAddressException e) {
Thread.sleep(WAIT_TIME);
//check if connection to replica timed out
if (((System.currentTimeMillis() - startTime) / 1000) >= replicationTimeOut) {
replicationManager.updateReplicaState(replica.getId(), ReplicaState.DEAD, suspendReplication);
return null;
}
}
}
}
Aggregations