public async Task TestHybridTime() { // Perform one write so we receive a timestamp from the server and can use // it to propagate a modified timestamp back to the server. Following writes // should force the servers to update their clocks to this value and increment // the logical component of the timestamp. await InsertRowAsync("0"); Assert.NotEqual(KuduClient.NoTimestamp, _client.LastPropagatedTimestamp); var(timestampMicros, logicalValue) = HybridTimeUtil.HtTimestampToPhysicalAndLogical( _client.LastPropagatedTimestamp); Assert.Equal(0, logicalValue); long futureTs = timestampMicros + 5000000; _client.LastPropagatedTimestamp = HybridTimeUtil.ClockTimestampToHtTimestamp(futureTs); var logicalValues = new List <long>(); var keys = new[] { "1", "2", "3", "11", "22", "33" }; for (int i = 0; i < keys.Length; i++) { await InsertRowAsync(keys[i]); Assert.NotEqual(KuduClient.NoTimestamp, _client.LastPropagatedTimestamp); (timestampMicros, logicalValue) = HybridTimeUtil.HtTimestampToPhysicalAndLogical( _client.LastPropagatedTimestamp); Assert.Equal(futureTs, timestampMicros); logicalValues.Add(logicalValue); Assert.Equal(logicalValues.OrderBy(v => v), logicalValues); } // Scan all rows with READ_LATEST (the default), which should retrieve all rows. var scanner = _client.NewScanBuilder(_table) .SetReadMode(ReadMode.ReadLatest) .Build(); Assert.Equal(1 + keys.Length, await scanner.CountAsync()); // Now scan at multiple snapshots with READ_AT_SNAPSHOT. The logical timestamp // from the 'i'th row (counted from 0) combined with the latest physical timestamp // should observe 'i + 1' rows. for (int i = 0; i < logicalValues.Count; i++) { logicalValue = logicalValues[i]; long snapshotTime = HybridTimeUtil.PhysicalAndLogicalToHtTimestamp( futureTs, logicalValue); int expected = i + 1; long numRows = await ScanAtSnapshotAsync(snapshotTime); Assert.Equal(expected, numRows); } // The last snapshots needs to be one into the future w.r.t. the last write's // timestamp to get all rows, but the snapshot timestamp can't be bigger than // the propagated timestamp. Ergo increase the propagated timestamp first. long latestLogicalValue = logicalValues[^ 1];
/// <summary> /// Sets the timestamp the scan must be executed at, in microseconds since the Unix epoch. /// None is used by default. Requires that the ReadMode is READ_AT_SNAPSHOT. /// </summary> /// <param name="timestamp">A long representing an instant in microseconds since the unix epoch.</param> public TBuilder SnapshotTimestampMicros(long timestamp) { HtTimestamp = HybridTimeUtil.PhysicalAndLogicalToHtTimestamp(timestamp, 0); return((TBuilder)this); }