private void handleEnrollInTransaction(Operation request) { String serviceSelfLink = this.service.getSelfLink(); if (Action.POST == request.getAction()) { ServiceDocument body = request.getBody(this.service.getStateType()); if (body.documentSelfLink == null) { body.documentSelfLink = UUID.randomUUID().toString(); request.setBody(body); } serviceSelfLink = UriUtils.buildUriPath(serviceSelfLink, body.documentSelfLink); } long servicePreviousVersion = this.service.getState(request) == null ? -1 : this.service.getState(request).documentVersion; Operation enrollRequest = SimpleTransactionService.TxUtils.buildEnrollRequest( this.service.getHost(), request.getTransactionId(), serviceSelfLink, request.getAction(), servicePreviousVersion) .setCompletion( (o, e) -> { if (e != null) { request.fail(e); return; } this.service .getOperationProcessingChain() .resumeProcessingRequest(request, this); }); this.service.sendRequest(enrollRequest); }
private boolean validateTransactionConflictsAndMarkState( Operation request, ServiceDocument currentState) { if (currentState == null) { return false; } String requestTransactionId = request.getTransactionId(); String currentStateTransactionId = currentState.documentTransactionId; if (request.getAction() == Action.GET) { if (requestTransactionId == null) { // non-transactional read if (currentStateTransactionId == null) { return false; } else { logTransactionConflict(request, currentState); return true; } } else { // transactional read if (currentStateTransactionId == null) { logTransactionUpdate(buildLogTransactionUpdateMsg(request, currentState)); currentState.documentTransactionId = requestTransactionId; return false; } else { if (requestTransactionId.equals(currentStateTransactionId)) { return false; } else { logTransactionConflict(request, currentState); return true; } } } } else { if (requestTransactionId == null) { // non-transactional write if (currentStateTransactionId == null || request.hasPragmaDirective(PRAGMA_DIRECTIVE_DELETE_ON_TRANSACTION_END)) { return false; } else { logTransactionConflict(request, currentState); return true; } } else { // transactional write if (currentStateTransactionId == null) { logTransactionUpdate(buildLogTransactionUpdateMsg(request, currentState)); currentState.documentTransactionId = requestTransactionId; return false; } else { if (requestTransactionId.equals(currentStateTransactionId)) { return false; } else { logTransactionConflict(request, currentState); return true; } } } } }
@Override public void handlePut(Operation op) { if (!op.hasBody()) { op.fail(new IllegalArgumentException("body is required")); return; } RoleState newState = op.getBody(RoleState.class); if (!validate(op, newState)) { return; } RoleState currentState = getState(op); ServiceDocumentDescription documentDescription = this.getDocumentTemplate().documentDescription; if (ServiceDocument.equals(documentDescription, currentState, newState)) { op.setStatusCode(Operation.STATUS_CODE_NOT_MODIFIED); } else { setState(op, newState); } op.complete(); }
private void handleClearTransaction( Operation request, ServiceDocument currentState, ClearTransactionRequest clearTransactionRequest) { if (currentState == null) { request.complete(); return; } if (!request.getTransactionId().equals(currentState.documentTransactionId)) { if (clearTransactionRequest.transactionOutcome == TransactionOutcome.COMMIT) { String warning = String.format( "Request to clear transaction %s from service %s but current transaction is: %s", request.getTransactionId(), this.service.getSelfLink(), currentState.documentTransactionId); this.service.getHost().log(Level.WARNING, warning); } request.complete(); return; } if (clearTransactionRequest.transactionOutcome == TransactionOutcome.ABORT && clearTransactionRequest.isUpdated) { // restore previous state URI previousStateQueryUri = UriUtils.buildDocumentQueryUri( this.service.getHost(), this.service.getSelfLink(), false, false, ServiceOption.PERSISTENCE); previousStateQueryUri = UriUtils.appendQueryParam( previousStateQueryUri, ServiceDocument.FIELD_NAME_VERSION, Long.toString(clearTransactionRequest.originalVersion)); Operation previousStateGet = Operation.createGet(previousStateQueryUri) .setCompletion( (o, e) -> { if (e != null) { request.fail(e); return; } ServiceDocument previousState = o.getBody(currentState.getClass()); this.service .getHost() .log( Level.INFO, "Aborting transaction %s on service %s, current version %d, restoring version %d", request.getTransactionId(), this.service.getSelfLink(), currentState.documentVersion, clearTransactionRequest.originalVersion); previousState.documentTransactionId = null; this.service.setState(request, previousState); request.complete(); }); this.service.sendRequest(previousStateGet); return; } currentState.documentTransactionId = null; request.complete(); }