Пример #1
0
        public long TryAppend(byte[] buffer, TapeAppendCondition appendCondition = new TapeAppendCondition())
        {
            if (buffer == null)
                throw new ArgumentNullException("buffer");

            if (buffer.Length == 0)
                throw new ArgumentException("Buffer must contain at least one byte.");

            try
            {
                var result = _dictionary.AddOrUpdate(_name, s =>
                {
                    appendCondition.Enforce(0);
                    var records = new List<TapeRecord>();
                    records.Add(new TapeRecord(1, buffer));
                    return records;
                }, (s, list) =>
                {
                    appendCondition.Enforce(list.Count);
                    return list.Concat(new[] {new TapeRecord(list.Count + 1, buffer)}).ToList();
                });

                return result.Count;
            }
            catch (TapeAppendConditionException e)
            {
                return 0;
            }
        }
Пример #2
0
        public bool AppendNonAtomic(IEnumerable <byte[]> records, TapeAppendCondition condition = default(TapeAppendCondition))
        {
            if (records == null)
            {
                throw new ArgumentNullException("records");
            }

            return(Write(w =>
            {
                var version = w.IndexWriter.BaseStream.Position / sizeof(long);

                if (!condition.Satisfy(version))
                {
                    return false;
                }

                var recordsArray = records.ToArray();

                if (version > long.MaxValue - 1)
                {
                    throw new IndexOutOfRangeException("Version is more than long.MaxValue.");
                }

                Append(w, recordsArray, version + 1);

                return true;
            }));
        }
Пример #3
0
        public long TryAppend(byte[] buffer, TapeAppendCondition condition)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }

            if (buffer.Length == 0)
            {
                throw new ArgumentException("Buffer must contain at least one byte.");
            }

            using (var file = OpenForWrite())
            {
                // we need to know version first.
                file.Seek(0, SeekOrigin.End);
                var version = TapeStreamSerializer.ReadVersionFromTheEnd(file);

                if (!condition.Satisfy(version))
                {
                    return(0);
                }

                var versionToWrite = version + 1;
                TapeStreamSerializer.WriteRecord(file, buffer, versionToWrite);

                return(versionToWrite);
            }
        }
Пример #4
0
        public long TryAppend(byte[] buffer, TapeAppendCondition appendCondition = new TapeAppendCondition())
        {
            if (buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }

            if (buffer.Length == 0)
            {
                throw new ArgumentException("Buffer must contain at least one byte.");
            }

            try
            {
                var result = _dictionary.AddOrUpdate(_name, s =>
                {
                    appendCondition.Enforce(0);
                    var records = new List <TapeRecord>();
                    records.Add(new TapeRecord(1, buffer));
                    return(records);
                }, (s, list) =>
                {
                    appendCondition.Enforce(list.Count);
                    return(list.Concat(new[] { new TapeRecord(list.Count + 1, buffer) }).ToList());
                });

                return(result.Count);
            }
            catch (TapeAppendConditionException e)
            {
                return(0);
            }
        }
Пример #5
0
        public bool TryAppend(byte[] buffer, TapeAppendCondition condition)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }

            if (buffer.Length == 0)
            {
                throw new ArgumentException("Buffer must contain at least one byte.");
            }

            try
            {
                _storage.AddOrUpdate(_name, s =>
                {
                    condition.Enforce(0);
                    return(new List <byte[]>
                    {
                        buffer
                    });
                }, (s, list) =>
                {
                    condition.Enforce(list.Count);
                    list.Add(buffer);
                    return(list);
                });
                return(true);
            }
            catch (TapeAppendConditionException)
            {
                return(false);
            }
        }
Пример #6
0
        public long TryAppend(byte[] buffer, TapeAppendCondition condition)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }

            if (buffer.Length == 0)
            {
                throw new ArgumentException("Buffer must contain at least one byte.");
            }

            return(Write(w => TryAppendInternal(w, buffer, condition)));
        }
Пример #7
0
        static long TryAppendInternal(Writers writers, byte[] buffer, TapeAppendCondition condition)
        {
            var version = writers.IndexWriter.BaseStream.Position / sizeof(long);

            if (!condition.Satisfy(version))
            {
                return(0);
            }

            if (version > long.MaxValue - 1)
            {
                throw new IndexOutOfRangeException("Version is more than long.MaxValue.");
            }

            Append(writers, new[] { buffer }, version + 1);
            return(version + 1);
        }
        public long TryAppend(byte[] buffer, TapeAppendCondition appendCondition = new TapeAppendCondition())
        {
            if (buffer == null)
                throw new ArgumentNullException("buffer");

            if (buffer.Length == 0)
                throw new ArgumentException("Buffer must contain at least one byte.");

            long version;
            int lastBlockSize;
            long offset;
            long firstVersion;
            long count;
            List<string> blockNames;

            var blob = _container.GetBlockBlobReference(_blobName);
            if (blob.Exists())
            {
                var blockList = blob.DownloadBlockList().ToArray();
                blockNames = blockList.Select(bl => bl.Name).ToList();
                var lastBlock = blockList.LastOrDefault();

                if (default(ListBlockItem) == lastBlock)
                {
                    version = 0;
                    lastBlockSize = int.MaxValue;
                    offset = 0;
                    firstVersion = 1;
                    count = 0;
                }
                else
                {
                    var nameInfo = Naming.GetInfo(DecodeName(lastBlock.Name));
                    firstVersion = nameInfo.FirstVersion;
                    version = nameInfo.FirstVersion - 1 + nameInfo.Count;
                    count = nameInfo.Count;

                    if (lastBlock.Size > int.MaxValue)
                        throw new InvalidOperationException("last block size must be in 'int' range");

                    lastBlockSize = (int) lastBlock.Size;
                    offset = blockList.Reverse().Skip(1).Sum(l => l.Size);
                }
            }
            else
            {
                version = 0;
                lastBlockSize = int.MaxValue;
                offset = 0;
                firstVersion = 1;
                count = 0;
                blockNames = new List<string>();
            }

            if (!appendCondition.Satisfy(version))
                return 0;

            if (version > long.MaxValue - 1)
                throw new IndexOutOfRangeException("Version is more than long.MaxValue.");

            if (buffer.Length > FourMb)
                throw new ArgumentException("buffer size must be less than or equal to 4 Mb", "buffer");

            using (var outStream = new MemoryStream())
            {
                if (buffer.Length < MaxBlockSize && lastBlockSize <= MaxBlockSize - buffer.Length)
                {
                    // read old block
                    using (var s = blob.OpenRead())
                    {
                        s.Seek(offset, SeekOrigin.Begin);
                        s.CopyTo(outStream);
                        TapeStreamSerializer.WriteRecord(outStream, buffer, version + 1);

                        count++;
                        blockNames.RemoveAt(blockNames.Count - 1);
                    }
                }
                else
                {
                    TapeStreamSerializer.WriteRecord(outStream, buffer, version + 1);

                    firstVersion = version + 1;
                    count = 1;
                }

                var blockId = EncodeName(Naming.GetName(firstVersion, count));

                string md5Hash;
                outStream.Seek(0, SeekOrigin.Begin);
                using (var md5 = MD5.Create()) {
                    md5Hash = Convert.ToBase64String(md5.ComputeHash(outStream));
                }

                outStream.Seek(0, SeekOrigin.Begin);
                blob.PutBlock(blockId, outStream, md5Hash);
                blockNames.Add(blockId);
                blob.PutBlockList(blockNames);

                return version+1;
            }
        }
Пример #9
0
        public bool TryAppend(byte[] buffer, TapeAppendCondition condition)
        {
            if (buffer == null)
                throw new ArgumentNullException("buffer");

            if (buffer.Length == 0)
                throw new ArgumentException("Buffer must contain at least one byte.");

            using (var file = OpenForWrite())
            {
                // we need to know version first.
                file.Seek(0, SeekOrigin.End);
                var version = TapeStreamSerializer.ReadVersionFromTheEnd(file);

                if (!condition.Satisfy(version))
                    return false;

                var versionToWrite = version + 1;
                TapeStreamSerializer.WriteRecord(file, buffer, versionToWrite);

                return true;
            }
        }
        public long TryAppend(byte[] buffer, TapeAppendCondition appendCondition = new TapeAppendCondition())
        {
            if (buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }

            if (buffer.Length == 0)
            {
                throw new ArgumentException("Buffer must contain at least one byte.");
            }

            long          version;
            int           lastBlockSize;
            long          offset;
            long          firstVersion;
            long          count;
            List <string> blockNames;

            var blob = _container.GetBlockBlobReference(_blobName);

            if (blob.Exists())
            {
                var blockList = blob.DownloadBlockList().ToArray();
                blockNames = blockList.Select(bl => bl.Name).ToList();
                var lastBlock = blockList.LastOrDefault();

                if (default(ListBlockItem) == lastBlock)
                {
                    version       = 0;
                    lastBlockSize = int.MaxValue;
                    offset        = 0;
                    firstVersion  = 1;
                    count         = 0;
                }
                else
                {
                    var nameInfo = Naming.GetInfo(DecodeName(lastBlock.Name));
                    firstVersion = nameInfo.FirstVersion;
                    version      = nameInfo.FirstVersion - 1 + nameInfo.Count;
                    count        = nameInfo.Count;

                    if (lastBlock.Size > int.MaxValue)
                    {
                        throw new InvalidOperationException("last block size must be in 'int' range");
                    }

                    lastBlockSize = (int)lastBlock.Size;
                    offset        = blockList.Reverse().Skip(1).Sum(l => l.Size);
                }
            }
            else
            {
                version       = 0;
                lastBlockSize = int.MaxValue;
                offset        = 0;
                firstVersion  = 1;
                count         = 0;
                blockNames    = new List <string>();
            }

            if (!appendCondition.Satisfy(version))
            {
                return(0);
            }

            if (version > long.MaxValue - 1)
            {
                throw new IndexOutOfRangeException("Version is more than long.MaxValue.");
            }

            if (buffer.Length > FourMb)
            {
                throw new ArgumentException("buffer size must be less than or equal to 4 Mb", "buffer");
            }

            using (var outStream = new MemoryStream())
            {
                if (buffer.Length < MaxBlockSize && lastBlockSize <= MaxBlockSize - buffer.Length)
                {
                    // read old block
                    using (var s = blob.OpenRead())
                    {
                        s.Seek(offset, SeekOrigin.Begin);
                        s.CopyTo(outStream);
                        TapeStreamSerializer.WriteRecord(outStream, buffer, version + 1);

                        count++;
                        blockNames.RemoveAt(blockNames.Count - 1);
                    }
                }
                else
                {
                    TapeStreamSerializer.WriteRecord(outStream, buffer, version + 1);

                    firstVersion = version + 1;
                    count        = 1;
                }

                var blockId = EncodeName(Naming.GetName(firstVersion, count));

                string md5Hash;
                outStream.Seek(0, SeekOrigin.Begin);
                using (var md5 = MD5.Create()) {
                    md5Hash = Convert.ToBase64String(md5.ComputeHash(outStream));
                }

                outStream.Seek(0, SeekOrigin.Begin);
                blob.PutBlock(blockId, outStream, md5Hash);
                blockNames.Add(blockId);
                blob.PutBlockList(blockNames);

                return(version + 1);
            }
        }