Strange race condition in BitmapIndex._cache

Dec 31, 2015 at 7:18 AM
Hi,

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,
Dragos.
Dec 31, 2015 at 7:42 AM
I did like this as a temporary fix:
        public void Commit(bool freeMemory)
        {
            using (new L(this))
            {
                int[] keys = _cache.Keys();
                Array.Sort(keys);

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

Sounds like the free memory timer interfering.

Thanks for the fix!