Inheritance: ISegmentBlockEncoder
示例#1
0
        public static void T01_BlockEncodeDecodeTest()
        {
            MemoryStream ms = new MemoryStream();
            byte[] testdata = { 0x00, 0x10, 0x78, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00 };

            // init an encoder and add one key which requires escaping
            {
                ISegmentBlockEncoder enc = new SegmentBlockBasicEncoder();
                enc.setStream(ms);

                RecordKey key = new RecordKey().appendParsedKey("TESTSETEST");
                RecordUpdate update = RecordUpdate.WithPayload(testdata);

                enc.add(key, update);
                enc.flush();
                ms.Flush();

                System.Console.WriteLine("Test Update: " + update.ToString());
            }

            byte[] block_contents = ms.ToArray();
            System.Console.WriteLine("Block Output: " + BitConverter.ToString(block_contents));

            // init the decoder
            {
                ISegmentBlockDecoder dec = new SegmentBlockBasicDecoder(new BlockAccessor(ms.ToArray()));

                foreach (var kvp in dec.sortedWalk()) {
                    System.Console.WriteLine("Payload Update: " + kvp.Value.ToString());

                    byte[] payload = kvp.Value.data;
                    Assert.AreEqual(testdata, payload, "payload data mismatch!");
                }
            }
        }
示例#2
0
        private byte[] fetchLogEntries_block(string log_server_guid, string log_start_key, string log_end_key)
        {
            var rk_start = new RecordKey()
                .appendKeyPart("_logs")
                .appendKeyPart(log_server_guid)
                .appendKeyPart(log_start_key);
            var rk_end = RecordKey.AfterPrefix(new RecordKey()
                .appendKeyPart("_logs")
                .appendKeyPart(log_server_guid)
                .appendKeyPart(log_end_key));
            var scanrange = new ScanRange<RecordKey>(rk_start, rk_end, null);

            byte[] packed_log_records;
            {
                MemoryStream writer = new MemoryStream();
                // TODO: this seems like a really inefficient way to write out a key
                ISegmentBlockEncoder encoder = new SegmentBlockBasicEncoder();
                encoder.setStream(writer);
                foreach (var logrow in next_stage.scanForward(scanrange)) {
                    encoder.add(logrow.Key, RecordUpdate.WithPayload(logrow.Value.data));
                }
                encoder.flush();
                packed_log_records = writer.ToArray();
            }

            // IF there are no log entries... BLOCK!

            return packed_log_records;
        }
示例#3
0
        public void setValue(RecordKey skey, RecordUpdate supdate)
        {
            checkActive();

            // (1) write our repl log entry

            DateTime now = DateTime.Now;
            long logstamp = id_gen.nextTimestamp();

            RecordKey logkey = new RecordKey()
                .appendKeyPart("_logs")
                .appendKeyPart(ctx.server_guid)
                .appendKeyPart(new RecordKeyType_Long(logstamp));

            // (1.1) pack the key/value together into the log entry
            byte[] packed_update;
            {
                MemoryStream writer = new MemoryStream();
                // TODO: this seems like a really inefficient way to write out a key
                ISegmentBlockEncoder encoder = new SegmentBlockBasicEncoder();
                encoder.setStream(writer);
                encoder.add(skey, supdate);
                encoder.flush();
                packed_update = writer.ToArray();
            }
            RecordUpdate logupdate = RecordUpdate.WithPayload(packed_update);

            Console.WriteLine("writing log entry: {0} -> [ {1} = {2} ]",
                logkey, skey, supdate);
            next_stage.setValue(logkey, logupdate);

            // (2) trigger the repl notifier that there is a new entry to push
            pusher.wakeUpLogSleepers();

            // (2) write the record key
            Console.WriteLine("writing data entry: {0} = {1}",
                skey, supdate);
            RecordKey private_record_key = new RecordKey()
                .appendKeyPart("_data");
            foreach (var part in skey.key_parts) {
                private_record_key.appendKeyPart(part);
            }
            next_stage.setValue(private_record_key, supdate);
        }
        public void T01_BasicBlock_Find()
        {
            string[] testvalues = { "test/1", "test/2", "test/3" };
            byte[] databuffer;

            // encode a buffer
            {
                MemoryStream ms = new MemoryStream();
                // add some values to the block encoder
                SegmentBlockBasicEncoder enc = new SegmentBlockBasicEncoder();
                enc.setStream(ms);
                for (int i = 0; i < testvalues.Length; i++) {
                    RecordKey tkey = new RecordKey().appendParsedKey(testvalues[i]);
                    RecordUpdate tupdate = RecordUpdate.WithPayload("data: " + testvalues[i]);

                    enc.add(tkey, tupdate);
                }
                enc.flush();

                databuffer = ms.ToArray();
            }

            // test FindNext(key,equal_ok=true)
            {
                BlockAccessor rs = new BlockAccessor(databuffer);
                SegmentBlockBasicDecoder decoder = new SegmentBlockBasicDecoder(rs);
                for (int i = testvalues.Length -1; i >= 0; i--) {
                    RecordKey tkey = new RecordKey().appendParsedKey(testvalues[i]);
                    RecordUpdate tupdate = RecordUpdate.WithPayload("data: " + testvalues[i]);

                    KeyValuePair<RecordKey,RecordUpdate> row = decoder.FindNext(tkey, true);
                    Assert.AreEqual(tkey, row.Key,  "record keys should match");
                    Assert.AreEqual(tupdate, row.Value, "record values should match:");
                }
            }

            // test FindNext(key,equal_ok=false)
            {
                BlockAccessor rs = new BlockAccessor(databuffer);
                SegmentBlockBasicDecoder decoder = new SegmentBlockBasicDecoder(rs);
                for (int i = testvalues.Length - 2; i >= 0; i--) {
                    RecordKey tkey = new RecordKey().appendParsedKey(testvalues[i]);
                    RecordUpdate tupdate = RecordUpdate.WithPayload("data: " + testvalues[i]);

                    RecordKey fkey = new RecordKey().appendParsedKey(testvalues[i + 1]);
                    RecordUpdate fupdate = RecordUpdate.WithPayload("data: " + testvalues[i+1]);

                    KeyValuePair<RecordKey, RecordUpdate> row = decoder.FindNext(tkey, false);
                    Assert.AreEqual(fkey, row.Key, "findnext(,false) should find next key");
                    Assert.AreEqual(fupdate, row.Value, "findnext(,false) should finx next key (value was botched)");
                }

                // test for "next" after end of buffer, and we should get an exception
                // test for "next" at beginning and we should get first
                // test some random values in the middle

            }
        }
        public void T02_BasicBlock_Enumerators()
        {
            // exercize the iscannable interface
            string[] testvalues = { "test/1", "test/2", "test/3" };
            byte[] databuffer;

            // encode a buffer
            {
                MemoryStream ms = new MemoryStream();
                // add some values to the block encoder
                SegmentBlockBasicEncoder enc = new SegmentBlockBasicEncoder();
                enc.setStream(ms);
                for (int i = 0; i < testvalues.Length; i++) {
                    RecordKey tkey = new RecordKey().appendParsedKey(testvalues[i]);
                    RecordUpdate tupdate = RecordUpdate.WithPayload("data: " + testvalues[i]);

                    enc.add(tkey, tupdate);
                }
                enc.flush();

                databuffer = ms.ToArray();
            }

            // decode and test the buffer, scan enumerators
            {
                BlockAccessor rs = new BlockAccessor(databuffer);
                SegmentBlockBasicDecoder decoder = new SegmentBlockBasicDecoder(rs);
                int pos = 0;
                IScanner<RecordKey> scanner = ScanRange<RecordKey>.All();
                foreach (KeyValuePair<RecordKey, RecordUpdate> row in decoder.scanForward(scanner)) {
                    RecordKey tkey = new RecordKey().appendParsedKey(testvalues[pos]);
                    RecordUpdate tupdate = RecordUpdate.WithPayload("data: " + testvalues[pos]);

                    Assert.AreEqual(tkey, row.Key, "forward, record keys should match");
                    Assert.AreEqual(tupdate, row.Value, "forward, record values should match:");
                    pos++;
                }
                Assert.AreEqual(testvalues.Length, pos, "forward, should return all values we put in");

                pos = testvalues.Length - 1;
                foreach (KeyValuePair<RecordKey, RecordUpdate> row in decoder.scanBackward(scanner)) {
                    RecordKey tkey = new RecordKey().appendParsedKey(testvalues[pos]);
                    RecordUpdate tupdate = RecordUpdate.WithPayload("data: " + testvalues[pos]);

                    Assert.AreEqual(tkey, row.Key, "backward, record keys should match, pos=" + pos);
                    Assert.AreEqual(tupdate, row.Value, "backward, record values should match:");
                    pos--;
                }
                Assert.AreEqual(-1, pos, "backward, should return all values we put in");

            }
        }
示例#6
0
        public void setValue(RecordKey key, RecordUpdate update)
        {
            // build a byte[] for the updates using the basic block encoder
            MemoryStream writer = new MemoryStream();
            // TODO: this seems like a really inefficient way to write out a key
            ISegmentBlockEncoder encoder = new SegmentBlockBasicEncoder();
            encoder.setStream(writer);
            encoder.add(key, update);
            encoder.flush();
            writer.Flush();
            this.addCommand((byte)LogCommands.UPDATE, writer.ToArray());

            // Writes are actually applied to the workingSegment when the LgoWriter pushes them to the ILogReceiver.
            // This assures, for example, that DISK_ATOMIC writes to not apply to the segments until the writegroup is flushed.
        }