Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] LiteDB cannot perform actions when disk got full and was then cleared manualy without restart of the program #2286

Open
NazarKobuk opened this issue Feb 14, 2023 · 0 comments
Labels

Comments

@NazarKobuk
Copy link

NazarKobuk commented Feb 14, 2023

Version
LiteDB - 5.0.15
.NET - 6.0.0
Windows - 10

Describe the bug
When the space on the disk with .db files got full - we encounter expected errors that there is not enough space on the disk to perform some of the actions. The problem is when we manually clear the disk, the LiteDB still thinks that there is no space.

Code to Reproduce

public class Program
    {
        private const string TargetFolder = "F:\\Data";
        private const string CacheFileName = "cache.db";

        private static readonly object _lockObject = new object();
        private static ILiteDatabase _db = GetContext();

        public static void Main()
        {
            int checker = 0;
            try
            {
                while (checker < 10000)
                {
                    checker++;
                    InsertData(new Person { Id = checker, Description = "test", Name = ("some name " + checker) });
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                Rebuild();
            }

            Console.ReadLine();
        }

        public static void InsertData(Person person)
        {
            lock (_lockObject)
            {
                _db.GetCollection<Person>().Insert(person);
            }
        }

        public static void Rebuild()
        {
            _db.Dispose();

            DestroyContext();

            _db = GetContext();
        }

        public static ILiteDatabase GetContext()
        {
            var dataBase = new LiteDatabase(@$"Filename={Path.Combine(TargetFolder, CacheFileName)}; Connection=Direct;");

            return dataBase;
        }

        public static void DestroyContext()
        {
            try
            {
                File.Delete($"{Path.Combine(TargetFolder, CacheFileName)}");
            }
            catch (Exception ex)
            {
                Console.WriteLine( ex.ToString() );
            }
        }
    }

Expected behavior
I expect that when we clear the disk - LiteDB automatically will know that there is a free space again and will continue to work without restart of the program.

Screenshots/Stacktrace
Unhandled exception. System.AggregateException: One or more errors occurred. (There is not enough space on the disk. : 'F:\Data\cache-log.db')
---> System.IO.IOException: There is not enough space on the disk. : 'F:\Data\cache-log.db'
at System.IO.RandomAccess.WriteAtOffset(SafeFileHandle handle, ReadOnlySpan1 buffer, Int64 fileOffset) at System.IO.Strategies.OSFileStreamStrategy.Write(ReadOnlySpan1 buffer)
at System.IO.Strategies.OSFileStreamStrategy.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.Strategies.BufferedFileStreamStrategy.WriteSpan(ReadOnlySpan1 source, ArraySegment1 arraySegment)
at System.IO.Strategies.BufferedFileStreamStrategy.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.FileStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at LiteDB.Engine.DiskWriterQueue.WritePageToStream(PageBuffer page)
at LiteDB.Engine.DiskWriterQueue.ExecuteQueue()
at System.Threading.Tasks.Task.InnerInvoke()
at System.Threading.Tasks.Task.<>c.<.cctor>b__272_0(Object obj)
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at LiteDB.Engine.DiskWriterQueue.Wait()
at LiteDB.Engine.WalIndexService.CheckpointInternal()
at LiteDB.Engine.WalIndexService.TryCheckpoint()
at LiteDB.Engine.LiteEngine.Dispose(Boolean disposing)
at LiteDB.Engine.LiteEngine.Dispose()
at LiteDB.LiteDatabase.Dispose()
at ConcoleApplication.Program.Rebuild() in E:\Work\LiteDbBug\ConsoleApplicationForTheBug\ConsoleApplicationForTheBug\Program.cs:line 98
at ConcoleApplication.Program.Main() in E:\Work\LiteDbBug\ConsoleApplicationForTheBug\ConsoleApplicationForTheBug\Program.cs:line 32

or when trying to commit:

Unhandled exception. System.AggregateException: One or more errors occurred. (There is not enough space on the disk. : 'F:\Data\cache-log.db')
---> System.IO.IOException: There is not enough space on the disk. : 'F:\Data\cache-log.db'
at System.IO.RandomAccess.WriteAtOffset(SafeFileHandle handle, ReadOnlySpan1 buffer, Int64 fileOffset) at System.IO.Strategies.OSFileStreamStrategy.Write(ReadOnlySpan1 buffer)
at System.IO.Strategies.OSFileStreamStrategy.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.Strategies.BufferedFileStreamStrategy.WriteSpan(ReadOnlySpan1 source, ArraySegment1 arraySegment)
at System.IO.Strategies.BufferedFileStreamStrategy.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.FileStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at LiteDB.Engine.DiskWriterQueue.WritePageToStream(PageBuffer page)
at LiteDB.Engine.DiskWriterQueue.ExecuteQueue()
at System.Threading.Tasks.Task.InnerInvoke()
at System.Threading.Tasks.Task.<>c.<.cctor>b__272_0(Object obj)
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at LiteDB.Engine.DiskWriterQueue.Wait()
at LiteDB.Engine.WalIndexService.CheckpointInternal()
at LiteDB.Engine.WalIndexService.TryCheckpoint()
at LiteDB.Engine.LiteEngine.CommitAndReleaseTransaction(TransactionService transaction)
at LiteDB.Engine.LiteEngine.Commit()
at ConcoleApplication.Program.Remove(Person person) in E:\Work\LiteDbBug\ConsoleApplicationForTheBug\ConsoleApplicationForTheBug\Program.cs:line 58
at ConcoleApplication.Program.Main() in E:\Work\LiteDbBug\ConsoleApplicationForTheBug\ConsoleApplicationForTheBug\Program.cs:line 30

Additional context
I created a small isolated class to reproduce the issue. Make sure when run it to specify the needed disk with few MB of a free space. Also you need to put a breakpoint into the catch block in the Main method in order to clear some space on the disk manually when breakpoint will be there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant