/** * Set the value of a property by its index * * @param index the index of the property * @param state the state of the property * @param value the value of the property */ public void setValue(int index, State state, String value) { // only update if it shall override if (state.compareTo(states[index]) >= 0) { values[index] = value; states[index] = state; } }
/** * Set the value for a specific property. * * @param property the property * @param state the state of the property * @param value the value of the property */ public void setValue(Property property, State state, String value) { // only update if it shall override if (state.compareTo(states[property.ordinal()]) >= 0) { values[property.ordinal()] = value; states[property.ordinal()] = state; } }
/** * Handles event that a submodule's out-port received a value. * * <p>This method starts copying the value to all ports that are connected via an outgoing * connection. Once all copy operations are completed (asynchronously), a {@link * SubmoduleOutPortNoLongerNeeded} message will be send to this actor. * * <p>This method does not finish any asynchronous actions. Instead, the asynchronous action * waiting for the submodule out-port is finished in {@link * #submoduleOutPortNoLongerNeeded(RuntimeOutPort)}. * * @param moduleId index of the module in {@link RuntimeParentModule#getModules()} that contains * the out-port * @param outPortId index of the out-port in {@link RuntimeModule#getOutPorts()} */ private void submoduleOutPortHasSignal(int moduleId, int outPortId) { assert state.compareTo(State.RUNNING) >= 0; final RuntimeOutPort outPort = module.getModules().get(moduleId).getOutPorts().get(outPortId); if (submoduleOutPortsReceivedMessage[moduleId].get(outPortId)) { log.warning( String.format( "Ignoring redundant message that %s of submodule '%s' provided a value.", outPort, outPort.getModule().getSimpleName())); } else if (isOutPortNeeded(outPort)) { submoduleOutPortsReceivedMessage[moduleId].set(outPortId); List<CompletableFuture<Void>> copyFutures = outPort .getOutConnections() .stream() .filter(this::isConnectionToRecomputedNode) .map(connection -> connection.accept(transmitFromSourcePortVisitor, outPort)) .collect(Collectors.toList()); CompletableFuture<Object> messageFuture = Futures.collect(copyFutures) .thenApply(ignored -> new SubmoduleOutPortNoLongerNeeded(outPort)); pipeResultToSelf( messageFuture, "copying value of %s of submodule to out-connections", outPort, outPort.getSimpleName()); } else { log.warning( String.format( "Ignoring unexpected message that %s of submodule '%s' provided a value because it is not needed.", outPort, outPort.getSimpleName())); } }
/** * Handles event that the value of a submodule's out-port is no longer needed. * * <p>If the submodule of the given out-port no longer has any (other) out-port whose value is * required, this method starts (asynchronously) cleaning all intermediate results for this * module. * * <p>This method also finishes the asynchronous action (waiting for submodule out-port) started * previously in {@link #getChildExecutor}. * * @param outPort out-port whose value is no longer needed */ private void submoduleOutPortNoLongerNeeded(RuntimeOutPort outPort) { assert state.compareTo(State.RUNNING) >= 0; RuntimeModule submodule = outPort.getModule(); BitSet neededOutPorts = computeResumeState.getSubmodulesNeededOutPorts()[submodule.getIndex()]; neededOutPorts.set(outPort.getOutIndex(), false); if (neededOutPorts.isEmpty() && getInterpreterProperties().isCleaningRequested()) { ExecutionTrace executionTrace = ExecutionTrace.empty().resolveContent().resolveModule(submodule.getSimpleName()); CompletableFuture<Void> future = stagingArea.delete(executionTrace); awaitAsynchronousAction( future, "cleaning up intermediate output of submodule '%s'", submodule.getSimpleName()); } endAsynchronousAction(outPort); }
/** * Gets the client's refund transaction which they can spend to get the entire channel value back * if it reaches its lock time. */ public synchronized long getRefundTransactionUnlockTime() { checkState(state.compareTo(State.WAITING_FOR_MULTISIG_CONTRACT) > 0 && state != State.ERROR); return refundTransactionUnlockTimeSecs; }
/** * Closes this channel and broadcasts the highest value payment transaction on the network. * * <p>This will set the state to {@link State#CLOSED} if the transaction is successfully broadcast * on the network. If we fail to broadcast for some reason, the state is set to {@link * State#ERROR}. * * <p>If the current state is before {@link State#READY} (ie we have not finished initializing the * channel), we simply set the state to {@link State#CLOSED} and let the client handle getting its * refund transaction confirmed. * * @return a future which completes when the provided multisig contract successfully broadcasts, * or throws if the broadcast fails for some reason. Note that if the network simply rejects * the transaction, this future will never complete, a timeout should be used. * @throws InsufficientMoneyException If the payment tx would have cost more in fees to spend than * it is worth. */ public synchronized ListenableFuture<Transaction> close() throws InsufficientMoneyException { if (storedServerChannel != null) { StoredServerChannel temp = storedServerChannel; storedServerChannel = null; StoredPaymentChannelServerStates channels = (StoredPaymentChannelServerStates) wallet.getExtensions().get(StoredPaymentChannelServerStates.EXTENSION_ID); channels.closeChannel( temp); // May call this method again for us (if it wasn't the original caller) if (state.compareTo(State.CLOSING) >= 0) return closedFuture; } if (state.ordinal() < State.READY.ordinal()) { log.error("Attempt to settle channel in state " + state); state = State.CLOSED; closedFuture.set(null); return closedFuture; } if (state != State.READY) { // TODO: What is this codepath for? log.warn("Failed attempt to settle a channel in state " + state); return closedFuture; } Transaction tx = null; try { Wallet.SendRequest req = makeUnsignedChannelContract(bestValueToMe); tx = req.tx; // Provide a throwaway signature so that completeTx won't complain out about unsigned inputs // it doesn't // know how to sign. Note that this signature does actually have to be valid, so we can't use // a dummy // signature to save time, because otherwise completeTx will try to re-sign it to make it // valid and then // die. We could probably add features to the SendRequest API to make this a bit more // efficient. signMultisigInput(tx, Transaction.SigHash.NONE, true); // Let wallet handle adding additional inputs/fee as necessary. req.shuffleOutputs = false; req.missingSigsMode = Wallet.MissingSigsMode.USE_DUMMY_SIG; wallet.completeTx(req); // TODO: Fix things so shuffling is usable. feePaidForPayment = req.tx.getFee(); log.info("Calculated fee is {}", feePaidForPayment); if (feePaidForPayment.compareTo(bestValueToMe) > 0) { final String msg = String.format( Locale.US, "Had to pay more in fees (%s) than the channel was worth (%s)", feePaidForPayment, bestValueToMe); throw new InsufficientMoneyException(feePaidForPayment.subtract(bestValueToMe), msg); } // Now really sign the multisig input. signMultisigInput(tx, Transaction.SigHash.ALL, false); // Some checks that shouldn't be necessary but it can't hurt to check. tx.verify(); // Sanity check syntax. for (TransactionInput input : tx.getInputs()) input.verify(); // Run scripts and ensure it is valid. } catch (InsufficientMoneyException e) { throw e; // Don't fall through. } catch (Exception e) { log.error( "Could not verify self-built tx\nMULTISIG {}\nCLOSE {}", multisigContract, tx != null ? tx : ""); throw new RuntimeException(e); // Should never happen. } state = State.CLOSING; log.info("Closing channel, broadcasting tx {}", tx); // The act of broadcasting the transaction will add it to the wallet. ListenableFuture<Transaction> future = broadcaster.broadcastTransaction(tx).future(); Futures.addCallback( future, new FutureCallback<Transaction>() { @Override public void onSuccess(Transaction transaction) { log.info("TX {} propagated, channel successfully closed.", transaction.getHash()); state = State.CLOSED; closedFuture.set(transaction); } @Override public void onFailure(Throwable throwable) { log.error("Failed to settle channel, could not broadcast", throwable); state = State.ERROR; closedFuture.setException(throwable); } }); return closedFuture; }
private static boolean isFinal(State state) { return (state.compareTo(State.Id) >= 0); }
/** * Once the servers signature over the refund transaction has been received and provided using * {@link PaymentChannelClientState#provideRefundSignature(byte[])} then this method can be called * to receive the now valid and broadcastable refund transaction. */ public synchronized Transaction getCompletedRefundTransaction() { checkState(state.compareTo(State.WAITING_FOR_SIGNED_REFUND) > 0); return refundTx; }
/** * Returns the fees that will be paid if the refund transaction has to be claimed because the * server failed to settle the channel properly. May only be called after {@link * PaymentChannelClientState#initiate()} */ public synchronized Coin getRefundTxFees() { checkState(state.compareTo(State.NEW) > 0); return refundFees; }
public static void parseDuration( final Object durationString, final int start, int length, IAObject mutableObject, ADurationParseOption parseOption) throws HyracksDataException { int offset = 0; int value = 0, hour = 0, minute = 0, second = 0, millisecond = 0, year = 0, month = 0, day = 0; State state = State.NOTHING_READ; IStringAccessor charAccessor; if (durationString instanceof char[]) { charAccessor = new IStringAccessor() { @Override public char getCharAt(int index) { return ((char[]) durationString)[start + index]; } }; } else if (durationString instanceof byte[]) { charAccessor = new IStringAccessor() { @Override public char getCharAt(int index) { return (char) (((byte[]) durationString)[start + index]); } }; } else if (durationString instanceof String) { charAccessor = new IStringAccessor() { @Override public char getCharAt(int index) { return ((String) durationString).charAt(start + index); } }; } else { throw new HyracksDataException(durationErrorMessage); } short sign = 1; if (charAccessor.getCharAt(offset) == '-') { offset++; sign = -1; } if (charAccessor.getCharAt(offset) != 'P') { throw new HyracksDataException(durationErrorMessage + ": Missing leading 'P'."); } offset++; for (; offset < length; offset++) { if (charAccessor.getCharAt(offset) >= '0' && charAccessor.getCharAt(offset) <= '9') { // accumulate the digit fields value = value * DECIMAL_UNIT + charAccessor.getCharAt(offset) - '0'; } else { switch (charAccessor.getCharAt(offset)) { case 'Y': if (state.compareTo(State.YEAR) < 0) { if (parseOption == ADurationParseOption.DAY_TIME) { throw new HyracksDataException(onlyDayTimeErrorMessage); } year = value; state = State.YEAR; } else { throw new HyracksDataException(durationErrorMessage + ": wrong YEAR feild."); } break; case 'M': if (state.compareTo(State.TIME) < 0) { if (state.compareTo(State.MONTH) < 0) { if (parseOption == ADurationParseOption.DAY_TIME) { throw new HyracksDataException(onlyDayTimeErrorMessage); } month = value; state = State.MONTH; } else { throw new HyracksDataException(durationErrorMessage + ": wrong MONTH field."); } } else if (state.compareTo(State.MIN) < 0) { if (parseOption == ADurationParseOption.YEAR_MONTH) { throw new HyracksDataException(onlyYearMonthErrorMessage); } minute = value; state = State.MIN; } else { throw new HyracksDataException(durationErrorMessage + ": wrong MIN field."); } break; case 'D': if (state.compareTo(State.DAY) < 0) { if (parseOption == ADurationParseOption.YEAR_MONTH) { throw new HyracksDataException(onlyYearMonthErrorMessage); } day = value; state = State.DAY; } else { throw new HyracksDataException(durationErrorMessage + ": wrong DAY field"); } break; case 'T': if (state.compareTo(State.TIME) < 0) { if (parseOption == ADurationParseOption.YEAR_MONTH) { throw new HyracksDataException(onlyYearMonthErrorMessage); } state = State.TIME; } else { throw new HyracksDataException(durationErrorMessage + ": wrong TIME field."); } break; case 'H': if (state.compareTo(State.HOUR) < 0) { if (parseOption == ADurationParseOption.YEAR_MONTH) { throw new HyracksDataException(onlyYearMonthErrorMessage); } hour = value; state = State.HOUR; } else { throw new HyracksDataException(durationErrorMessage + ": wrong HOUR field."); } break; case '.': if (state.compareTo(State.MILLISEC) < 0) { if (parseOption == ADurationParseOption.YEAR_MONTH) { throw new HyracksDataException(onlyYearMonthErrorMessage); } int i = 1; for (; offset + i < length; i++) { if (charAccessor.getCharAt(offset + i) >= '0' && charAccessor.getCharAt(offset + i) <= '9') { if (i < 4) { millisecond = millisecond * DECIMAL_UNIT + (charAccessor.getCharAt(offset + i) - '0'); } else { throw new HyracksDataException( durationErrorMessage + ": wrong MILLISECOND field."); } } else { break; } } offset += i; state = State.MILLISEC; } else { throw new HyracksDataException(durationErrorMessage + ": wrong MILLISECOND field."); } case 'S': if (state.compareTo(State.SEC) < 0) { if (parseOption == ADurationParseOption.YEAR_MONTH) { throw new HyracksDataException(onlyYearMonthErrorMessage); } second = value; state = State.SEC; } else { throw new HyracksDataException(durationErrorMessage + ": wrong SECOND field."); } break; default: throw new HyracksDataException(durationErrorMessage + ": wrong format for duration."); } value = 0; } } if (state.compareTo(State.TIME) == 0) { throw new HyracksDataException( durationErrorMessage + ": no time fields after time separator."); } int totalMonths = sign * (year * 12 + month); long totalMilliseconds = sign * (day * GregorianCalendarSystem.CHRONON_OF_DAY + hour * GregorianCalendarSystem.CHRONON_OF_HOUR + minute * GregorianCalendarSystem.CHRONON_OF_MINUTE + second * GregorianCalendarSystem.CHRONON_OF_SECOND + millisecond); if (sign > 0) { if (totalMonths < 0) { throw new HyracksDataException( durationErrorMessage + ": total number of months is beyond its max value (-2147483647 to 2147483647)."); } if (totalMilliseconds < 0) { throw new HyracksDataException( durationErrorMessage + ": total number of milliseconds is beyond its max value (-9223372036854775808 to 9223372036854775807)."); } } if (mutableObject instanceof AMutableDuration) { ((AMutableDuration) mutableObject).setValue(totalMonths, totalMilliseconds); } else if (mutableObject instanceof AMutableYearMonthDuration) { ((AMutableYearMonthDuration) mutableObject).setMonths(totalMonths); } else if (mutableObject instanceof AMutableDayTimeDuration) { ((AMutableDayTimeDuration) mutableObject).setMilliseconds(totalMilliseconds); } }