Esempio n. 1
0
        /// <summary>
        /// For internal use; use the parameterless overload for effeciency.
        /// </summary>
        /// <param name="host"></param>
        /// <returns></returns>
        public static string ComputeHostHash(string host)
        {
            long   sum  = new long?(getBytesSum(computeMd5(host), 36, 2)).Value;
            string hash = Base36Converter.Encode(sum);

            return(hash);
        }
Esempio n. 2
0
        /// <summary>
        /// Compresses the MD5 of this server's hostname by summing the bytes until the sum
        /// fits into two Base36 characters (<= 36^2, or 1296):
        /// </summary>
        /// <returns>2 character Base36 checksum of MD5 of hostname</returns>
        public static string ComputeHostHash()
        {
            string hash = Base36Converter.Encode(
                (_hostSum.HasValue ? _hostSum.Value : (
                     _hostSum = new long?(getBytesSum(computeMd5(getHostBytes()), 36, 2))).Value));

            return(hash);
        }
Esempio n. 3
0
        /// <summary>
        /// Returns a random Base36 number 3 characters long.
        /// </summary>
        /// <returns></returns>
        private static string getRandomDigits()
        {
            Int32 rndInt;

            lock (_lockObj)
            {
                rndInt = _rnd.Next(46655);
            }
            return(Base36Converter.Encode(rndInt));
        }
Esempio n. 4
0
        /// <summary>
        /// Returns value with all non base 36 characters removed.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Base36Id Parse(string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                throw new ArgumentNullException(paramName: "value");
            }
            string ret = _regex.Replace(value, "").ToUpper();

            if (ret.Length != 16)
            {
                throw new ArgumentException("Value was not a valid Base36 id", "value");
            }

            Base36Id fields = new Base36Id
            {
                Id        = ret,
                HostHash  = ret.Substring(10, 2),
                Reserved  = ret.Substring(12, 1),
                InService = _inService
            };
            int pos           = Base36Converter.CharList.IndexOf(fields.Reserved, System.StringComparison.Ordinal);
            int centuryCycles = Math.Max(0, ((35 - pos) - 1));
            // some precision is lost, as chars beyond 10 weren't originally from the timestamp
            // component of the ID:
            int probableEncodedLength =
                Base36Converter.FromInt64(InServiceDate.AddDays(365.25 * 115.89 * centuryCycles).Ticks / 10).Length;

            if (centuryCycles == 0)
            {
                probableEncodedLength = 10;
            }
            string encodedMs = ret.Substring(0, probableEncodedLength);
            long   ms        = Base36Converter.Decode(encodedMs);

            fields.Microseconds   = ms;
            fields.CreatedRoughly = _inService.AddTicks(ms * 10);             //.AddTicks((3656158440062976 * 10 + 9) * centuryCycles);
            return(fields);
        }
Esempio n. 5
0
        /// <summary>
        /// Generates a unique, sequential, Base36 string, 16 characters long.
        /// The first 10 characters are the microseconds elapsed since the InService DateTime
        ///		(constant field you hardcode in this file).
        /// The next 2 characters are a compressed checksum of the MD5 of this host.
        /// The next 1 character is a reserved constant of 36 ('Z' in Base36).
        /// The last 3 characters are random number less than 46655 additional for additional uniqueness.
        /// </summary>
        /// <param name="delimiter">If provided, formats the ID as four groups of
        /// 4 characters separated by the delimiter.</param>
        /// <returns>Returns a unique, sequential, 16-character Base36 string</returns>
        public static string NewBase36String(string delimiter)
        {
            // For 10 chars from timestamp, microseconds since InService, uses Stopwatch...
            long microseconds = initStaticsReturnMicroseconds();

            // For 2 chars from host id MD5...
            string hostHash = (_hostHash ?? (_hostHash = ComputeHostHash()));

            // 1 reserved char; static largest base36 digit.
            // If the same ID system, scheme and sequence is still in use
            // more than 115.85 years after in-service date, decrements
            // 'reserved' by 1 for each whole multiple of 115 years
            // elapsed, up to 35 times max. If the same system, scheme
            // and sequence is still in service 3,850 years from the
            // initial go-live, you probably have bigger problems than
            // ID collisions...
            int reserved = _reserved;

            // 3 chars random in Base36 = 46656 units
            string        rndHexStr = getRandomDigits();
            StringBuilder sb        = new StringBuilder();

            sb.Append(Base36Converter.FromInt64(microseconds).PadLeft(10, '0'));
            sb.Length = 10;
            sb.Append(hostHash.PadLeft(2, '0'));
            sb.Length = 12;
            sb.Append(Base36Converter.FromInt32(reserved));
            sb.Length = 13;
            sb.Append(Base36Converter.FromHex(rndHexStr).PadLeft(3, '0'));
            sb.Length = 16;
            if (!string.IsNullOrEmpty(delimiter))
            {
                sb.Insert(12, delimiter);
                sb.Insert(8, delimiter);
                sb.Insert(4, delimiter);
            }
            return(sb.ToString());
        }