public void handleCommand(LogCommands cmd, byte[] cmddata) { if (cmd == LogCommands.UPDATE) { // decode basic block key/value writes BlockAccessor ba = new BlockAccessor(cmddata); ISegmentBlockDecoder decoder = new SegmentBlockBasicDecoder(ba); foreach (KeyValuePair<RecordKey, RecordUpdate> kvp in decoder.sortedWalk()) { // add the updates to our working segment... lock (mylayer.segmentlayers) { #if false // some status debug code... if (RangemapManager.RangeKey.isRangeKey(kvp.Key)) { System.Console.WriteLine("LayerManager.handleCommand : setValue() {0} => {1}", kvp.Key.ToString(), kvp.Value.ToString()); if (kvp.Value.type != RecordUpdateTypes.DELETION_TOMBSTONE && kvp.Value.data.Length != 16) { throw new Exception("!!! corrupted rangekey appeared in handleCommand"); } } #endif mylayer.workingSegment.setRecord(kvp.Key, kvp.Value); } } } else if (cmd == LogCommands.CHECKPOINT_START) { // here we move aside the checkpoint segment... // - if this is during live operation, the checkpoint is running as soon as we return. // - if this is during recovery, there is no checkpoint running and we'll need to // TODO: we need some kind of key/checksum to be sure that we CHECKPOINT and DROP the right dataF checkpointSegment = mylayer.workingSegment; SegmentMemoryBuilder newsegment = new SegmentMemoryBuilder(); lock (mylayer.segmentlayers) { mylayer.workingSegment = newsegment; mylayer.segmentlayers.Insert(0, mylayer.workingSegment); } } else if (cmd == LogCommands.CHECKPOINT_DROP) { // TODO: we need some kind of key/checksum to be sure that we CHECKPOINT and DROP the right data if (checkpointSegment != null) { lock (mylayer.segmentlayers) { mylayer.segmentlayers.Remove(checkpointSegment); checkpointSegment = null; } } else { throw new Exception("can't drop, no segment to drop"); } } else { throw new Exception("unimplemented command"); } }
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!"); } } }
internal void applyLogEntry(string from_server_guid, long logstamp, RecordUpdate logdata) { // (0) unpack the data BlockAccessor ba = new BlockAccessor(logdata.data); ISegmentBlockDecoder decoder = new SegmentBlockBasicDecoder(ba); // (1) add it to our copy of that server's log this._recordLogEntry(from_server_guid, logstamp, logdata); // (2) add it to the database foreach (var kvp in decoder.sortedWalk()) { RecordKey local_data_key = new RecordKey() .appendKeyPart("_data"); foreach (var part in kvp.Key.key_parts) { local_data_key.appendKeyPart(part); } next_stage.setValue(local_data_key, kvp.Value); } }
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"); } }