Example #1
0
        /// <summary>
        /// Removes the serialized objects at the given cache keys from the cache.
        /// </summary>
        /// <param name="cacheKeys">The cache keys.</param>
        public void Remove(IEnumerable<string> cacheKeys)
        {
            // Sanitize
            if (cacheKeys == null)
            {
                throw new ArgumentNullException("cacheKeys");
            }
            if (!cacheKeys.Any())
            {
                throw new ArgumentException("must have at least one element", "cacheKeys");
            }

            byte[] command = null;
            using (var memoryStream = new MemoryStream())
            {
                memoryStream.WriteControlBytePlaceHolder();
                memoryStream.Write("del");
                foreach (var cacheKey in cacheKeys)
                {
                    memoryStream.WriteSpace();
                    memoryStream.Write(cacheKey);
                }
                command = memoryStream.ToArray();
            }

            // Set control byte
            command.SetControlByte(DacheProtocolHelper.MessageType.RepeatingCacheKeys);
            // Send
            _client.Send(command);
        }
Example #2
0
        /// <summary>
        /// Removes all serialized objects associated with the given tag names and optionally with keys matching the given pattern.
        /// WARNING: THIS IS A VERY EXPENSIVE OPERATION FOR LARGE TAG CACHES. USE WITH CAUTION.
        /// </summary>
        /// <param name="tagNames">The tag names.</param>
        /// <param name="pattern">The search pattern (RegEx). Optional. If not specified, the default of "*" is used to indicate match all.</param>
        public void RemoveTagged(IEnumerable<string> tagNames, string pattern = "*")
        {
            // Sanitize
            if (tagNames == null)
            {
                throw new ArgumentNullException("tagNames");
            }
            if (!tagNames.Any())
            {
                throw new ArgumentException("must have at least one element", "tagNames");
            }
            if (string.IsNullOrWhiteSpace(pattern))
            {
                throw new ArgumentException("cannot be null, empty, or white space", "pattern");
            }

            byte[] command;
            using (var memoryStream = new MemoryStream())
            {
                memoryStream.WriteControlBytePlaceHolder();
                memoryStream.Write("del-tag");
                memoryStream.WriteSpace();
                memoryStream.Write(pattern);
                foreach (var tagName in tagNames)
                {
                    memoryStream.WriteSpace();
                    memoryStream.Write(tagName);
                }
                command = memoryStream.ToArray();
            }

            // Set control byte
            command.SetControlByte(DacheProtocolHelper.MessageType.RepeatingCacheKeys);
            // Send
            _client.Send(command);
        }
Example #3
0
        /// <summary>
        /// Gets all serialized objects associated with the given tag name.
        /// </summary>
        /// <param name="tagNames">The tag names.</param>
        /// <returns>A list of the serialized objects.</returns>
        public List<byte[]> GetTagged(IEnumerable<string> tagNames)
        {
            // Sanitize
            if (tagNames == null)
            {
                throw new ArgumentNullException("tagNames");
            }
            if (!tagNames.Any())
            {
                throw new ArgumentException("must have at least one element", "tagNames");
            }

            byte[] command = null;
            using (var memoryStream = new MemoryStream())
            {
                memoryStream.WriteControlBytePlaceHolder();
                memoryStream.Write("get-tag");
                foreach (var tagName in tagNames)
                {
                    memoryStream.WriteSpace();
                    memoryStream.Write(tagName);
                }
                command = memoryStream.ToArray();
            }

            // Set control byte
            command.SetControlByte(DacheProtocolHelper.MessageType.RepeatingCacheKeys);
            // Send and receive
            command = _client.SendReceive(command);
            // Parse string
            var commandResult = DacheProtocolHelper.CommunicationEncoding.GetString(command);

            // Verify that we got something
            if (commandResult == null)
            {
                return null;
            }

            // Parse command from bytes
            var commandResultParts = commandResult.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            return ParseCacheObjects(commandResultParts);
        }
Example #4
0
        /// <summary>
        /// Gets all cache keys associated with the given tag names and optionally matching the given pattern.
        /// WARNING: THIS IS A VERY EXPENSIVE OPERATION FOR LARGE TAG CACHES. USE WITH CAUTION.
        /// </summary>
        /// <param name="tagNames">The tag names.</param>
        /// <param name="pattern">The search pattern (RegEx). Optional. If not specified, the default of "*" is used to indicate match all.</param>
        /// <returns>The list of cache keys matching the provided pattern.</returns>
        public List<byte[]> GetCacheKeysTagged(IEnumerable<string> tagNames, string pattern = "*")
        {
            if (tagNames == null)
            {
                throw new ArgumentNullException("tagNames");
            }
            if (!tagNames.Any())
            {
                throw new ArgumentException("must have at least one element", "tagNames");
            }
            if (string.IsNullOrWhiteSpace(pattern))
            {
                throw new ArgumentException("cannot be null, empty, or white space", "pattern");
            }

            byte[] command;
            using (var memoryStream = new MemoryStream())
            {
                memoryStream.WriteControlBytePlaceHolder();
                memoryStream.Write("keys-tag");
                memoryStream.WriteSpace();
                memoryStream.Write(pattern);
                foreach (var tagName in tagNames)
                {
                    memoryStream.WriteSpace();
                    memoryStream.Write(tagName);
                }
                command = memoryStream.ToArray();
            }

            // Set control byte
            command.SetControlByte(DacheProtocolHelper.MessageType.Literal);
            // Send and receive
            var rawResult = _client.SendReceive(command);

            // Verify that we got something
            if (rawResult == null)
            {
                return null;
            }

            // Parse string
            var decodedResult = DacheProtocolHelper.CommunicationEncoding.GetString(rawResult);
            if (string.IsNullOrWhiteSpace(decodedResult))
            {
                return null;
            }

            // Parse command from bytes
            var commandResultParts = decodedResult.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            return ParseCacheObjects(commandResultParts);
        }
Example #5
0
        /// <summary>
        /// Adds or updates the interned serialized objects in the cache at the given cache keys.
        /// NOTE: interned objects use significantly less memory when placed in the cache multiple times however cannot expire or be evicted. 
        /// You must remove them manually when appropriate or else you may face a memory leak.
        /// </summary>
        /// <param name="cacheKeysAndSerializedObjects">The cache keys and associated serialized objects.</param>
        /// <param name="tagName">The tag name.</param>
        public void AddOrUpdateTaggedInterned(IEnumerable<KeyValuePair<string, byte[]>> cacheKeysAndSerializedObjects, string tagName)
        {
            // Sanitize
            if (cacheKeysAndSerializedObjects == null)
            {
                throw new ArgumentNullException("cacheKeysAndSerializedObjects");
            }
            if (!cacheKeysAndSerializedObjects.Any())
            {
                throw new ArgumentException("must have at least one element", "cacheKeysAndSerializedObjects");
            }
            if (string.IsNullOrWhiteSpace(tagName))
            {
                throw new ArgumentException("cannot be null, empty, or white space", "tagName");
            }

            byte[] command = null;
            using (var memoryStream = new MemoryStream())
            {
                memoryStream.WriteControlBytePlaceHolder();
                memoryStream.Write("set-tag-intern {0}", tagName);
                foreach (var cacheKeyAndSerializedObjectKvp in cacheKeysAndSerializedObjects)
                {
                    memoryStream.WriteSpace();
                    memoryStream.Write(cacheKeyAndSerializedObjectKvp.Key);
                    memoryStream.WriteSpace();
                    memoryStream.WriteBase64(cacheKeyAndSerializedObjectKvp.Value);
                }
                command = memoryStream.ToArray();
            }

            // Set control byte
            command.SetControlByte(DacheProtocolHelper.MessageType.RepeatingCacheKeysAndObjects);
            // Send
            _client.Send(command);
        }
Example #6
0
        /// <summary>
        /// Adds or updates the serialized objects in the cache at the given cache keys.
        /// </summary>
        /// <param name="cacheKeysAndSerializedObjects">The cache keys and associated serialized objects.</param>
        /// <param name="slidingExpiration">The sliding expiration.</param>
        public void AddOrUpdate(IEnumerable<KeyValuePair<string, byte[]>> cacheKeysAndSerializedObjects, TimeSpan slidingExpiration)
        {
            // Sanitize
            if (cacheKeysAndSerializedObjects == null)
            {
                throw new ArgumentNullException("cacheKeysAndSerializedObjects");
            }
            if (!cacheKeysAndSerializedObjects.Any())
            {
                throw new ArgumentException("must have at least one element", "cacheKeysAndSerializedObjects");
            }

            byte[] command = null;
            using (var memoryStream = new MemoryStream())
            {
                memoryStream.WriteControlBytePlaceHolder();
                memoryStream.Write("set {0}", (int)slidingExpiration.TotalSeconds);
                foreach (var cacheKeyAndSerializedObjectKvp in cacheKeysAndSerializedObjects)
                {
                    memoryStream.WriteSpace();
                    memoryStream.Write(cacheKeyAndSerializedObjectKvp.Key);
                    memoryStream.WriteSpace();
                    memoryStream.WriteBase64(cacheKeyAndSerializedObjectKvp.Value);
                }
                command = memoryStream.ToArray();
            }

            // Set control byte
            command.SetControlByte(DacheProtocolHelper.MessageType.RepeatingCacheKeysAndObjects);
            // Send
            _client.Send(command);
        }
Example #7
0
        private byte[] ProcessCommand(string command, DacheProtocolHelper.MessageType messageType)
        {
            // Sanitize
            if (command == null)
            {
                return null;
            }
            if (string.IsNullOrWhiteSpace(command))
            {
                return null;
            }

            string[] commandParts = command.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            if (commandParts.Length == 0)
            {
                return null;
            }

            List<byte[]> results;
            byte[] commandResult = null;

            switch (messageType)
            {
                case DacheProtocolHelper.MessageType.Literal:
                {
                    if (string.Equals(commandParts[0], "keys", StringComparison.OrdinalIgnoreCase))
                    {
                        // Sanitize the command
                        if (commandParts.Length != 2)
                        {
                            return null;
                        }

                        var pattern = commandParts[1];
                        results = GetCacheKeys(pattern);
                        // Structure the results for sending
                        using (var memoryStream = new MemoryStream())
                        {
                            for (int i = 0; i < results.Count; i++)
                            {
                                if (i != 0)
                                {
                                    memoryStream.WriteSpace();
                                }
                                memoryStream.WriteBase64(results[i]);
                            }
                            commandResult = memoryStream.ToArray();
                        }
                    }
                    else if (string.Equals(commandParts[0], "clear", StringComparison.OrdinalIgnoreCase))
                    {
                        Clear();
                    }

                    break;
                }
                case DacheProtocolHelper.MessageType.RepeatingCacheKeys:
                {
                    // Determine command
                    if (string.Equals(commandParts[0], "get", StringComparison.OrdinalIgnoreCase))
                    {
                        // Sanitize the command
                        if (commandParts.Length < 2)
                        {
                            return null;
                        }

                        var cacheKeys = commandParts.Skip(1);
                        results = Get(cacheKeys);
                        // Structure the results for sending
                        using (var memoryStream = new MemoryStream())
                        {
                            for (int i = 0; i < results.Count; i++)
                            {
                                if (i != 0)
                                {
                                    memoryStream.WriteSpace();
                                }
                                memoryStream.WriteBase64(results[i]);
                            }
                            commandResult = memoryStream.ToArray();
                        }
                    }
                    if (string.Equals(commandParts[0], "get-tag", StringComparison.OrdinalIgnoreCase))
                    {
                        // Sanitize the command
                        if (commandParts.Length < 2)
                        {
                            return null;
                        }

                        var tagNames = commandParts.Skip(1);
                        results = GetTagged(tagNames);
                        // Structure the results for sending
                        using (var memoryStream = new MemoryStream())
                        {
                            for (int i = 0; i < results.Count; i++)
                            {
                                if (i != 0)
                                {
                                    memoryStream.WriteSpace();
                                }
                                memoryStream.WriteBase64(results[i]);
                            }
                            commandResult = memoryStream.ToArray();
                        }
                    }
                    else if (string.Equals(commandParts[0], "del-tag", StringComparison.OrdinalIgnoreCase))
                    {
                        // sample commands:
                        // del-tag * tagName1
                        // del-tag * tagName1 tagName2
                        // del-tag myPrefix* tagName1 tagName2

                        // Sanitize the command
                        if (commandParts.Length < 3)
                        {
                            return null;
                        }

                        var pattern = commandParts[1];
                        var tagNames = commandParts.Skip(2);
                        RemoveTagged(tagNames, pattern);
                    }
                    else if (string.Equals(commandParts[0], "del", StringComparison.OrdinalIgnoreCase))
                    {
                        // Sanitize the command
                        if (commandParts.Length < 2)
                        {
                            return null;
                        }

                        var cacheKeys = commandParts.Skip(1);
                        Remove(cacheKeys);
                    }
                    else if (string.Equals(commandParts[0], "keys-tag", StringComparison.OrdinalIgnoreCase))
                    {
                        // Sanitize the command
                        if (commandParts.Length < 3)
                        {
                            return null;
                        }

                        var pattern = commandParts[1];
                        var tagNames = commandParts.Skip(2);
                        results = GetCacheKeysTagged(tagNames, pattern);
                        // Structure the results for sending
                        using (var memoryStream = new MemoryStream())
                        {
                            for (int i = 0; i < results.Count; i++)
                            {
                                if (i != 0)
                                {
                                    memoryStream.WriteSpace();
                                }
                                memoryStream.WriteBase64(results[i]);
                            }
                            commandResult = memoryStream.ToArray();
                        }
                    }

                    break;
                }
                case DacheProtocolHelper.MessageType.RepeatingCacheKeysAndObjects:
                {
                    // Determine command
                    IEnumerable<KeyValuePair<string, byte[]>> cacheKeysAndObjects;
                    if (string.Equals(commandParts[0], "set-tag-intern", StringComparison.OrdinalIgnoreCase))
                    {
                        // Only one method, so call it
                        if (commandParts.Length == 2)
                        {
                            cacheKeysAndObjects = ParseCacheKeysAndObjects(commandParts, 2);
                            AddOrUpdateTaggedInterned(cacheKeysAndObjects, commandParts[1]);
                        }
                    }
                    else if (string.Equals(commandParts[0], "set-intern", StringComparison.OrdinalIgnoreCase))
                    {
                        // Only one method, so call it
                        cacheKeysAndObjects = ParseCacheKeysAndObjects(commandParts, 1);
                        AddOrUpdateInterned(cacheKeysAndObjects);
                    }
                    else if (string.Equals(commandParts[0], "set-tag", StringComparison.OrdinalIgnoreCase))
                    {
                        // set-tag command should have no less than 4 parts: set-tag tagName keyName keyValue
                        if (commandParts.Length < 4)
                        {
                            return null;
                        }

                        // Check whether we have absolute or sliding options
                        if (commandParts.Length % 2 == 0)
                        {
                            // Regular set
                            cacheKeysAndObjects = ParseCacheKeysAndObjects(commandParts, 2);
                            AddOrUpdateTagged(cacheKeysAndObjects, commandParts[1]);
                        }
                        else
                        {
                            // Get absolute or sliding expiration
                            int slidingExpiration;
                            DateTimeOffset absoluteExpiration;
                            if (int.TryParse(commandParts[2], out slidingExpiration))
                            {
                                // Sliding expiration
                                cacheKeysAndObjects = ParseCacheKeysAndObjects(commandParts, 3);
                                AddOrUpdateTagged(cacheKeysAndObjects, commandParts[1], TimeSpan.FromSeconds(slidingExpiration));
                            }
                            else if (DateTimeOffset.TryParseExact(commandParts[2], DacheProtocolHelper.AbsoluteExpirationFormat, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out absoluteExpiration))
                            {
                                // Absolute expiration
                                cacheKeysAndObjects = ParseCacheKeysAndObjects(commandParts, 3);
                                AddOrUpdateTagged(cacheKeysAndObjects, commandParts[1], absoluteExpiration);
                            }
                        }
                    }
                    else if (string.Equals(commandParts[0], "set", StringComparison.OrdinalIgnoreCase))
                    {
                        // Check whether we have absolute or sliding options
                        if (commandParts.Length % 2 == 1)
                        {
                            // Regular set
                            cacheKeysAndObjects = ParseCacheKeysAndObjects(commandParts, 1);
                            AddOrUpdate(cacheKeysAndObjects);
                        }
                        else
                        {
                            // Get absolute or sliding expiration
                            int slidingExpiration;
                            DateTimeOffset absoluteExpiration;
                            if (int.TryParse(commandParts[1], out slidingExpiration))
                            {
                                // sliding expiration
                                cacheKeysAndObjects = ParseCacheKeysAndObjects(commandParts, 2);
                                AddOrUpdate(cacheKeysAndObjects, TimeSpan.FromSeconds(slidingExpiration));
                            }
                            else if (DateTimeOffset.TryParseExact(commandParts[1], DacheProtocolHelper.AbsoluteExpirationFormat, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out absoluteExpiration))
                            {
                                // absolute expiration
                                cacheKeysAndObjects = ParseCacheKeysAndObjects(commandParts, 2);
                                AddOrUpdate(cacheKeysAndObjects, absoluteExpiration);
                            }
                        }
                    }

                    break;
                }
            }

            // Return the result - may be null if there was no valid message
            return commandResult;
        }