Exemplo n.º 1
0
        /// <summary>
        /// Delete an object stored in the deduplication index.
        /// This method will use the callbacks supplied in the method signature.
        /// </summary>
        /// <param name="objectName">The name of the object.</param>
        /// <param name="callbacks">CallbackMethods object containing callback methods.</param>
        /// <returns>True if successful.</returns>
        public bool DeleteObject(string objectName, CallbackMethods callbacks)
        {
            if (String.IsNullOrEmpty(objectName))
            {
                throw new ArgumentNullException(nameof(objectName));
            }
            if (callbacks == null)
            {
                throw new ArgumentNullException(nameof(callbacks));
            }
            if (callbacks.DeleteChunk == null)
            {
                throw new ArgumentException("DeleteChunk callback must be specified.");
            }
            objectName = DedupeCommon.SanitizeString(objectName);

            List <string> garbageCollectChunks = null;

            lock (_ChunkLock)
            {
                _Database.DeleteObjectChunks(objectName, out garbageCollectChunks);
                if (garbageCollectChunks != null && garbageCollectChunks.Count > 0)
                {
                    foreach (string key in garbageCollectChunks)
                    {
                        if (!callbacks.DeleteChunk(key))
                        {
                            Log("Unable to delete chunk: " + key);
                        }
                    }
                }
            }

            return(true);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Store an object in the deduplication index.
        /// This method will use the callbacks supplied in the method signature.
        /// </summary>
        /// <param name="objectName">The name of the object.  Must be unique in the index.</param>
        /// <param name="callbacks">CallbackMethods object containing callback methods.</param>
        /// <param name="contentLength">The length of the data.</param>
        /// <param name="stream">The stream containing the data.</param>
        /// <param name="chunks">The list of chunks identified during the deduplication operation.</param>
        /// <returns>True if successful.</returns>
        public bool StoreObject(string objectName, CallbackMethods callbacks, long contentLength, Stream stream, out List <Chunk> chunks)
        {
            #region Initialize

            chunks = new List <Chunk>();
            if (String.IsNullOrEmpty(objectName))
            {
                throw new ArgumentNullException(nameof(objectName));
            }
            if (callbacks == null)
            {
                throw new ArgumentNullException(nameof(callbacks));
            }
            if (callbacks.WriteChunk == null)
            {
                throw new ArgumentException("WriteChunk callback must be specified.");
            }
            if (callbacks.DeleteChunk == null)
            {
                throw new ArgumentException("DeleteChunk callback must be specified.");
            }
            if (contentLength < 1)
            {
                throw new ArgumentException("Content length must be at least one byte.");
            }
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }
            if (!stream.CanRead)
            {
                throw new ArgumentException("Cannot read from supplied stream.");
            }
            objectName = DedupeCommon.SanitizeString(objectName);

            if (_Database.ObjectExists(objectName))
            {
                Log("Object " + objectName + " already exists");
                return(false);
            }

            bool garbageCollectionRequired = false;

            #endregion

            #region Chunk-Data

            try
            {
                Func <Chunk, bool> processChunk = delegate(Chunk chunk)
                {
                    if (chunk == null)
                    {
                        return(false);
                    }

                    lock (_ChunkLock)
                    {
                        if (!_Database.AddObjectChunk(objectName, contentLength, chunk))
                        {
                            Log("Unable to add chunk key " + chunk.Key);
                            garbageCollectionRequired = true;
                            return(false);
                        }

                        if (!callbacks.WriteChunk(chunk))
                        {
                            Log("Unable to write chunk key " + chunk.Key);
                            garbageCollectionRequired = true;
                            return(false);
                        }
                    }

                    return(true);
                };

                if (!ChunkStream(contentLength, stream, processChunk, out chunks))
                {
                    Log("Unable to chunk object " + objectName);
                    garbageCollectionRequired = true;
                    return(false);
                }
            }
            finally
            {
                if (garbageCollectionRequired)
                {
                    List <string> garbageCollectKeys = new List <string>();
                    _Database.DeleteObjectChunks(objectName, out garbageCollectKeys);

                    if (garbageCollectKeys != null && garbageCollectKeys.Count > 0)
                    {
                        foreach (string key in garbageCollectKeys)
                        {
                            if (!callbacks.DeleteChunk(key))
                            {
                                Log("Unable to garbage collect chunk " + key);
                            }
                        }
                    }
                }
            }

            #endregion

            return(true);
        }