public void T05_TestBackgroundFlushAndMergeConsistency()
        {
            // (1) one key to each of NUM_SEGMENTS separate segments
            // (2) setup a separate thread that just repeatedly checks each key
            // (3) perform a merge
            // (4) shutdown the threads and see if any detected a readback failure

            LayerManager db = new LayerManager(InitMode.NEW_REGION, "c:\\BENDtst\\7");
            List<ValueCheckerThread> checkers = new List<ValueCheckerThread>();
            int NUM_SEGMENTS = 7;
            int performed_iterations = 0;
            int TARGET_ITERATIONS = 10;
            try {
                for (int iter = 0; iter < TARGET_ITERATIONS; iter++) {

                    // setup the initial keys and checker threads
                    for (int x = 0; x < NUM_SEGMENTS; x++) {
                        string key = "test-" + x;
                        string value = "test-value-" + x;
                        db.setValueParsed(key, value);

                        // put it in it's own segment
                        db.flushWorkingSegment();

                        // start a checking thread
                        ValueCheckerThread checker = new ValueCheckerThread(db, key, value);
                        Thread newthread = new Thread(checker.doValidate);
                        newthread.Start();
                        checkers.Add(checker);
                    }
                    Thread.Sleep(5);

                    // verify there are no errors
                    foreach (ValueCheckerThread checker in checkers) {
                        Console.WriteLine("Thread  key:{0}  checks:{1}  errors:{2}", checker.key_to_check, checker.num_checks, checker.num_errors);
                    }
                    foreach (ValueCheckerThread checker in checkers) {
                        Assert.AreEqual(0, checker.num_errors, "checker thread error, key(" + checker.key_to_check + ") error count != 0");
                    }

                    // trigger a merge

                    for (int x = 0; x < 20; x++) {
                        db.mergeIfNeeded();
                    }
                    Thread.Sleep(5);

                    // verify there are no errors
                    foreach (ValueCheckerThread checker in checkers) {
                        Console.WriteLine("Thread  key:{0}  checks:{1}  errors:{2}", checker.key_to_check, checker.num_checks, checker.num_errors);
                    }
                    foreach (ValueCheckerThread checker in checkers) {
                        Assert.AreEqual(0, checker.num_errors, "checker thread error, key:" + checker.key_to_check);
                    }

                    // end the threads..
                    foreach (ValueCheckerThread checker in checkers) {
                        checker.end();
                    }
                    Thread.Sleep(10);
                    foreach (ValueCheckerThread checker in checkers) {
                        checker.waitForEnd();
                    }
                    checkers.Clear();

                    Thread.Sleep(5);

                    // delete the keys
                    System.Console.WriteLine("======= Clearing for next run...");

                    for (int x = 0; x < NUM_SEGMENTS; x++) {
                        string key = "test-" + x;
                        string value = "test-value-" + x;
                        db.setValue(new RecordKey().appendParsedKey(key), RecordUpdate.DeletionTombstone());
                    }
                    db.flushWorkingSegment();
                    Thread.Sleep(5);
                    db.mergeIfNeeded();
                    Thread.Sleep(5);
                    System.Console.WriteLine("======= Cleared for next run...");
                    performed_iterations = iter;
                }
            } finally {
                System.Console.WriteLine("performed iterations = " + performed_iterations + " target iterations = " + TARGET_ITERATIONS);
            }
        }
        internal static void Init(LayerManager store, int firstAvailableAddress)
        {
            // this was a test to be able to start with big address numbers..
            // firstAvailableAddress = 4294971392;
            // firstAvailableAddress = 4294971392 - 8*1024*1024;

            store.setValue(new RecordKey().appendParsedKey(".ROOT/FREELIST/HEAD"),
                RecordUpdate.WithPayload(Lsd.numberToLsd(firstAvailableAddress, 13)));
        }