Project Description
STSdb Multi-Threading Layer C# Csharp .NET Framework 3.5> MONO

The project is abandoned because of
DBreeze database development.
NOSQL object embedded transactional database and a virtual filesystem.

Thist project is a multi-threading layer for this database. Version of STSdb embedded to the source is STSdb 3.5.12 - 3993 (2012-02-01)

STSdb works for now with the single process only, but its gorgeous "locators" give us ability to create parallel views on one data set and later merge them in.

Based on this multi-locator concept, new namespace STSdb.MTL was created, giving ability to work with the data from multiple threads.


  • Ability to work safely from different threads with the database.
  • Eliminating of the deadlocks by registering tables, which have to be modified or read-write-synchronized, before in-transactional operations are started.
  • The earliest stage of the deadlocks prediction (in case if the read-write-synchro-tables are not registered in the beginning of the transaction); the belated deadlock transaction fails, the came first transaction goes on with its job.
  • New layer for the LINQ based statements: selects inserts updates deletes etc...
  • Select of committed data is parallel and fast, even if in this moment other threads are changing the data. This all  - due to different locators.
  • No need to Rollback data, if it's not Committed - then not saved.
  • "DataBreezing". Automatic data compaction, within tables life cycle.
  • Backup (dump, to support complex XKeyMaps and PersistWrites need a little hack), with possibility to change virtual file system sector size. [In a raw state]
  • Current RELEASE is 13883. [Ready for use. VFS sector size is 4096 bytes, - small or medium data storage - sector size can be changed via static variable to 65536 bytes]
  • Documentation and techniques are available here
  • Inspiration source is here
  • "Commercial" license for closed-source projects must be obtained on


Programmer has to start like this:



        string dbPath = @"S:\temp\STS\test1_SSD.stsdb";

        STSdb.MTL.STSdbMTLengine _sts_engine = null;

        //VERY IMPORTANT, in the Dispose function of your application main thread or DLL to say 
        //if (_sts_engine != null)
        //        _sts_engine.Dispose();

        private void testSTSdbMTL()
            if (_sts_engine == null)
                _sts_engine = new STSdb.MTL.STSdbMTLengine(dbPath); //STSdb has virtual file system layer, also database can be created from many files located in different places.

            using (STSdb.MTL.Transaction tran = _sts_engine.GetTransaction())
                //transaction is started, the whole code inside of using statement better to put into try/catch block

                //here we can register tables which have to be modified, and get 100% defense from the deadlocks.

                tran.RegisterWriteOrSynchroReadTables("table1/mainInfo", "table1/extras");

                //we've reserved these two tables for mutation inside of our transaction.

                //we DON'T NEED to register tables, if only one (or less) table must be mutated or eSelectMode.READ_SYNCHRO within one transaction.

                //we must register BEFORE any "write-bid" appears in the transaction, but it's possible to register after eSelectMode.READ statements 

                //Now, we want to insert rows into two different tables. Tables will be created and supported automatically, if they don't exist.

                DateTime now = DateTime.Now;
                tran.Insert<long, string>("table1/mainInfo", now.Ticks, "serialized main info");
                tran.Insert<long, string>("table1/extras", now.Ticks, "serialized extras");

                //STSdb is a Key/Value Storage (complex keys are supported), so first type "long" is our key, second type "string" is our data.
                //Documentation about STSdb better to get on their website

                //Then we have to commit all operations. If we don't commit, data will not be changed
                tran.Commit(); //already in db

                //STSdb.MTL.Transaction methods like Insert, Update, Select SelectForward, SelectBackward etc. have lots of overloads, so use them.

                //No we want to select something and change it.

                STSdb.MTL.TableRow<long, string> tr = tran.Select<long, string>("table1/mainInfo", STSdb.MTL.eSelectMode.READ_SYNCHRO, now.Ticks);

                //update of the value
                tr.Value = "new value";

                //update of the key
                tr.Key = 4568; //new key

                tran.Commit(); //already in db

                //or loop

                foreach (var row in tran.SelectBackward<long, string>("table1/mainInfo", STSdb.MTL.eSelectMode.READ, 20, 8).Take(2))

                    //Don't use .Where(r=>...) after LINQ Extensions Select, therefore extra range queries extensions were developed: SelectForward and SelectBackward.
                    //All computations must be made here in a loop
                    //You can use .Take() to limit quantity of data, if necessary.
                    //Or safely break; from here if quantity of checked records is enough.

                    Console.WriteLine(DateTime.Now.Ticks.ToString() + " " + DateTime.Now.ToString("") + " > Key: " + row.Key.ToString() + " ;;; Value: " + row.Value.ToString());

                //BTW. if table is mutated and still not committed, selects of this table with eSelectMode.READ_SYNCHRO, 
                //within the same transaction, shows changed values,
                //though selects of this table with eSelectMode.READ will go on to show unmodified data (sure, till Commit).

                //With eSelectMode.READ_SYNCHRO you can be sure that you take the latest modified value, 
                //then you can modify it in your thread and Commit it, 
                //the next concurrent thread will take exactly your modified value. 
                //If there are concurrent threads which want to update the same table as your transaction thread and at the same time, 
                //they will have to wait, till your transaction is finished (not committed, because you can commit 
                //several times in one transaction, but finished).

                //Otherwise, the threads, who want to eSelectMode.READ values, will receive them fast and in parallel 
                //with the thread who is making modification and with each other.

                //Only select and show - use eSelectMode.READ 
                //Select and then update value in the same transaction - must be used eSelect.READ_SYNCHRO 

                //eSelectMode.READ - reporting style. 
                //eSelectMode.READ_SYNCHRO - bank account value change style. 

            Max Row, Min Row, Count

            using (STSdb.MTL.Transaction tran = _sts_engine.GetTransaction())
                //tran.Insert<long, string>("t1", 1, null);
                //tran.Insert<long, string>("t1", 2, null);
                //tran.Insert<long, string>("t1", 3, "test");

                tran.Insert<DateTime, string>("t1", new DateTime(2011, 10, 10, 10, 0, 0, 0), null);
                tran.Insert<DateTime, string>("t1", new DateTime(2011, 10, 10, 12, 0, 0, 0), null);
                tran.Insert<DateTime, string>("t1", new DateTime(2011, 10, 10, 14, 0, 0, 0), "test");


                //var max = tran.MaxRow<long, string>("t1");
                //var min = tran.MinRow<long, string>("t1");
                //var count = tran.Count<long, string>("t1");

                var max = tran.MaxRow<DateTime, string>("t1");
                var min = tran.MinRow<DateTime, string>("t1");
                var count = tran.Count<DateTime, string>("t1");


Last edited May 6, 2012 at 12:55 PM by hhblaze, version 92