diff --git a/src/Knet.Kudu.Client/ExternalConsistencyMode.cs b/src/Knet.Kudu.Client/ExternalConsistencyMode.cs
index 580aa349..d8d5838d 100644
--- a/src/Knet.Kudu.Client/ExternalConsistencyMode.cs
+++ b/src/Knet.Kudu.Client/ExternalConsistencyMode.cs
@@ -3,62 +3,69 @@
namespace Knet.Kudu.Client
{
///
+ ///
/// The external consistency mode for client requests.
/// This defines how transactions and/or sequences of operations that touch
/// several TabletServers, in different machines, can be observed by external
/// clients.
- ///
+ ///
+ ///
+ ///
/// Note that ExternalConsistencyMode makes no guarantee on atomicity, i.e.
/// no sequence of operations is made atomic (or transactional) just because
/// an external consistency mode is set.
/// Note also that ExternalConsistencyMode has no implication on the
/// consistency between replicas of the same tablet.
+ ///
///
public enum ExternalConsistencyMode
{
///
- /// The response to any write will contain a timestamp.
- /// Any further calls from the same client to other servers will update
- /// those servers with that timestamp. The user will make sure that the
- /// timestamp is propagated through back-channels to other
- /// KuduClient's.
- ///
- /// WARNING: Failure to propagate timestamp information through
- /// back-channels will negate any external consistency guarantee under this
- /// mode.
- ///
- /// Example:
- /// 1 - Client A executes operation X in Tablet A
- /// 2 - Afterwards, Client A executes operation Y in Tablet B
- ///
- ///
- /// Client B may observe the following operation sequences:
- /// {}, {X}, {X Y}
- ///
- /// This is the default mode.
+ ///
+ /// The response to any write will contain a timestamp. Any further calls
+ /// from the same client to other servers will update those servers
+ /// with that timestamp. Following write operations from the same client
+ /// will be assigned timestamps that are strictly higher, enforcing external
+ /// consistency without having to wait or incur any latency penalties.
+ ///
+ ///
+ ///
+ /// In order to maintain external consistency for writes between
+ /// two different clients in this mode, the user must forward the timestamp
+ /// from the first client to the second by using
+ /// .
+ ///
+ ///
+ ///
+ /// This is the default external consistency mode.
+ ///
+ ///
+ ///
+ /// Failure to propagate timestamp information through back-channels
+ /// between two different clients will negate any external consistency
+ /// guarantee under this mode.
+ ///
///
ClientPropagated = ExternalConsistencyModePB.ClientPropagated,
///
- /// The server will guarantee that each transaction is externally
- /// consistent by making sure that none of its results are visible
- /// until every Kudu server agrees that the transaction is in the past.
- /// The client is not obligated to forward timestamp information
- /// through back-channels.
- ///
- /// WARNING: Depending on the clock synchronization state of TabletServers
- /// this may imply considerable latency. Moreover operations with
- /// COMMIT_WAIT requested external consistency will outright fail if
- /// TabletServer clocks are either unsynchronized or synchronized but
- /// with a maximum error which surpasses a pre-configured one.
- ///
- /// Example:
- /// - Client A executes operation X in Tablet A
- /// - Afterwards, Client A executes operation Y in Tablet B
- ///
- ///
- /// Client B may observe the following operation sequences:
- /// {}, {X}, {X Y}
+ ///
+ /// The server will guarantee that write operations from the same or from
+ /// other client are externally consistent, without the need to propagate
+ /// timestamps across clients. This is done by making write operations
+ /// wait until there is certainty that all follow up write operations
+ /// (operations that start after the previous one finishes)
+ /// will be assigned a timestamp that is strictly higher, enforcing external
+ /// consistency.
+ ///
+ ///
+ ///
+ /// Depending on the clock synchronization state of TabletServers this may
+ /// imply considerable latency. Moreover operations in COMMIT_WAIT
+ /// external consistency mode will outright fail if TabletServer clocks
+ /// are either unsynchronized or synchronized but with a maximum error
+ /// which surpasses a pre-configured threshold.
+ ///
///
CommitWait = ExternalConsistencyModePB.CommitWait
}
diff --git a/src/Knet.Kudu.Client/Internal/ISystemClock.cs b/src/Knet.Kudu.Client/Internal/ISystemClock.cs
index 919df555..c8d0f7b0 100644
--- a/src/Knet.Kudu.Client/Internal/ISystemClock.cs
+++ b/src/Knet.Kudu.Client/Internal/ISystemClock.cs
@@ -2,6 +2,11 @@
{
public interface ISystemClock
{
+ ///
+ /// Retrieve the current milliseconds. This value should only
+ /// be used to measure how much time has passed relative to
+ /// another call to this property.
+ ///
long CurrentMilliseconds { get; }
}
}
diff --git a/src/Knet.Kudu.Client/Internal/SystemClock.cs b/src/Knet.Kudu.Client/Internal/SystemClock.cs
index 59272757..e48e7fda 100644
--- a/src/Knet.Kudu.Client/Internal/SystemClock.cs
+++ b/src/Knet.Kudu.Client/Internal/SystemClock.cs
@@ -6,10 +6,12 @@ namespace Knet.Kudu.Client.Internal
public sealed class SystemClock : ISystemClock
{
#if NETCOREAPP3_0
+ ///
public long CurrentMilliseconds => Environment.TickCount64;
#else
private readonly Stopwatch _stopwatch = Stopwatch.StartNew();
+ ///
public long CurrentMilliseconds => _stopwatch.ElapsedMilliseconds;
#endif
}
diff --git a/src/Knet.Kudu.Client/KuduClient.cs b/src/Knet.Kudu.Client/KuduClient.cs
index 8b8a8822..d34962ea 100644
--- a/src/Knet.Kudu.Client/KuduClient.cs
+++ b/src/Knet.Kudu.Client/KuduClient.cs
@@ -168,17 +168,23 @@ public void ImportAuthenticationCredentials(ReadOnlyMemory token)
_securityContext.ImportAuthenticationCredentials(token);
}
+ ///
+ /// Create a table on the cluster with the specified name, schema, and
+ /// table configurations.
+ ///
+ /// The create table options.
+ /// The cancellation token.
public async Task CreateTableAsync(
- TableBuilder tableBuilder, CancellationToken cancellationToken = default)
+ TableBuilder builder, CancellationToken cancellationToken = default)
{
- var rpc = new CreateTableRequest(tableBuilder.Build());
+ var rpc = new CreateTableRequest(builder.Build());
var response = await SendRpcAsync(rpc, cancellationToken)
.ConfigureAwait(false);
var tableId = new TableIdentifierPB { TableId = response.TableId };
- if (tableBuilder.Wait)
+ if (builder.Wait)
{
await WaitForCreateTableDoneAsync(
tableId, cancellationToken).ConfigureAwait(false);
@@ -190,11 +196,16 @@ await WaitForCreateTableDoneAsync(
return null;
}
+ ///
+ /// Alter a table on the cluster as specified by the builder.
+ ///
+ /// The alter table options.
+ /// The cancellation token.
public async Task AlterTableAsync(
- AlterTableBuilder alterTable,
+ AlterTableBuilder builder,
CancellationToken cancellationToken = default)
{
- var rpc = new AlterTableRequest(alterTable);
+ var rpc = new AlterTableRequest(builder);
AlterTableResponse response;
try
@@ -204,19 +215,19 @@ public async Task AlterTableAsync(
}
finally
{
- if (alterTable.HasAddDropRangePartitions)
+ if (builder.HasAddDropRangePartitions)
{
// Clear the table locations cache so the new partition is
// immediately visible. We clear the cache even on failure,
// just in case the alter table operation actually succeeded.
- _tableLocations.TryRemove(alterTable.TableId, out _);
+ _tableLocations.TryRemove(builder.TableId, out _);
}
}
- if (alterTable.Wait)
+ if (builder.Wait)
{
var isDoneResponse = await WaitForAlterTableDoneAsync(
- alterTable.TableIdPb, cancellationToken).ConfigureAwait(false);
+ builder.TableIdPb, cancellationToken).ConfigureAwait(false);
response = new AlterTableResponse(
response.TableId,
@@ -286,6 +297,13 @@ public async Task DeleteTableAsync(
await SendRpcAsync(rpc, cancellationToken).ConfigureAwait(false);
}
+ ///
+ /// Get a list of table names. Passing a null filter returns all the tables.
+ /// When a filter is specified, it only returns tables that satisfy a substring
+ /// match.
+ ///
+ /// An optional table name filter.
+ /// The cancellation token.
public async Task> GetTablesAsync(
string nameFilter = null, CancellationToken cancellationToken = default)
{
@@ -381,6 +399,11 @@ internal async Task> GetTableLocationsAsync(
return tableLocations;
}
+ ///
+ /// Open the table with the given name.
+ ///
+ /// The table to open.
+ /// The cancellation token.
public async Task OpenTableAsync(
string tableName, CancellationToken cancellationToken = default)
{
@@ -532,6 +555,23 @@ public IKuduSession NewSession(KuduSessionOptions options)
return new KuduSession(this, options, _loggerFactory);
}
+ ///
+ ///
+ /// Create a that allows clients to determine
+ /// the target partition of a row without actually performing a write. The
+ /// set of partitions is eagerly fetched when the KuduPartitioner is constructed
+ /// so that the actual partitioning step can be performed synchronously
+ /// without any network trips.
+ ///
+ ///
+ ///
+ /// NOTE: Because this operates on a metadata snapshot retrieved at
+ /// construction time, it will not reflect any metadata changes to the
+ /// table that have occurred since its creation.
+ ///
+ ///
+ /// The table to operate on.
+ /// The cancellation token.
public async ValueTask CreatePartitionerAsync(
KuduTable table, CancellationToken cancellationToken = default)
{
@@ -736,7 +776,7 @@ private TableLocationsCache GetTableLocationsCache(string tableId)
#endif
}
- public async ValueTask> LoopLocateTableAsync(
+ private async ValueTask> LoopLocateTableAsync(
string tableId,
byte[] startPartitionKey,
byte[] endPartitionKey,
diff --git a/src/Knet.Kudu.Client/KuduScanEnumerator.cs b/src/Knet.Kudu.Client/KuduScanEnumerator.cs
index 78722738..2a472f8e 100644
--- a/src/Knet.Kudu.Client/KuduScanEnumerator.cs
+++ b/src/Knet.Kudu.Client/KuduScanEnumerator.cs
@@ -131,7 +131,6 @@ public KuduScanEnumerator(
_lastPrimaryKey = Array.Empty();
_cancellationToken = cancellationToken;
ResourceMetrics = new ResourceMetrics();
- // TODO: Register cancellation callback and cancel the scan.
// Map the column names to actual columns in the table schema.
// If the user set this to 'null', we scan all columns.
@@ -436,7 +435,6 @@ private async ValueTask ScanNextRowsAsync()
private ScanRequest GetOpenRequest()
{
- //checkScanningNotStarted();
var request = new ScanRequestPB();
var newRequest = request.NewScanRequest = new NewScanRequestPB
@@ -499,7 +497,6 @@ private ScanRequest GetOpenRequest()
private ScanRequest GetNextRowsRequest()
{
- //checkScanningNotStarted();
var request = new ScanRequestPB
{
ScannerId = _scannerId,