Exemple #1
0
 private CorrelationVector(string baseVector, int extension, CorrelationVectorVersion version, bool immutable)
 {
     this.BaseVector = baseVector;
     this.extension  = extension;
     this.Version    = version;
     this.immutable  = immutable || CorrelationVector.IsOversized(baseVector, extension, version);
 }
        /// <summary>
        /// Gets the value of the correlation vector base encoded as a <see cref="Guid"/>.
        /// </summary>
        /// <returns>The <see cref="Guid"/> value of the encoded vector base.</returns>
        public static Guid GetBaseAsGuid(this CorrelationVector correlationVector)
        {
            if (correlationVector.Version == CorrelationVectorVersion.V1)
            {
                throw new InvalidOperationException("Cannot convert a V1 correlation vector base to a guid.");
            }

            if (CorrelationVector.ValidateCorrelationVectorDuringCreation)
            {
                // In order to reliably convert a V2 vector base to a guid, the four least significant bits of the last
                // base64 content-bearing 6-bit block must be zeros.
                // There are four such base64 characters so we can easily detect whether this condition is true.
                // A - 00 0000
                // Q - 01 0000
                // g - 10 0000
                // w - 11 0000
                char lastChar = correlationVector.BaseVector[CorrelationVector.BaseLengthV2 - 1];

                if (lastChar != 'A' && lastChar != 'Q' && lastChar != 'g' && lastChar != 'w')
                {
                    throw new InvalidOperationException(
                              "The four least significant bits of the base64 encoded vector base must be zeros to reliably convert to a guid.");
                }
            }

            return(new Guid(Convert.FromBase64String(correlationVector.BaseVector + "==")));
        }
Exemple #3
0
        /// <summary>
        /// Increments the current extension by one. Do this before passing the value to an
        /// outbound message header.
        /// </summary>
        /// <returns>
        /// The new value as a string that you can add to the outbound message header
        /// indicated by <see cref="HeaderName"/>.
        /// </returns>
        public string Increment()
        {
            if (this.immutable)
            {
                return(this.Value);
            }
            int snapshot = 0;
            int next     = 0;

            do
            {
                snapshot = this.extension;
                if (snapshot == int.MaxValue)
                {
                    return(this.Value);
                }
                next = snapshot + 1;
                if (CorrelationVector.IsOversized(this.BaseVector, next, this.Version))
                {
                    this.immutable = true;
                    return(this.Value);
                }
            }while (snapshot != Interlocked.CompareExchange(ref this.extension, next, snapshot));
            return(string.Concat(this.BaseVector, ".", next));
        }
Exemple #4
0
        /// <summary>
        /// Creates a new correlation vector by applying the Spin operator to an existing value.
        /// This should be done at the entry point of an operation.
        /// </summary>
        /// <param name="correlationVector">
        /// Taken from the message header indicated by <see cref="HeaderName"/>.
        /// </param>
        /// <returns>A new correlation vector extended from the current vector.</returns>
        public static CorrelationVector Spin(string correlationVector)
        {
            SpinParameters defaultParameters = new SpinParameters
            {
                Interval    = SpinCounterInterval.Coarse,
                Periodicity = SpinCounterPeriodicity.Short,
                Entropy     = SpinEntropy.Two
            };

            return(CorrelationVector.Spin(correlationVector, defaultParameters));
        }
Exemple #5
0
        /// <summary>
        /// Creates a new correlation vector by applying the Spin operator to an existing value.
        /// This should be done at the entry point of an operation.
        /// </summary>
        /// <param name="correlationVector">
        /// Taken from the message header indicated by <see cref="HeaderName"/>.
        /// </param>
        /// <param name="parameters">
        /// The parameters to use when applying the Spin operator.
        /// </param>
        /// <returns>A new correlation vector extended from the current vector.</returns>
        public static CorrelationVector Spin(string correlationVector, SpinParameters parameters)
        {
            if (CorrelationVector.IsImmutable(correlationVector))
            {
                return(CorrelationVector.Parse(correlationVector));
            }

            CorrelationVectorVersion version = CorrelationVector.InferVersion(
                correlationVector, CorrelationVector.ValidateCorrelationVectorDuringCreation);

            if (CorrelationVector.ValidateCorrelationVectorDuringCreation)
            {
                CorrelationVector.Validate(correlationVector, version);
            }

            byte[] entropy = new byte[parameters.EntropyBytes];
            rng.NextBytes(entropy);

            ulong value = (ulong)(DateTime.UtcNow.Ticks >> parameters.TicksBitsToDrop);

            for (int i = 0; i < parameters.EntropyBytes; i++)
            {
                value = (value << 8) | Convert.ToUInt64(entropy[i]);
            }

            // Generate a bitmask and mask the lower TotalBits in the value.
            // The mask is generated by (1 << TotalBits) - 1. We need to handle the edge case
            // when shifting 64 bits, as it wraps around.
            value &= (parameters.TotalBits == 64 ? 0 : (ulong)1 << parameters.TotalBits) - 1;

            string s = unchecked ((uint)value).ToString();

            if (parameters.TotalBits > 32)
            {
                s = string.Concat((value >> 32).ToString(), ".", s);
            }

            string baseVector = string.Concat(correlationVector, ".", s);

            if (CorrelationVector.IsOversized(baseVector, 0, version))
            {
                return(CorrelationVector.Parse(correlationVector + CorrelationVector.TerminationSign));
            }

            return(new CorrelationVector(baseVector, 0, version, false));
        }
Exemple #6
0
        /// <summary>
        /// Creates a new correlation vector by parsing its string representation
        /// </summary>
        /// <param name="correlationVector">correlationVector</param>
        /// <returns>CorrelationVector</returns>
        public static CorrelationVector Parse(string correlationVector)
        {
            if (!string.IsNullOrEmpty(correlationVector))
            {
                int  p         = correlationVector.LastIndexOf('.');
                bool immutable = CorrelationVector.IsImmutable(correlationVector);
                if (p > 0)
                {
                    string extensionValue = immutable ? correlationVector.Substring(p + 1, correlationVector.Length - p - 1 - CorrelationVector.TerminationSign.Length)
                        : correlationVector.Substring(p + 1);
                    int extension;
                    if (int.TryParse(extensionValue, out extension) && extension >= 0)
                    {
                        return(new CorrelationVector(correlationVector.Substring(0, p), extension, CorrelationVector.InferVersion(correlationVector, false), immutable));
                    }
                }
            }

            return(new CorrelationVector());
        }
Exemple #7
0
        /// <summary>
        /// Creates a new correlation vector by extending an existing value. This should be
        /// done at the entry point of an operation.
        /// </summary>
        /// <param name="correlationVector">
        /// Taken from the message header indicated by <see cref="HeaderName"/>.
        /// </param>
        /// <returns>A new correlation vector extended from the current vector.</returns>
        public static CorrelationVector Extend(string correlationVector)
        {
            if (CorrelationVector.IsImmutable(correlationVector))
            {
                return(CorrelationVector.Parse(correlationVector));
            }

            CorrelationVectorVersion version = CorrelationVector.InferVersion(
                correlationVector, CorrelationVector.ValidateCorrelationVectorDuringCreation);

            if (CorrelationVector.ValidateCorrelationVectorDuringCreation)
            {
                CorrelationVector.Validate(correlationVector, version);
            }

            if (CorrelationVector.IsOversized(correlationVector, 0, version))
            {
                return(CorrelationVector.Parse(correlationVector + CorrelationVector.TerminationSign));
            }

            return(new CorrelationVector(correlationVector, 0, version, false));
        }
Exemple #8
0
 /// <summary>
 /// Determines whether two instances of the <see cref="CorrelationVector"/> class
 /// are equal.
 /// </summary>
 /// <param name="vector">
 /// The correlation vector you want to compare with the current correlation vector.
 /// </param>
 /// <returns>
 /// True if the specified correlation vector is equal to the current correlation
 /// vector; otherwise, false.
 /// </returns>
 public bool Equals(CorrelationVector vector)
 {
     return(string.Equals(this.Value, vector.Value, StringComparison.Ordinal));
 }
Exemple #9
0
 /// <summary>
 /// Initializes a new instance of the <see cref="CorrelationVector"/> class of the
 /// given implemenation version. This should only be called when no correlation
 /// vector was found in the message header.
 /// </summary>
 /// <param name="version">The correlation vector implemenation version.</param>
 public CorrelationVector(CorrelationVectorVersion version)
     : this(CorrelationVector.GetUniqueValue(version), 0, version, false)
 {
 }