/// Add a suggestion string to an auto-complete suggestion dictionary. This is disconnected from the index definitions, and leaves creating and updating suggestino dictionaries to the user.
/// Add a suggestion string to an auto-complete suggestion dictionary. This is disconnected from the index definitions, and leaves creating and updating suggestino dictionaries to the user.
/// </summary>
/// </summary>
/// <param name="value">the suggestion string we index</param>
/// <param name="value">the suggestion string we index</param>
/// <param name="score">a floating point number of the suggestion string's weight</param>
/// <param name="score">a floating point number of the suggestion string's weight</param>
/// <param name="increment">if set, we increment the existing entry of the suggestion by the given score, instead of replacing the score. This is useful for updating the dictionary based on user queries in real time</param>
/// <param name="increment">if set, we increment the existing entry of the suggestion by the given score, instead of replacing the score. This is useful for updating the dictionary based on user queries in real time</param>
/// <returns>the current size of the suggestion dictionary.</returns>
/// <returns>the current size of the suggestion dictionary.</returns>
/// Add a suggestion string to an auto-complete suggestion dictionary. This is disconnected from the index definitions, and leaves creating and updating suggestino dictionaries to the user.
/// Add a suggestion string to an auto-complete suggestion dictionary. This is disconnected from the index definitions, and leaves creating and updating suggestino dictionaries to the user.
/// </summary>
/// </summary>
/// <param name="value">the suggestion string we index</param>
/// <param name="value">the suggestion string we index</param>
/// <param name="score">a floating point number of the suggestion string's weight</param>
/// <param name="score">a floating point number of the suggestion string's weight</param>
/// <param name="increment">if set, we increment the existing entry of the suggestion by the given score, instead of replacing the score. This is useful for updating the dictionary based on user queries in real time</param>
/// <param name="increment">if set, we increment the existing entry of the suggestion by the given score, instead of replacing the score. This is useful for updating the dictionary based on user queries in real time</param>
/// <returns>the current size of the suggestion dictionary.</returns>
/// <returns>the current size of the suggestion dictionary.</returns>
//Assert.False(cluster.Wait(existsY), "y exists");
//Assert.False(cluster.Wait(existsY), "y exists");
}
}
});
});
Assert.Equal("Multi-key operations must involve a single slot; keys can use 'hash tags' to help this, i.e. '{/users/12345}/account' and '{/users/12345}/contacts' will always be in the same slot",ex.Message);
Assert.Equal("Multi-key operations must involve a single slot; keys can use 'hash tags' to help this, i.e. '{/users/12345}/account' and '{/users/12345}/contacts' will always be in the same slot",ex.Message);
// invent 2 keys that we believe are served by different nodes
// invent 2 keys that we believe are served by different nodes
stringx=Guid.NewGuid().ToString(),y;
stringx=Guid.NewGuid().ToString(),y;
varxNode=config.GetBySlot(x);
varxNode=config.GetBySlot(x);
intabort=1000;
intabort=1000;
do
do
{
{
y=Guid.NewGuid().ToString();
y=Guid.NewGuid().ToString();
}while(--abort>0&&config.GetBySlot(y)!=xNode);
}while(--abort>0&&config.GetBySlot(y)!=xNode);
if(abort==0)Skip.Inconclusive("failed to find a key with the same node to use");
if(abort==0)Skip.Inconclusive("failed to find a key with the same node to use");
varyNode=config.GetBySlot(y);
varyNode=config.GetBySlot(y);
Output.WriteLine("x={0}, served by {1}",x,xNode.NodeId);
Output.WriteLine("x={0}, served by {1}",x,xNode.NodeId);
Output.WriteLine("y={0}, served by {1}",y,yNode.NodeId);
Output.WriteLine("y={0}, served by {1}",y,yNode.NodeId);
Assert.Equal(xNode.NodeId,yNode.NodeId);
Assert.Equal(xNode.NodeId,yNode.NodeId);
// wipe those keys
// wipe those keys
cluster.KeyDelete(x,CommandFlags.FireAndForget);
cluster.KeyDelete(x,CommandFlags.FireAndForget);
cluster.KeyDelete(y,CommandFlags.FireAndForget);
cluster.KeyDelete(y,CommandFlags.FireAndForget);
// create a transaction that attempts to assign both keys
// create a transaction that attempts to assign both keys
vartran=cluster.CreateTransaction();
vartran=cluster.CreateTransaction();
tran.AddCondition(Condition.KeyNotExists(x));
tran.AddCondition(Condition.KeyNotExists(x));
tran.AddCondition(Condition.KeyNotExists(y));
tran.AddCondition(Condition.KeyNotExists(y));
varsetX=tran.StringSetAsync(x,"x-val");
varsetX=tran.StringSetAsync(x,"x-val");
varsetY=tran.StringSetAsync(y,"y-val");
varsetY=tran.StringSetAsync(y,"y-val");
boolsuccess=tran.Execute();
boolsuccess=tran.Execute();
Assert.True(false,"Expected single-slot rules to apply");
Assert.True(false,"Expected single-slot rules to apply");
// the rest no longer applies while we are following single-slot rules
// the rest no longer applies while we are following single-slot rules
//// check that everything was aborted
//// check that everything was aborted
//Assert.True(success, "tran aborted");
//Assert.True(success, "tran aborted");
//Assert.False(setX.IsCanceled, "set x cancelled");
//Assert.False(setX.IsCanceled, "set x cancelled");
//Assert.False(setY.IsCanceled, "set y cancelled");
//Assert.False(setY.IsCanceled, "set y cancelled");
//var existsX = cluster.KeyExistsAsync(x);
//var existsX = cluster.KeyExistsAsync(x);
//var existsY = cluster.KeyExistsAsync(y);
//var existsY = cluster.KeyExistsAsync(y);
//Assert.True(cluster.Wait(existsX), "x exists");
//Assert.True(cluster.Wait(existsX), "x exists");
//Assert.True(cluster.Wait(existsY), "y exists");
//Assert.True(cluster.Wait(existsY), "y exists");
}
}
});
});
Assert.Equal("Multi-key operations must involve a single slot; keys can use 'hash tags' to help this, i.e. '{/users/12345}/account' and '{/users/12345}/contacts' will always be in the same slot",ex.Message);
Assert.Equal("Multi-key operations must involve a single slot; keys can use 'hash tags' to help this, i.e. '{/users/12345}/account' and '{/users/12345}/contacts' will always be in the same slot",ex.Message);
//Flags expect commas as separators, but we need to use '|' since commas are already used in the connection string to mean something else
//Flags expect commas as separators, but we need to use '|' since commas are already used in the connection string to mean something else
value=value?.Replace("|",",");
value=value?.Replace("|",",");
if(!Enum.TryParse(value,true,outSslProtocolstmp))thrownewArgumentOutOfRangeException("Keyword '"+key+"' requires an SslProtocol value (multiple values separated by '|').");
if(!Enum.TryParse(value,true,outSslProtocolstmp))thrownewArgumentOutOfRangeException("Keyword '"+key+"' requires an SslProtocol value (multiple values separated by '|').");
returntmp;
returntmp;
}
}
internalstaticvoidUnknown(stringkey)
internalstaticvoidUnknown(stringkey)
{
{
thrownewArgumentException("Keyword '"+key+"' is not supported");
thrownewArgumentException("Keyword '"+key+"' is not supported");