private void _organizeLogSegments(RootBlockLogSegment[] segments) { BDSkipList<long, RootBlockLogSegment> order_segments = new BDSkipList<long, RootBlockLogSegment>(); // (2) scan and organize the log-segments (so they are in proper order) foreach (RootBlockLogSegment seg in segments) { Stream logsegment = regionmgr.readRegionAddr(seg.logsegment_start).getNewAccessStream(); BinaryReader br = new BinaryReader(logsegment); LogPacketHeader hdr = Util.readStruct<LogPacketHeader>(br); if (hdr.magic != LogPacketHeader.LOG_MAGIC) { abortCorrupt(String.Format("_organizeLogSegments() found corrupt log segment! magic => {0}", hdr.magic)); } if (hdr.cmddata_length == 0 && hdr.checksum == 0) { empty_log_segments.Add(seg); } else { order_segments.Add(hdr.curLWSN, seg); } logsegment.Close(); } // now insert the active segments in proper order.. foreach (var kvp in order_segments.scanForward(ScanRange<long>.All())) { Console.WriteLine("active segment: {0}", kvp.Key); active_log_segments.Add(kvp.Value); } }
private long _logWaitSequenceNumber = 1; // this must be recovered during recovery... #endregion Fields #region Constructors public LogSegmentsHandler(LogWriter logwriter, IRegionManager regionmgr, RootBlockLogSegment[] segments) { nextChunkBuffer = new BinaryWriter(new MemoryStream()); this.regionmgr = regionmgr; this.logwriter = logwriter; _organizeLogSegments(segments); }
public void prepareLog() { // make sure there is an active log segment if (active_log_segments.Count == 0) { // move an empty log segment to active... lock (this) { active_log_segments.Add(empty_log_segments[0]); empty_log_segments.RemoveAt(0); } } // open the current log stream... currentLogSegmentInfo = active_log_segments[active_log_segments.Count - 1]; // get last currentLogHeadStream = regionmgr.writeExistingRegionAddr(currentLogSegmentInfo.logsegment_start).getNewAccessStream(); // move to the "end" of this active segment }
public void advanceActiveLogSegment() { Console.WriteLine("advance to next segment"); // close the current active segment currentLogHeadStream.Close(); // advance to the next empty log stream... if (empty_log_segments.Count == 0) { // no more empty log segments! this.logwriter.receiver.requestLogExtension(); if (empty_log_segments.Count == 0) { throw new Exception("forceCheckpoint() failed to free log segments"); } } this.notifyLogStatus(); lock (this) { currentLogSegmentInfo = empty_log_segments[0]; empty_log_segments.RemoveAt(0); active_log_segments.Add(currentLogSegmentInfo); } // open the current log stream... currentLogHeadStream = regionmgr.writeExistingRegionAddr(currentLogSegmentInfo.logsegment_start).getNewAccessStream(); if (currentLogHeadStream.Position != 0) { throw new Exception(String.Format("advanced to non-start of segment! pos = {0}", currentLogHeadStream.Position)); } }
private void _InitResume(IRegionManager regionmgr) { this.rootblockstream = regionmgr.readRegionAddr(0).getNewAccessStream(); root = Util.readStruct<RootBlockHeader>(rootblockstream); if (!root.IsValid()) { throw new Exception("invalid root block"); } RootBlockLogSegment[] log_segments = new RootBlockLogSegment[root.num_logsegments]; for (int i=0;i<root.num_logsegments;i++) { log_segments[i] = Util.readStruct<RootBlockLogSegment>(rootblockstream); } // setup the log segment handler this.log_handler = new LogSegmentsHandler(this,regionmgr, log_segments); foreach (LogCmd cmd in log_handler.recoverLogCmds()) { receiver.handleCommand(cmd.cmd, cmd.cmddata); } }
// special "init" of a region private void _InitNewRegion(IRegionManager regionmgr, out int system_reserved_space) { // test to see if there is already a root record there { try { Stream testrootblockstream = regionmgr.readRegionAddr(0).getNewAccessStream(); RootBlockHeader nroot = Util.readStruct<RootBlockHeader>(testrootblockstream); long rtblksz = testrootblockstream.Position; if (nroot.IsValid()) { // TODO: we should be careful not to overwrite an existing root record... // throw new Exception("existing root record present! Can't re-init."); } testrootblockstream.Close(); } catch (RegionExposedFiles.RegionMissingException) { } } // (1) initialize the log segments... RootBlockLogSegment[] log_segments = new RootBlockLogSegment[LogWriter.DEFAULT_LOG_SEGMENTS]; uint nextFreeAddress = RootBlockHeader.ROOTBLOCK_SIZE; for (int i=0;i<log_segments.Length;i++) { // calculate the segment start and length log_segments[i].logsegment_size = LogWriter.DEFAULT_LOG_SEGMENT_SIZE; log_segments[i].logsegment_start = nextFreeAddress; nextFreeAddress += LogWriter.DEFAULT_LOG_SEGMENT_SIZE; // open the segment Stream logstream = regionmgr.writeFreshRegionAddr(log_segments[i].logsegment_start, log_segments[i].logsegment_size).getNewAccessStream(); // write to the end of the log to be sure the file/stream has enough space logstream.Seek(log_segments[i].logsegment_size - 1, SeekOrigin.Begin); logstream.WriteByte(0x00); logstream.Flush(); logstream.Seek(0, SeekOrigin.Begin); LogSegmentsHandler.InitLogSegmentStream(logstream); // write the initial "log-end" record at the beginning of the segment logstream.Close(); } root.magic = RootBlockHeader.ROOTMAGIC; root.root_checksum = 0; byte[] root_block_data = root.constructRootBlock(log_segments); // open the streams... Stream rootblockwritestream = regionmgr.writeFreshRegionAddr(0, (long)RootBlockHeader.ROOTBLOCK_SIZE).getNewAccessStream(); // this.logstream = logwritestream; this.rootblockstream = rootblockwritestream; // now write the root record rootblockstream.Seek(0, SeekOrigin.Begin); rootblockstream.Write(root_block_data,0,root_block_data.Length); rootblockstream.Flush(); rootblockstream.Close(); // must close the stream so resume can operate system_reserved_space = (int)nextFreeAddress; }
// utility... public byte[] constructRootBlock(RootBlockLogSegment[] segments) { this.num_logsegments = (uint)segments.Length; MemoryStream ms = new MemoryStream(); Util.writeStruct(this, ms); foreach (RootBlockLogSegment seg in segments) { Util.writeStruct(seg, ms); } return ms.ToArray(); }