Example #1
0
        public void Delete(Guid id)
        {
            var ids    = new List <Guid>();
            var nextId = id;

            var block = new BinaryDataStorageClass();

            do
            {
                block.Id = nextId;
                if (!_file.Get(block))
                {
                    break;
                }

                ids.Add(nextId);

                nextId = block.NextBlock;
            } while (block.NextBlock != null);

            ids.Reverse();
            foreach (var deleteId in ids)
            {
                block.Id = deleteId;
                _file.Delete(block);
            }
        }
Example #2
0
        /// <summary>
        /// Add a binary to the file and store the data in the data cache.
        ///
        /// It should be noted that there is a failure mode in which the commit of the binary details file could work, but the commit
        /// of the data could fail. This would result in the record of the binary being stored, but no actual data would be present
        /// in the files. This would manifest itself as an exception, which is caught here, and an attempt to remove the binary details
        /// is made. In the event that the data commit fails because of catastrophic failure or power loss, the recovery attempt may not
        /// take place or may itself fail. This would leave the data in an inconsistent state, but only for the most recently saved binary.
        ///
        /// On open, the most recently saved binary is checked, to see if the data is present. If it is not, it is removed at that stage.
        /// On the assumption that the failure to
        /// </summary>
        /// <param name="details"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public Guid Add(BinaryStorageClass details, byte[] data)
        {
            lock (_lock)
            {
                try
                {
                    if (details.Id == Guid.Empty)
                    {
                        details.Id = Guid.NewGuid();
                    }
                    details.FileIndex        = _nextIndex++;
                    details.FirstDataBlockId = _data.Write(data);
                    _file.Write(details);
                    _file.Commit();

                    _binaries.Add(details.Id, details);

                    //Make sure that the file is removed if commit fails.
                    Action reverseOutFile = () =>
                    {
                        // ReSharper disable AccessToDisposedClosure
                        //Note: Resharper cannot determine whether the lambda will outlive the try/catch block. It can't so we can ignore the warning.
                        _file.Delete(details);
                        _file.Commit();
                        // ReSharper restore AccessToDisposedClosure
                    };

                    using (var reverse = new OnError(reverseOutFile))
                    {
                        _data.Commit();
                        reverse.Commit(); //if we reach here, the commit worked and we don't need to reverse out the file.
                    }

                    return(details.Id);
                }
                catch
                {
                    _file.Dispose();
                    _file = null;
                    Open(_path);
                    _data.ReOpen();
                    throw;
                }
            }
        }