Skip to content

Commit

Permalink
Merge branch 'googleapis:main' into interval_support
Browse files Browse the repository at this point in the history
  • Loading branch information
sagarwaal authored and Sagar Agarwal committed Oct 22, 2024
2 parents df6ebe7 + 16cc6ee commit f16ae42
Show file tree
Hide file tree
Showing 29 changed files with 1,135 additions and 221 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import com.google.spanner.v1.ExecuteSqlRequest;
import com.google.spanner.v1.ExecuteSqlRequest.QueryMode;
import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions;
import com.google.spanner.v1.MultiplexedSessionPrecommitToken;
import com.google.spanner.v1.PartialResultSet;
import com.google.spanner.v1.ReadRequest;
import com.google.spanner.v1.RequestOptions;
Expand Down Expand Up @@ -893,6 +894,13 @@ public void onDone(boolean withBeginTransaction) {
this.session.onReadDone();
}

/**
* For transactions other than read-write, the MultiplexedSessionPrecommitToken will not be
* present in the RPC response. In such cases, this method will be a no-op.
*/
@Override
public void onPrecommitToken(MultiplexedSessionPrecommitToken token) {}

private ResultSet readInternal(
String table,
@Nullable String index,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.google.protobuf.ListValue;
import com.google.protobuf.ProtocolMessageEnum;
import com.google.protobuf.Value.KindCase;
import com.google.spanner.v1.MultiplexedSessionPrecommitToken;
import com.google.spanner.v1.Transaction;
import java.io.IOException;
import java.io.Serializable;
Expand Down Expand Up @@ -57,6 +58,12 @@ void onTransactionMetadata(Transaction transaction, boolean shouldIncludeId)

/** Called when the read finishes normally. */
void onDone(boolean withBeginTransaction);

/**
* Called when the RPC response contains a MultiplexedSessionPrecommitToken. A precommit token
* will be included if the read-write transaction is executed on a multiplexed session.
*/
void onPrecommitToken(MultiplexedSessionPrecommitToken token);
}

static final class LazyByteArray implements Serializable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.protobuf.ByteString;

/** Implementation of {@link AsyncTransactionManager}. */
final class AsyncTransactionManagerImpl
Expand Down Expand Up @@ -80,7 +81,19 @@ public TransactionContextFutureImpl beginAsync() {

private ApiFuture<TransactionContext> internalBeginAsync(boolean firstAttempt) {
txnState = TransactionState.STARTED;
txn = session.newTransaction(options);

// Determine the latest transactionId when using a multiplexed session.
ByteString multiplexedSessionPreviousTransactionId = ByteString.EMPTY;
if (txn != null && session.getIsMultiplexed() && !firstAttempt) {
// Use the current transactionId if available, otherwise fallback to the previous aborted
// transactionId.
multiplexedSessionPreviousTransactionId =
txn.transactionId != null ? txn.transactionId : txn.getPreviousTransactionId();
}

txn =
session.newTransaction(
options, /* previousTransactionId = */ multiplexedSessionPreviousTransactionId);
if (firstAttempt) {
session.setActive(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static com.google.cloud.spanner.BuiltInMetricsConstant.CLIENT_HASH_KEY;
import static com.google.cloud.spanner.BuiltInMetricsConstant.CLIENT_NAME_KEY;
import static com.google.cloud.spanner.BuiltInMetricsConstant.CLIENT_UID_KEY;
import static com.google.cloud.spanner.BuiltInMetricsConstant.DIRECT_PATH_ENABLED_KEY;
import static com.google.cloud.spanner.BuiltInMetricsConstant.INSTANCE_CONFIG_ID_KEY;
import static com.google.cloud.spanner.BuiltInMetricsConstant.LOCATION_ID_KEY;
import static com.google.cloud.spanner.BuiltInMetricsConstant.PROJECT_ID_KEY;
Expand Down Expand Up @@ -83,6 +84,7 @@ Map<String, String> createClientAttributes(String projectId, String client_name)
clientAttributes.put(LOCATION_ID_KEY.getKey(), detectClientLocation());
clientAttributes.put(PROJECT_ID_KEY.getKey(), projectId);
// TODO: Replace this with real value.
clientAttributes.put(DIRECT_PATH_ENABLED_KEY.getKey(), "false");
clientAttributes.put(INSTANCE_CONFIG_ID_KEY.getKey(), "unknown");
clientAttributes.put(CLIENT_NAME_KEY.getKey(), client_name);
String clientUid = getDefaultTaskValue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ public void addAttributes(Map<String, String> attributes) {
for (ApiTracer child : children) {
if (child instanceof MetricsTracer) {
MetricsTracer metricsTracer = (MetricsTracer) child;
attributes.forEach((key, value) -> metricsTracer.addAttributes(key, value));
metricsTracer.addAttributes(attributes);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class DatabaseClientImpl implements DatabaseClient {
/* useMultiplexedSessionBlindWrite = */ false,
/* multiplexedSessionDatabaseClient = */ null,
tracer,
false);
/* useMultiplexedSessionForRW = */ false);
}

DatabaseClientImpl(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class GrpcResultSet extends AbstractResultSet<List<Object>> implements ProtobufR

GrpcResultSet(
CloseableIterator<PartialResultSet> iterator, Listener listener, DecodeMode decodeMode) {
this.iterator = new GrpcValueIterator(iterator);
this.iterator = new GrpcValueIterator(iterator, listener);
this.listener = listener;
this.decodeMode = decodeMode;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static com.google.common.base.Preconditions.checkState;

import com.google.cloud.spanner.AbstractResultSet.CloseableIterator;
import com.google.cloud.spanner.AbstractResultSet.Listener;
import com.google.common.collect.AbstractIterator;
import com.google.protobuf.ListValue;
import com.google.protobuf.Value.KindCase;
Expand All @@ -44,9 +45,11 @@ private enum StreamValue {
private PartialResultSet current;
private int pos;
private ResultSetStats statistics;
private final Listener listener;

GrpcValueIterator(CloseableIterator<PartialResultSet> stream) {
GrpcValueIterator(CloseableIterator<PartialResultSet> stream, Listener listener) {
this.stream = stream;
this.listener = listener;
}

@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -154,6 +157,10 @@ private boolean ensureReady(StreamValue requiredValue) throws SpannerException {
ErrorCode.INTERNAL, "Invalid type metadata: " + e.getMessage(), e);
}
}
// collect the precommit token from each PartialResultSet
if (current.hasPrecommitToken()) {
listener.onPrecommitToken(current.getPrecommitToken());
}
if (current.hasStats()) {
statistics = current.getStats();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

@AutoValue
@Immutable
public abstract class Interval implements Comparable<Interval>, Serializable {
public abstract class Interval implements Serializable {
public static final long MONTHS_PER_YEAR = 12;
public static final long DAYS_PER_MONTH = 30;
public static final long HOURS_PER_DAY = 24;
Expand All @@ -53,48 +53,92 @@ public abstract class Interval implements Comparable<Interval>, Serializable {
Pattern.compile(
"^P(?!$)(-?\\d+Y)?(-?\\d+M)?(-?\\d+D)?(T(?=-?\\d)(-?\\d+H)?(-?\\d+M)?(-?\\d+(\\.\\d{1,9})?S)?)?$");

public abstract long months();
/** Returns the months component of the interval. */
public abstract int months();

public abstract long days();
/** Returns the days component of the interval. */
public abstract int days();

/** Returns the microseconds component of the interval. */
public abstract long micros();

/** Returns the nanoFractions component of the interval. */
public abstract short nanoFractions();

public static Builder builder() {
return new AutoValue_Interval.Builder();
}

/** Returns the nanoseconds component of the interval. */
public BigInteger nanos() {
return BigInteger.valueOf(micros())
.multiply(BigInteger.valueOf(NANOS_PER_MICRO))
.add(BigInteger.valueOf(nanoFractions()));
}

/** Returns the total micros represented by the Interval. */
/** Returns the total microseconds represented by the interval. */
public long getAsMicros() {
return months() * MICROS_PER_MONTH + days() * MICROS_PER_DAY + micros();
}

/** Returns the total nanos represented by the Interval. */
/** Returns the total nanoseconds represented by the interval. */
public BigInteger getAsNanos() {
return BigInteger.valueOf(getAsMicros())
.multiply(BigInteger.valueOf(NANOS_PER_MICRO))
.add(BigInteger.valueOf(nanoFractions()));
}

/** Creates an Interval consisting of the given number of months. */
public static Interval ofMonths(long months) {
/** Creates an interval with specified number of months. */
public static Interval ofMonths(int months) {
return builder().setMonths(months).setDays(0).setMicros(0).setNanoFractions((short) 0).build();
}

/** Creates an Interval consisting of the given number of days. */
public static Interval ofDays(long days) {
/** Creates an interval with specified number of days. */
public static Interval ofDays(int days) {
return builder().setMonths(0).setDays(days).setMicros(0).setNanoFractions((short) 0).build();
}

/** Creates an Interval with specified months, days and micros. */
public static Interval fromMonthsDaysMicros(long months, long days, long micros) {
/** Creates an interval with specified number of seconds. */
public static Interval ofSeconds(long seconds) {
return builder()
.setMonths(0)
.setDays(0)
.setMicros(seconds * MICROS_PER_SECOND)
.setNanoFractions((short) 0)
.build();
}

/** Creates an interval with specified number of milliseconds. */
public static Interval ofMilliseconds(long milliseconds) {
return builder()
.setMonths(0)
.setDays(0)
.setMicros(milliseconds * MICROS_PER_MILLI)
.setNanoFractions((short) 0)
.build();
}

/** Creates an interval with specified number of microseconds. */
public static Interval ofMicros(long micros) {
return builder().months(0).days(0).micros(micros).nanoFractions((short) 0).build();
}

/** Creates an interval with specified number of nanoseconds. */
public static Interval ofNanos(@NotNull BigInteger nanos) {
BigInteger micros = nanos.divide(BigInteger.valueOf(NANOS_PER_MICRO));
BigInteger nanoFractions = nanos.subtract(micros.multiply(BigInteger.valueOf(NANOS_PER_MICRO)));
long microsValue = micros.longValueExact();
short nanoFractionsValue = nanoFractions.shortValueExact();
return builder()
.setMonths(0)
.setDays(0)
.setMicros(microsValue)
.setNanoFractions(nanoFractionsValue)
.build();
}

/** Creates an interval with specified number of months, days and microseconds. */
public static Interval fromMonthsDaysMicros(int months, int days, long micros) {
return builder()
.setMonths(months)
.setDays(days)
Expand All @@ -103,13 +147,15 @@ public static Interval fromMonthsDaysMicros(long months, long days, long micros)
.build();
}

/** Creates an Interval with specified months, days and nanos. */
public static Interval fromMonthsDaysNanos(long months, long days, BigInteger nanos) {
long micros = nanos.divide(BigInteger.valueOf(NANOS_PER_MICRO)).longValue();
/** Creates an interval with specified number of months, days and nanoseconds. */
public static Interval fromMonthsDaysNanos(int months, int days, BigInteger nanos) {
long micros = (nanos.divide(BigInteger.valueOf(NANOS_PER_MICRO))).longValueExact();
short nanoFractions =
nanos
.subtract(BigInteger.valueOf(micros).multiply(BigInteger.valueOf(NANOS_PER_MICRO)))
(nanos.subtract(BigInteger.valueOf(micros).multiply(BigInteger.valueOf(NANOS_PER_MICRO))))
.shortValue();

System.out.println("Micros: " + micros + " Nanos: " + nanoFractions);

return builder()
.setMonths(months)
.setDays(days)
Expand Down Expand Up @@ -149,14 +195,14 @@ public static Interval parseFromString(String interval) {
totalNanos.subtract(totalMicros.multiply(BigInteger.valueOf(NANOS_PER_MICRO)));

return Interval.builder()
.setMonths(totalMonths)
.setDays(days)
.setMicros(totalMicros.longValue())
.setNanoFractions(nanoFractions.shortValue())
.setMonths(Math.toIntExact(totalMonths))
.setDays(Math.toIntExact(days))
.setMicros(totalMicros.longValueExact())
.setNanoFractions(nanoFractions.shortValueExact())
.build();
}

/** @return the Interval in ISO801 duration format. */
/** Converts Interval to ISO8601 Duration Formatted String. */
public String ToISO8601() {
StringBuilder result = new StringBuilder();
result.append("P");
Expand Down Expand Up @@ -197,7 +243,7 @@ public String ToISO8601() {
BigDecimal seconds = new BigDecimal(nanos).movePointLeft(9);

if (seconds.compareTo(new BigDecimal(zero)) != 0) {
result.append(String.format("%sS", seconds));
result.append(String.format("%sS", seconds.stripTrailingZeros()));
}
}

Expand All @@ -208,47 +254,7 @@ public String ToISO8601() {
return result.toString();
}

/** Creates an Interval consisting of the given number of seconds. */
public static Interval ofSeconds(long seconds) {
return builder()
.setMonths(0)
.setDays(0)
.setMicros(seconds * MICROS_PER_SECOND)
.setNanoFractions((short) 0)
.build();
}

/** Creates an Interval consisting of the given number of milliseconds. */
public static Interval ofMilliseconds(long milliseconds) {
return builder()
.setMonths(0)
.setDays(0)
.setMicros(milliseconds * MICROS_PER_MILLI)
.setNanoFractions((short) 0)
.build();
}

/** Creates an Interval consisting of the given number of microseconds. */
public static Interval ofMicros(long micros) {
return builder().months(0).days(0).micros(micros).nanoFractions((short) 0).build();
}

/** Creates an Interval consisting of the given number of nanoseconds. */
public static Interval ofNanos(@NotNull BigInteger nanos) {
BigInteger micros = nanos.divide(BigInteger.valueOf(NANOS_PER_MICRO));
BigInteger nanoFractions = nanos.subtract(micros.multiply(BigInteger.valueOf(NANOS_PER_MICRO)));

long microsValue = micros.longValue();
long nanoFractionsValue = nanoFractions.longValue();

return builder()
.setMonths(0)
.setDays(0)
.setMicros(microsValue)
.setNanoFractions((short) nanoFractionsValue)
.build();
}

/** Creates an interval which representing 0-duration. */
public static Interval zeroInterval() {
return builder().setMonths(0).setDays(0).setMicros(0).setNanoFractions((short) 0).build();
}
Expand All @@ -265,14 +271,6 @@ && days() == anotherInterval.days()
&& nanos().equals(anotherInterval.nanos());
}

@Override
public int compareTo(@NotNull Interval anotherInterval) {
if (equals(anotherInterval)) {
return 0;
}
return getAsNanos().compareTo(anotherInterval.getAsNanos());
}

@Override
public int hashCode() {
int result = 17;
Expand All @@ -284,19 +282,19 @@ public int hashCode() {

@AutoValue.Builder
public abstract static class Builder {
abstract Builder months(long months);
abstract Builder months(int months);

abstract Builder days(long days);
abstract Builder days(int days);

abstract Builder micros(long micros);

abstract Builder nanoFractions(short nanoFractions);

public Builder setMonths(long months) {
public Builder setMonths(int months) {
return months(months);
}

public Builder setDays(long days) {
public Builder setDays(int days) {
return days(days);
}

Expand Down
Loading

0 comments on commit f16ae42

Please sign in to comment.