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));
            }
        }
Exemple #5
0
        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);
            }
        }
Exemple #6
0
        // 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;
        }
Exemple #7
0
 // 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();
 }