{"action":"created","issue":{"url":"https://api.github.com/repos/mbdavid/LiteDB/issues/78","labels_url":"https://api.github.com/repos/mbdavid/LiteDB/issues/78/labels{/name}","comments_url":"https://api.github.com/repos/mbdavid/LiteDB/issues/78/comments","events_url":"https://api.github.com/repos/mbdavid/LiteDB/issues/78/events","html_url":"https://github.com/mbdavid/LiteDB/issues/78","id":116747298,"number":78,"title":"Concurrent read/write failures","user":{"login":"stojy","id":11408611,"avatar_url":"https://avatars.githubusercontent.com/u/11408611?v=3","gravatar_id":"","url":"https://api.github.com/users/stojy","html_url":"https://github.com/stojy","followers_url":"https://api.github.com/users/stojy/followers","following_url":"https://api.github.com/users/stojy/following{/other_user}","gists_url":"https://api.github.com/users/stojy/gists{/gist_id}","starred_url":"https://api.github.com/users/stojy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stojy/subscriptions","organizations_url":"https://api.github.com/users/stojy/orgs","repos_url":"https://api.github.com/users/stojy/repos","events_url":"https://api.github.com/users/stojy/events{/privacy}","received_events_url":"https://api.github.com/users/stojy/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/mbdavid/LiteDB/labels/bug","name":"bug","color":"fc2929"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2015-11-13T11:02:41Z","updated_at":"2015-11-14T12:38:26Z","closed_at":null,"body":"Using LiteDB 1.0.4, I'm getting failures when performing reads (e.g.FindAll) and writes (e.g. Insert, Update) from different threads at the same time.\r\n\r\nAs far as I can tell, I'm using LiteDB correctly whereby each thread has it's own instance of the database which is disposed when no longer needed.\r\n\r\nThis issue is potentially related to #73, however I'm receiving different exceptions.  The workaround I've used to overcome the issue is to thread lock all DB access, but unfortunately this isn't a viable long term solution due to performance hit when servicing simultaneous access from our users (a small web site).\r\n\r\nBelow are the unique exceptions with stack traces that I've seen.\r\n\r\n\tLiteDB.LiteException: Failed to create instance for type 'System.Collections.Generic.List`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]' from assembly 'System.Collections.Generic.List`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. Checks if has a public constructor with no parameters\r\n\t   at LiteDB.Reflection.CreateInstance(Type type)\r\n\t   at LiteDB.BsonMapper.DeserializeList(Type type, BsonArray value)\r\n\t   at LiteDB.BsonMapper.Deserialize(Type type, BsonValue value)\r\n\t   at LiteDB.BsonMapper.DeserializeObject(Type type, Object obj, BsonDocument value)\r\n\t   at LiteDB.BsonMapper.Deserialize(Type type, BsonValue value)\r\n\t   at LiteDB.BsonMapper.ToObject[T](BsonDocument doc)\r\n\t   at LiteDB.LiteCollection`1.<Find>d__9.MoveNext()\r\n\t   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)\r\n\t   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)\r\n\r\n\tSystem.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.\r\n\t   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)\r\n\t   at LiteDB.LiteCollection`1.<Find>d__9.MoveNext()\r\n\t   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)\r\n\t   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)\r\n\r\n\tLiteDB.LiteException: Timeout. Database is locked for more than 00:01:00\r\n\t   at LiteDB.DiskService.TryExec(TimeSpan timeout, Action action)\r\n\t   at LiteDB.JournalService.CreateJournalFile(Action action)\r\n\t   at LiteDB.TransactionService.Commit()\r\n\t   at LiteDB.LiteCollection`1.Insert(T document)\r\n\r\n\t- only seen this when LiteDB automatically creates the .db file\r\n\tSystem.IO.IOException: The process cannot access the file 'C:\\code\\distribution\\RWWA.Distribution\\RWWA.Deployment.Tests\\bin\\Debug\\dummy.db' because it is being used by another process.\r\n\t   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)\r\n\t   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)\r\n\t   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize)\r\n\t   at LiteDB.DiskService.CreateNewDatafile(ConnectionString connectionString)\r\n\t   at LiteDB.LiteDatabase..ctor(String connectionString)\r\n\r\n\tSystem.NullReferenceException: Object reference not set to an instance of an object.\r\n\t   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)\r\n\t   at LiteDB.BsonMapper.GetPropertyMapper(Type type)\r\n\t   at LiteDB.BsonMapper.SetAutoId(Object entity, LiteCollection`1 col)\r\n\t   at LiteDB.LiteCollection`1.Insert(T document)\r\n\r\n\tSystem.UnauthorizedAccessException: Access to the path 'C:\\code\\distribution\\RWWA.Distribution\\RWWA.Deployment.Tests\\bin\\Debug\\dummy-journal.db' is denied.\r\n\t   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)\r\n\t   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)\r\n\t   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)\r\n\t   at LiteDB.RecoveryService.OpenExclusiveFile(String filename, Action`1 success)\r\n\t   at LiteDB.LiteDatabase..ctor(String connectionString)\r\n\r\n\t[I didn't log this exception type]: DB.IndexService.GetNode(PageAddress address)\r\n\t   at LiteDB.IndexService.<FindAll>d__2.MoveNext()\r\n\t   at LiteDB.LiteCollection`1.<Find>d__9.MoveNext()\r\n\t   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)\r\n\t   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)\r\n\r\nAll of the above were re-created with the below code.\r\n\r\n    using System;\r\n    using System.Linq;\r\n    using System.Threading;\r\n    using System.Threading.Tasks;\r\n    using CsQuery.ExtensionMethods;\r\n    using LiteDB;\r\n    using NUnit.Framework;\r\n\r\n    namespace RWWA.Deployment.Tests\r\n    {\r\n        public class LiteDbTest\r\n        {\r\n            public class Target\r\n            {\r\n                [BsonId]\r\n                public ObjectId Id { get; set; }\r\n\r\n                [BsonIndex(true)]\r\n                public string Name { get; set; }\r\n\r\n                public DateTime LastUpdateCheck { get; set; }\r\n            }\r\n\r\n            [Test]\r\n            public void TestReadInsertUpdate()\r\n            {\r\n                Setup();\r\n\r\n                var update = Execute(\"u\", db =>\r\n                {\r\n                    var target = db.GetCollection<Target>(\"targets\").FindOne(x => x.Name != null);\r\n                    if (target != null)\r\n                    {\r\n                        target.LastUpdateCheck = DateTime.Now;\r\n                        db.GetCollection<Target>(\"targets\").Update(target);\r\n                    }\r\n                });\r\n                var insert = Execute(\"i\", db => db.GetCollection<Target>(\"targets\").Insert(CreateTarget()));\r\n                var read = Execute(\"r\", db => db.GetCollection<Target>(\"targets\").FindAll().ToList());\r\n                Task.WaitAll(update, insert, read);\r\n            }\r\n\r\n            [Test]\r\n            public void TestReadInsert()\r\n            {\r\n                Setup();\r\n\r\n                var insert = Execute(\"i\", db => db.GetCollection<Target>(\"targets\").Insert(CreateTarget()));\r\n                var read = Execute(\"r\", db => db.GetCollection<Target>(\"targets\").FindAll().ToList());\r\n                Task.WaitAll(insert, read);\r\n            }\r\n\r\n            [Test]\r\n            public void TestReadUpdate()\r\n            {\r\n                Setup();\r\n\r\n                var update = Execute(\"u\", db =>\r\n                {\r\n                    var target = db.GetCollection<Target>(\"targets\").FindOne(x => x.Name != null);\r\n                    if (target != null)\r\n                    {\r\n                        target.LastUpdateCheck = DateTime.Now;\r\n                        db.GetCollection<Target>(\"targets\").Update(target);\r\n                    }\r\n                });\r\n                var read = Execute(\"r\", db => db.GetCollection<Target>(\"targets\").FindAll().ToList());\r\n                Task.WaitAll(update, read);\r\n            }\r\n\r\n            private static Target CreateTarget()\r\n            {\r\n                return new Target { Name = Guid.NewGuid().ToString(), LastUpdateCheck = DateTime.Now };\r\n            }\r\n\r\n            private static void Setup()\r\n            {\r\n                using (var db = new LiteDatabase(\"dummy.db\"))\r\n                {\r\n                    db.DropCollection(\"targets\");\r\n                    Enumerable.Repeat(0, 1000).ForEach(x => db.GetCollection<Target>(\"targets\").Insert(CreateTarget()));\r\n                }\r\n            }\r\n\r\n            private static Task<ParallelLoopResult> Execute(string prefix, Action<LiteDatabase> action)\r\n            {\r\n                return Task.Run(() => Parallel.For(0, 100, x =>\r\n                                                                {\r\n                                                                    Console.Write($\"{prefix}-{x}-{Thread.CurrentThread.ManagedThreadId} \");\r\n                                                                    try\r\n                                                                    {\r\n                                                                        using (var db = new LiteDatabase(\"dummy.db\"))\r\n                                                                            action(db);\r\n                                                                    }\r\n                                                                    catch (Exception e)\r\n                                                                    {\r\n                                                                        Console.WriteLine(e);\r\n                                                                    }\r\n                                                                }));\r\n            }\r\n        }\r\n    }"},"comment":{"url":"https://api.github.com/repos/mbdavid/LiteDB/issues/comments/156693262","html_url":"https://github.com/mbdavid/LiteDB/issues/78#issuecomment-156693262","issue_url":"https://api.github.com/repos/mbdavid/LiteDB/issues/78","id":156693262,"user":{"login":"mbdavid","id":1137197,"avatar_url":"https://avatars.githubusercontent.com/u/1137197?v=3","gravatar_id":"","url":"https://api.github.com/users/mbdavid","html_url":"https://github.com/mbdavid","followers_url":"https://api.github.com/users/mbdavid/followers","following_url":"https://api.github.com/users/mbdavid/following{/other_user}","gists_url":"https://api.github.com/users/mbdavid/gists{/gist_id}","starred_url":"https://api.github.com/users/mbdavid/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mbdavid/subscriptions","organizations_url":"https://api.github.com/users/mbdavid/orgs","repos_url":"https://api.github.com/users/mbdavid/repos","events_url":"https://api.github.com/users/mbdavid/events{/privacy}","received_events_url":"https://api.github.com/users/mbdavid/received_events","type":"User","site_admin":false},"created_at":"2015-11-14T12:38:26Z","updated_at":"2015-11-14T12:38:26Z","body":"Hi @stojy, v2 are building to improve code and consistence. I split code in modules to better maintaince. I guess in one or two weeks I will release a beta version. Than, I need write more unit tests and update site/wiki."}}