Strange race condition in BitmapIndex._cache

Dec 31, 2015 at 8:18 AM

First, Happy New Year! ;-)

Second, it looks like I ran into a strange race condition. I have a raptordb collection which does not change in time. It's size is around 2-300M records all split between 5-6 views and in general, it works fine. Of course, there are also few other smaller collections, independent, running in the same process - but they do not "touch" and they have nothing in common with this one.

However, last night while I let some tests to run over the night, I got a strange crash:
  • the exception is "System.Collections.Generic.KeyNotFoundException";
  • it occurred in BitmapIndex.cs, on method "Commit";
  • the exact line is "var bmp = _cache[k];"
  • it looks like the _cache dictionary is empty;
  • however, 4 lines upper, there is this call: "int[] keys = _cache.Keys();" and when I looked in keys, I have 25 elements. I ran also in ImmediateWindow the _cache.Keys() and it returned a 0-length array;
In case it matters, the call stack is:
    RaptorDB.Common.dll!RaptorDB.Common.SafeDictionary<int,RaptorDB.WAHBitArray>.this[int].get(int key) Line 34 C#
    RaptorDB.dll!RaptorDB.BitmapIndex.Commit(bool freeMemory) Line 86   C#
    RaptorDB.dll!RaptorDB.IndexFile<int>.BitmapFlush() Line 472 C#
    RaptorDB.dll!RaptorDB.MGIndex<int>.SaveIndex() Line 212 C#
    RaptorDB.dll!RaptorDB.Views.ViewHandler._saveTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) Line 76 C#
It looks like someone, somehow, erased the elements from _cache between those 2 calls. Any idea on what might have triggered this and any hint on how should I fix this?

Thank you,
Dec 31, 2015 at 8:42 AM
I did like this as a temporary fix:
        public void Commit(bool freeMemory)
            using (new L(this))
                int[] keys = _cache.Keys();

                foreach (int k in keys)
                    WAHBitArray bmp = null;
                    if (_cache.TryGetValue(k, out bmp) && bmp.isDirty)
                        SaveBitmap(k, bmp);
                        bmp.isDirty = false;
                if (freeMemory)
                    _cache = new SafeDictionary<int, WAHBitArray>();
Dec 31, 2015 at 10:07 AM
Happy New Year to you too!

Sounds like the free memory timer interfering.

Thanks for the fix!