Пример #1
0
 public void PutRecordCase1(HashDatabase db, Transaction txn)
 {
     byte[] bigArray = new byte[262144];
     for (int i = 0; i < 50; i++)
     {
         if (txn == null)
         {
             db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
                    new DatabaseEntry(BitConverter.GetBytes(i)));
         }
         else
         {
             db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
                    new DatabaseEntry(BitConverter.GetBytes(i)), txn);
         }
     }
     for (int i = 50; i < 100; i++)
     {
         if (txn == null)
         {
             db.Put(new DatabaseEntry(bigArray),
                    new DatabaseEntry(bigArray));
         }
         else
         {
             db.Put(new DatabaseEntry(bigArray),
                    new DatabaseEntry(bigArray), txn);
         }
     }
 }
        /*
         * Insert a document to the database.
         */
        public void InsertToDatabase(Document document)
        {
            DatabaseEntry key   = new DatabaseEntry(BitConverter.GetBytes(document.Id));
            DatabaseEntry value = new DatabaseEntry(document.GetByteArray());

            hashDatabase.Put(key, value);

            key   = new DatabaseEntry(Encoding.UTF8.GetBytes(document.Url));
            value = new DatabaseEntry(BitConverter.GetBytes(document.Id));
            urlDatabase.Put(key, value);
        }
        protected void AddToDb(string keyval, byte[] dataval)
        {
            var key  = new DatabaseEntry(Encoding.UTF8.GetBytes(keyval));
            var data = new DatabaseEntry(dataval);

            db.Put(key, data);
        }
Пример #4
0
        /// <summary>
        /// Inserts the specified (integer, string) pair of internal- and external representations
        /// into the dictionary.
        /// </summary>
        /// <param name="internalValue">The internal representation.</param>
        /// <param name="externalValue">The external representation.</param>
        private void Insert(long internalValue, string externalValue)
        {
            //
            // the (external, internal) key-value pair is put in the string2integer dictionary

            var str2LongKey   = new DatabaseEntry(Util.Encoding.DbEncode(externalValue));
            var str2LongValue = new DatabaseEntry(Util.Encoding.DbEncode(internalValue));

            m_dbStr2Long.Put(str2LongKey, str2LongValue);

            //
            // similarly, the (internal, external) key-value pair goes into the integer2string
            // dictionary

            var long2StrKey   = new DatabaseEntry(Util.Encoding.DbEncode(internalValue));
            var long2StrValue = new DatabaseEntry(Util.Encoding.DbEncode(externalValue));

            m_dbLong2Str.Put(long2StrKey, long2StrValue);
        }
Пример #5
0
        public void TestCompactWithoutTxn()
        {
            int i, nRecs;

            nRecs    = 10000;
            testName = "TestCompactWithoutTxn";
            SetUpTest(true);
            string hashDBFileName = testHome + "/" + testName + ".db";

            HashDatabaseConfig hashDBConfig = new HashDatabaseConfig();

            hashDBConfig.Creation = CreatePolicy.ALWAYS;
            // The minimum page size
            hashDBConfig.PageSize       = 512;
            hashDBConfig.HashComparison =
                new EntryComparisonDelegate(dbIntCompare);
            using (HashDatabase hashDB = HashDatabase.Open(
                       hashDBFileName, hashDBConfig)) {
                DatabaseEntry key;
                DatabaseEntry data;

                // Fill the database with entries from 0 to 9999
                for (i = 0; i < nRecs; i++)
                {
                    key  = new DatabaseEntry(BitConverter.GetBytes(i));
                    data = new DatabaseEntry(BitConverter.GetBytes(i));
                    hashDB.Put(key, data);
                }

                /*
                 * Delete entries below 500, between 3000 and
                 * 5000 and above 7000
                 */
                for (i = 0; i < nRecs; i++)
                {
                    if (i < 500 || i > 7000 || (i < 5000 && i > 3000))
                    {
                        key = new DatabaseEntry(BitConverter.GetBytes(i));
                        hashDB.Delete(key);
                    }
                }

                hashDB.Sync();
                long fileSize = new FileInfo(hashDBFileName).Length;

                // Compact database
                CompactConfig cCfg = new CompactConfig();
                cCfg.FillPercentage = 30;
                cCfg.Pages          = 10;
                cCfg.Timeout        = 1000;
                cCfg.TruncatePages  = true;
                cCfg.start          = new DatabaseEntry(BitConverter.GetBytes(1));
                cCfg.stop           = new DatabaseEntry(BitConverter.GetBytes(7000));
                CompactData compactData = hashDB.Compact(cCfg);
                Assert.IsFalse((compactData.Deadlocks == 0) &&
                               (compactData.Levels == 0) &&
                               (compactData.PagesExamined == 0) &&
                               (compactData.PagesFreed == 0) &&
                               (compactData.PagesTruncated == 0));

                hashDB.Sync();
                long compactedFileSize = new FileInfo(hashDBFileName).Length;
                Assert.Less(compactedFileSize, fileSize);
            }
        }
Пример #6
0
        /// <summary>
        /// Builds the index over the buckets that belong to this index.
        /// </summary>
        internal void Build()
        {
            var currentAtom = Int64.MaxValue;
            var start       = new long[3];
            var count       = new long[3];

            var cursors = new TripleCursor[3];

            cursors[0] = m_sBucket.OpenRead();
            cursors[1] = m_pBucket.OpenRead();
            cursors[2] = m_oBucket.OpenRead();

            //
            // the index building algorithm is fairly straightforward: all three buckets are opened
            // simultaneously, and we go through them such that we are always dealing with the same
            // atom X for all three buckets. at any time we are at (or before) X in the S-bucket
            // where X is in the S-position, at X in the P-bucket where it is in the P-position,
            // and at X in the O-bucket where it is in the O-position. when we are done with X we
            // move on to the next atom and never see a relevant X value again. in this way, we
            // only need one pass over all three buckets to build the index.

            long peek;

            while (cursors[0].HasNext || cursors[1].HasNext || cursors[2].HasNext)
            {
                //
                // find the next smallest atom value to handle

                if (cursors[0].HasNext)
                {
                    peek = cursors[0].Peek().S.InternalValue;
                    if (peek < currentAtom)
                    {
                        currentAtom = peek;
                    }
                }
                if (cursors[1].HasNext)
                {
                    peek = cursors[1].Peek().P.InternalValue;
                    if (peek < currentAtom)
                    {
                        currentAtom = peek;
                    }
                }
                if (cursors[2].HasNext)
                {
                    peek = cursors[2].Peek().O.InternalValue;
                    if (peek < currentAtom)
                    {
                        currentAtom = peek;
                    }
                }

                //
                // see how much atoms with the selected value there are with that value in the S
                // position

                start[0] = -1;
                count[0] = -1;
                if (cursors[0].HasNext && cursors[0].Peek().S.InternalValue == currentAtom)
                {
                    start[0] = cursors[0].Position;
                    count[0] = 0;
                    do
                    {
                        count[0]++;
                        cursors[0].Next();
                    } while (cursors[0].HasNext && cursors[0].Peek().S.InternalValue == currentAtom);
                }

                //
                // see how much atoms with the selected value there are with that value in the P
                // position

                start[1] = -1;
                count[1] = -1;
                if (cursors[1].HasNext && cursors[1].Peek().P.InternalValue == currentAtom)
                {
                    start[1] = cursors[1].Position;
                    count[1] = 0;
                    do
                    {
                        count[1]++;
                        cursors[1].Next();
                    } while (cursors[1].HasNext && cursors[1].Peek().P.InternalValue == currentAtom);
                }

                //
                // see how much atoms with the selected value there are with that value in the O
                // position

                start[2] = -1;
                count[2] = -1;
                if (cursors[2].HasNext && cursors[2].Peek().O.InternalValue == currentAtom)
                {
                    start[2] = cursors[2].Position;
                    count[2] = 0;
                    do
                    {
                        count[2]++;
                        cursors[2].Next();
                    } while (cursors[2].HasNext && cursors[2].Peek().O.InternalValue == currentAtom);
                }

                //
                // create and insert the index payload for the atom with the current value into the
                // index database

                var payload = new byte[8 * 6];
                var i       = 0;
                for (int j = 0; j < start.Length; j++)
                {
                    Encoding.DbEncode(start[j]).CopyTo(payload, i);
                    i += 8;
                    Encoding.DbEncode(count[j]).CopyTo(payload, i);
                    i += 8;
                }

                var key   = new DatabaseEntry(Encoding.DbEncode(currentAtom));
                var value = new DatabaseEntry(payload);
                m_db.Put(key, value);

                currentAtom = Int64.MaxValue;
            }
        }
        /*
         * Test the external file database with or without environment.
         * 1. Config and open the environment;
         * 2. Verify the environment external file configs;
         * 3. Config and open the database;
         * 4. Verify the database external file configs;
         * 5. Insert and verify some external file data by database methods;
         * 6. Insert some external file data by cursor, update it and verify
         * the update by database stream and cursor;
         * 7. Verify the stats;
         * 8. Close all handles.
         * If "blobdbt" is true, set the data DatabaseEntry.ExternalFile as
         * true, otherwise make the data DatabaseEntry reach the external file
         * threshold in size.
         */
        void TestBlobHashDatabase(uint env_threshold, string env_blobdir,
                                  uint db_threshold, string db_blobdir, bool blobdbt)
        {
            if (env_threshold == 0 && db_threshold == 0)
            {
                return;
            }

            string hashDBName =
                testHome + "/" + testName + ".db";

            Configuration.ClearDir(testHome);
            HashDatabaseConfig cfg = new HashDatabaseConfig();

            cfg.Creation = CreatePolicy.ALWAYS;
            string blrootdir = "__db_bl";

            // Open the environment and verify the external file config.
            if (env_threshold > 0)
            {
                DatabaseEnvironmentConfig envConfig =
                    new DatabaseEnvironmentConfig();
                envConfig.AutoCommit            = true;
                envConfig.Create                = true;
                envConfig.UseMPool              = true;
                envConfig.UseLogging            = true;
                envConfig.UseTxns               = true;
                envConfig.UseLocking            = true;
                envConfig.ExternalFileThreshold = env_threshold;
                if (env_blobdir != null)
                {
                    envConfig.ExternalFileDir = env_blobdir;
                    blrootdir = env_blobdir;
                }
                DatabaseEnvironment env = DatabaseEnvironment.Open(
                    testHome, envConfig);
                if (env_blobdir == null)
                {
                    Assert.IsNull(env.ExternalFileDir);
                }
                else
                {
                    Assert.AreEqual(0,
                                    env.ExternalFileDir.CompareTo(env_blobdir));
                }
                Assert.AreEqual(env_threshold,
                                env.ExternalFileThreshold);
                cfg.Env    = env;
                hashDBName = testName + ".db";
            }

            // Open the database and verify the external file config.
            if (db_threshold > 0)
            {
                cfg.ExternalFileThreshold = db_threshold;
            }
            if (db_blobdir != null)
            {
                cfg.ExternalFileDir = db_blobdir;

                /*
                 * The external file directory setting in the database
                 * is effective only when it is opened without
                 * an environment.
                 */
                if (cfg.Env == null)
                {
                    blrootdir = db_blobdir;
                }
            }

            HashDatabase db = HashDatabase.Open(hashDBName, cfg);

            Assert.AreEqual(
                db_threshold > 0 ? db_threshold : env_threshold,
                db.ExternalFileThreshold);
            if (db_blobdir == null && cfg.Env == null)
            {
                Assert.IsNull(db.ExternalFileDir);
            }
            else
            {
                Assert.AreEqual(0,
                                db.ExternalFileDir.CompareTo(blrootdir));
            }

            // Insert and verify some external file data by database
            // methods.
            string[]      records = { "a", "b", "c", "d", "e", "f", "g", "h",
                                      "i",      "j", "k", "l", "m", "n", "o", "p","q","r", "s",
                                      "t",      "u", "v", "w", "x", "y", "z" };
            DatabaseEntry kdbt = new DatabaseEntry();
            DatabaseEntry ddbt = new DatabaseEntry();

            byte[] kdata, ddata;
            string str;
            KeyValuePair <DatabaseEntry, DatabaseEntry> pair;

            ddbt.ExternalFile = blobdbt;
            Assert.AreEqual(blobdbt, ddbt.ExternalFile);
            for (int i = 0; i < records.Length; i++)
            {
                kdata = BitConverter.GetBytes(i);
                str   = records[i];
                if (!blobdbt)
                {
                    for (int j = 0; j < db_threshold; j++)
                    {
                        str = str + records[i];
                    }
                }
                ddata     = Encoding.ASCII.GetBytes(str);
                kdbt.Data = kdata;
                ddbt.Data = ddata;
                db.Put(kdbt, ddbt);
                try
                {
                    pair = db.Get(kdbt);
                }
                catch (DatabaseException)
                {
                    db.Close();
                    if (cfg.Env != null)
                    {
                        cfg.Env.Close();
                    }
                    throw new TestException();
                }
                Assert.AreEqual(ddata, pair.Value.Data);
            }

            /*
             * Insert some external file data by cursor, update it and
             * verify the update by database stream.
             */
            kdata             = BitConverter.GetBytes(records.Length);
            ddata             = Encoding.ASCII.GetBytes("abc");
            kdbt.Data         = kdata;
            ddbt.Data         = ddata;
            ddbt.ExternalFile = true;
            Assert.IsTrue(ddbt.ExternalFile);
            pair =
                new KeyValuePair <DatabaseEntry, DatabaseEntry>(kdbt, ddbt);
            CursorConfig dbcConfig = new CursorConfig();
            Transaction  txn       = null;

            if (cfg.Env != null)
            {
                txn = cfg.Env.BeginTransaction();
            }
            HashCursor cursor = db.Cursor(dbcConfig, txn);

            cursor.Add(pair);
            DatabaseStreamConfig dbsc = new DatabaseStreamConfig();

            dbsc.SyncPerWrite = true;
            DatabaseStream dbs = cursor.DbStream(dbsc);

            Assert.AreNotEqual(null, dbs);
            Assert.IsFalse(dbs.GetConfig.ReadOnly);
            Assert.IsTrue(dbs.GetConfig.SyncPerWrite);
            Assert.AreEqual(3, dbs.Size());
            DatabaseEntry sdbt = dbs.Read(0, 3);

            Assert.IsNotNull(sdbt);
            Assert.AreEqual(ddata, sdbt.Data);
            sdbt = new DatabaseEntry(Encoding.ASCII.GetBytes("defg"));
            Assert.IsTrue(dbs.Write(sdbt, 3));
            Assert.AreEqual(7, dbs.Size());
            sdbt = dbs.Read(0, 7);
            Assert.IsNotNull(sdbt);
            Assert.AreEqual(Encoding.ASCII.GetBytes("abcdefg"), sdbt.Data);
            dbs.Close();

            /*
             * Verify the database stream can not write when it is
             * configured to be read-only.
             */
            dbsc.ReadOnly = true;
            dbs           = cursor.DbStream(dbsc);
            Assert.IsTrue(dbs.GetConfig.ReadOnly);
            try
            {
                Assert.IsFalse(dbs.Write(sdbt, 7));
                throw new TestException();
            }
            catch (DatabaseException)
            {
            }
            dbs.Close();

            // Verify the update by cursor.
            Assert.IsTrue(cursor.Move(kdbt, true));
            pair = cursor.Current;
            Assert.AreEqual(Encoding.ASCII.GetBytes("abcdefg"),
                            pair.Value.Data);
            cursor.Close();
            if (cfg.Env != null)
            {
                txn.Commit();
            }

            /*
             * Verify the external files are created in the expected
             * location.
             * This part of test is disabled since BTreeDatabase.BlobSubDir
             * is not exposed to users.
             */
            //if (cfg.Env != null)
            //	blrootdir = testHome + "/" + blrootdir;
            //string blobdir = blrootdir + "/" + db.BlobSubDir;
            //Assert.AreEqual(records.Length + 1,
            //    Directory.GetFiles(blobdir, "__db.bl*").Length);
            //Assert.AreEqual(1,
            //    Directory.GetFiles(blobdir, "__db_blob_meta.db").Length);

            // Verify the stats.
            HashStats st = db.Stats();

            Assert.AreEqual(records.Length + 1, st.nExternalFiles);

            // Close all handles.
            db.Close();
            if (cfg.Env != null)
            {
                cfg.Env.Close();
            }

            /*
             * Remove the default external file directory
             * when it is not under the test home.
             */
            if (db_blobdir == null && cfg.Env == null)
            {
                Directory.Delete("__db_bl", true);
            }
        }