use of com.couchbase.client.core.deps.io.netty.buffer.ByteBuf in project couchbase-jvm-clients by couchbase.
the class FeatureNegotiatingHandler method extractFeaturesFromBody.
/**
* Helper method to safely extract the negotiated server features from the
* body of the memcache payload.
*
* @param response the response to extract from.
* @return the list of server features, may be empty but never null.
*/
private Set<ServerFeature> extractFeaturesFromBody(final ByteBuf response) {
Optional<ByteBuf> body = MemcacheProtocol.body(response);
Set<ServerFeature> negotiated = EnumSet.noneOf(ServerFeature.class);
List<ServerFeature> unsolicited = new ArrayList<>();
if (!body.isPresent()) {
return negotiated;
}
while (body.get().isReadable()) {
try {
short featureRaw = body.get().readShort();
ServerFeature feature = ServerFeature.from(featureRaw);
if (features.contains(feature)) {
negotiated.add(feature);
} else {
unsolicited.add(feature);
}
} catch (Exception ex) {
interceptedConnectPromise.tryFailure(new CouchbaseException("Error while parsing negotiated server features.", ex));
}
}
if (!unsolicited.isEmpty()) {
endpointContext.environment().eventBus().publish(new UnsolicitedFeaturesReturnedEvent(ioContext, unsolicited));
}
return negotiated;
}
use of com.couchbase.client.core.deps.io.netty.buffer.ByteBuf in project couchbase-jvm-clients by couchbase.
the class QueryRequest method encode.
@Override
public FullHttpRequest encode() {
ByteBuf content = Unpooled.wrappedBuffer(query);
FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, URI, content);
request.headers().set(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON);
request.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
request.headers().set(HttpHeaderNames.USER_AGENT, context().environment().userAgent().formattedLong());
authenticator.authHttpRequest(serviceType(), request);
return request;
}
use of com.couchbase.client.core.deps.io.netty.buffer.ByteBuf in project couchbase-jvm-clients by couchbase.
the class SubdocMutateRequest method decode.
@Override
public SubdocMutateResponse decode(final ByteBuf response, KeyValueChannelContext ctx) {
Optional<ByteBuf> maybeBody = body(response);
short rawOverallStatus = status(response);
ResponseStatus overallStatus = decodeStatus(response);
Optional<CouchbaseException> error = Optional.empty();
SubDocumentField[] values = null;
if (maybeBody.isPresent()) {
ByteBuf body = maybeBody.get();
// If there's a multi-mutation failure we only get the first failure back
if (rawOverallStatus == Status.SUBDOC_MULTI_PATH_FAILURE.status() || rawOverallStatus == Status.SUBDOC_MULTI_PATH_FAILURE_DELETED.status()) {
byte index = body.readByte();
short opStatusRaw = body.readShort();
SubDocumentOpResponseStatus opStatus = decodeSubDocumentStatus(opStatusRaw);
Command c = commands.get(index);
error = Optional.of(mapSubDocumentError(this, opStatus, c.path, c.originalIndex));
values = new SubDocumentField[0];
} else if (overallStatus.success()) {
// "For successful multi mutations, there will be zero or more results; each of the results containing a value."
values = new SubDocumentField[commands.size()];
// Check we can read index (1 byte) and status (2 bytes), else we're done
int INDEX_PLUS_STATUS_FIELDS_BYTES = 3;
while (body.isReadable(INDEX_PLUS_STATUS_FIELDS_BYTES)) {
byte index = body.readByte();
Command command = commands.get(index);
// "Status of the mutation. If the status indicates success, the next two fields are applicable. If it is an
// error then the result has been fully read"
short statusRaw = body.readShort();
SubDocumentOpResponseStatus status = decodeSubDocumentStatus(statusRaw);
if (status != SubDocumentOpResponseStatus.SUCCESS) {
CouchbaseException err = mapSubDocumentError(this, status, command.path, command.originalIndex);
SubDocumentField op = new SubDocumentField(status, Optional.of(err), Bytes.EMPTY_BYTE_ARRAY, command.path, command.type);
values[command.originalIndex] = op;
} else {
int valueLength = body.readInt();
byte[] value = new byte[valueLength];
body.readBytes(value, 0, valueLength);
SubDocumentField op = new SubDocumentField(status, Optional.empty(), value, command.path, command.type);
values[command.originalIndex] = op;
}
}
}
}
if (values == null) {
values = new SubDocumentField[0];
}
// Handle any document-level failures here
if (rawOverallStatus == Status.SUBDOC_DOC_NOT_JSON.status()) {
SubDocumentErrorContext e = createSubDocumentExceptionContext(SubDocumentOpResponseStatus.DOC_NOT_JSON);
error = Optional.of(new DocumentNotJsonException(e));
} else if (rawOverallStatus == Status.SUBDOC_DOC_TOO_DEEP.status()) {
SubDocumentErrorContext e = createSubDocumentExceptionContext(SubDocumentOpResponseStatus.DOC_TOO_DEEP);
error = Optional.of(new DocumentTooDeepException(e));
} else if (rawOverallStatus == Status.SUBDOC_XATTR_INVALID_KEY_COMBO.status()) {
SubDocumentErrorContext e = createSubDocumentExceptionContext(SubDocumentOpResponseStatus.XATTR_INVALID_KEY_COMBO);
error = Optional.of(new XattrInvalidKeyComboException(e));
} else if (rawOverallStatus == Status.SUBDOC_CAN_ONLY_REVIVE_DELETED_DOCUMENTS.status()) {
SubDocumentErrorContext e = createSubDocumentExceptionContext(SubDocumentOpResponseStatus.CAN_ONLY_REVIVE_DELETED_DOCUMENTS);
error = Optional.of(new DocumentAlreadyAliveException(e));
}
// Do not handle SUBDOC_INVALID_COMBO here, it indicates a client-side bug
return new SubdocMutateResponse(overallStatus, error, values, cas(response), extractToken(ctx.mutationTokensEnabled(), partition(), response, ctx.bucket().get()));
}
use of com.couchbase.client.core.deps.io.netty.buffer.ByteBuf in project couchbase-jvm-clients by couchbase.
the class BaseEndpointIntegrationTest method startLocalServer.
private LocalServerController startLocalServer(final DefaultEventLoopGroup eventLoopGroup) {
final LocalServerController localServerController = new LocalServerController();
ServerBootstrap bootstrap = new ServerBootstrap().group(eventLoopGroup).localAddress(new LocalAddress("server")).childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) {
ch.pipeline().addLast(new SimpleChannelInboundHandler<ByteBuf>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) {
}
@Override
public void channelActive(ChannelHandlerContext ctx) {
localServerController.channel.set(ctx.channel());
localServerController.connectAttempts.incrementAndGet();
ctx.fireChannelActive();
}
});
}
}).channel(LocalServerChannel.class);
bootstrap.bind().awaitUninterruptibly();
return localServerController;
}
use of com.couchbase.client.core.deps.io.netty.buffer.ByteBuf in project couchbase-jvm-clients by couchbase.
the class MemcacheProtocolDecodeHandlerTest method writeAsRandomChunks.
/**
* Helper method to randomly chunk up the source until the channel emits a new message.
*
* @param channel the channel to write into.
* @param source the source buffer.
*/
private static void writeAsRandomChunks(final EmbeddedChannel channel, final ByteBuf source) {
while (channel.inboundMessages().isEmpty()) {
int chunkSize = new Random().nextInt(source.readableBytes() + 1);
ByteBuf toWrite = source.readBytes(chunkSize);
channel.writeOneInbound(toWrite);
}
}
Aggregations