Esempio n. 1
0
        /// <summary>
        /// Shrinks database transactions and reduces file size on disk
        /// </summary>
        /// <returns></returns>
        public async Task <ShrinkInfo> Shrink()
        {
            ShrinkInfo info = null;

            try
            {
                Stream        stream = File.GetStream();
                List <string> msgs;
                long          position;
                int           count;

                await WaitForLock();

                try
                {
                    count    = _deletedMessages.Count;
                    position = stream.Position;
                    msgs     = _deletedMessages.Count > 0
                               ? new List <string>(_deletedMessages)
                               : new List <string>();
                }
                finally
                {
                    ReleaseLock();
                }

                info = await _shrinkManager.Shrink(position, msgs);

                //sync deleted messages array
                if (info.Successful)
                {
                    if (count > 0)
                    {
                        await WaitForLock();

                        try
                        {
                            if (_deletedMessages.Count > count)
                            {
                                _deletedMessages = _deletedMessages.GetRange(count, _deletedMessages.Count - count);
                            }
                            else
                            {
                                _deletedMessages.Clear();
                            }
                        }
                        finally
                        {
                            ReleaseLock();
                        }
                    }
                }

                OnShrink?.Invoke(this, info);
            }
            catch (Exception ex)
            {
                if (info == null)
                {
                    info = new ShrinkInfo();
                }

                info.Error = ex;
                TriggerError(ErrorHint.Shrink, ex);
            }

            return(info);
        }
Esempio n. 2
0
        /// <summary>
        /// Shrinks database file from begin to position pointer.
        /// This is a partial shrink and can run almost without any lock and thread-block operations.
        /// </summary>
        public async Task <ShrinkInfo> Shrink(long position, List <string> deletedMessages)
        {
            _info = new ShrinkInfo();

            if (_shrinking)
            {
                return(_info);
            }

            Stopwatch sw = new Stopwatch();

            sw.Start();

            try
            {
                _shrinking        = true;
                _end              = position;
                _deletingMessages = new HashSet <string>(deletedMessages);
                _info.OldSize     = _end;

                if (_source != null)
                {
                    await DisposeSource();
                }

                await using (FileStream file = new FileStream(_database.File.Filename, FileMode.Open, FileAccess.Read))
                {
                    int capacity = Convert.ToInt32(_end);
                    _source = new MemoryStream(capacity);
                    await CopyStream(file, _source, capacity);

                    _source.Position = 0;
                }

                _target = new FileStream(_database.File.Filename + ".shrink", FileMode.Create, FileAccess.Write);

                sw.Stop();
                _info.PreparationDuration = sw.Elapsed;
                sw.Reset();
                sw.Start();

                bool proceed = await ProcessShrink();

                sw.Stop();
                _info.TruncateDuration = sw.Elapsed;
                sw.Reset();

                if (!proceed)
                {
                    _shrinking = false;
                    return(_info);
                }

                sw.Start();
                bool sync = await SyncShrink();

                sw.Stop();

                _info.SyncDuration = sw.Elapsed;
                _info.Successful   = sync;

                return(_info);
            }
            finally
            {
                ShrinkRequired = false;
                _shrinking     = false;
            }
        }