private FileHeader m_fileHeader; //the only file header in the two files, it is located at page 0. public memSegmentManager(DiskFile file) { m_cache = new CacheHashtable(m_cacheSize); m_pageSize = 1 << m_pageBits; m_diskFile = file; m_bitmap = new PageBitmap(); m_fileHeader = new FileHeader(); if (file.Length < m_bitmap.Data.Length + m_pageSize*2) //page 0 for fileheader, page 33 for segTree, page 44 for spacetree { //this helper file is a new one for (int i=0; i<(m_bitmap.Data.Length >> (m_pageBits + 3)); i++) m_bitmap.Data[i] = 0xFF; m_bitmap.SetPageTaken(m_bitmap.GetFirstFreePageID()); //one more page taken because of the fileheader m_bitmap.Dirty = true; m_fileHeader.SetInitializeNeeded(); } else { byte[] header = file.SynRead(0, m_pageSize); m_fileHeader.Deserialize(header); file.SynRead(m_bitmap.Data, 0, m_pageSize, m_bitmap.Data.Length); } m_LRU = new BNode(); }
public bool Insert(Segment seg) { Debug.Assert(Exists(seg.SegmentID) == false); int pos = (int)(seg.SegmentID % m_size); CacheEntry head = m_data[pos]; if (head == null) m_data[pos] = new CacheEntry(seg); else { while (head.Next != null &&head.Segment.SegmentID != seg.SegmentID) { head = head.Next; } if (head.Segment.SegmentID == seg.SegmentID) return false; else { head.Next = new CacheEntry(seg,null); } } m_count ++; return true; }
public override Segment GetSegment(uint segId, Segment segFactory, object helper) { Debug.Assert(segId >= (m_bitmap.Data.Length >> m_pageBits)); Debug.Assert(m_bitmap.PageFree(segId) == false); if (m_cache.Exists(segId)) { //requested page is in the cache Segment seg = m_cache.Retrive(segId); //update recently used page list, move this one to the front of the list, most recently used. seg.BreakLinks(); seg.BuildLinks(m_LRU, m_LRU.Next); return seg; } else { //the requested page is not in the cache, read it from disk byte[] content = m_diskFile.SynRead(segId*m_pageSize, m_pageSize); Segment seg = segFactory.Deserialize(segId, helper, content); _put_in_cache(seg); return seg; } }
public void BreakLinks() { m_prev.m_next = m_next; m_next.m_prev = m_prev; m_next = m_prev = this; }
public void BuildLinks(Segment prev, Segment next) { m_prev = prev; m_next = next; prev.m_next = this; next.m_prev = this; }
private int m_threshold = 256; //256 bytes public dbSegmentManager(uint nextSegmentId, SegTree segTree, SpaceTree spaceTree, DiskFile file) { m_next_segment_id = nextSegmentId; m_segTree = segTree; m_cache = new CacheHashtable(m_cacheSize); m_diskFile = file; m_spaceTree = spaceTree; m_LRU = new BNode(); }
public override Segment GetSegment(uint segId, Segment segFactory, object helper) { Segment result = null; //check if this segment is already in cache if (m_cache.Exists(segId)) { result = m_cache.Retrive(segId); //update the least recently used list result.BreakLinks(); result.BuildLinks(m_LRU, m_LRU.Next); return result; } else { //if not, read that from disk uint offset = 0; int length = 0; if (m_segTree.GetAddr(segId, ref offset, ref length)) { // put this segment into cache byte[] content = m_diskFile.SynRead(offset, length); result = segFactory.Deserialize(segId, helper, content); _put_in_cache(result); } else throw new OOD.Exception.ProgramLogicError( this, "Trying to access a non-existing segment."); return result; } }
/// <summary> /// insert this segment into cache, kick out other if needed /// </summary> /// <param name="seg"></param> /// <precondition>seg is a new page brought in memory</precondition> /// <postcondition>seg is insert into the cache, and the front of the LRU list, kick out one page if needed.</postcondition> internal void _put_in_cache(Segment seg) { //if the cache is full, kick least recently used one out if (m_cache.Count > m_cacheLimit) { //pick least recently used one Segment victim = m_LRU.Prev; Debug.Assert(victim != m_LRU); if (victim.Dirty) { _write_back(victim); } victim.BreakLinks(); bool t = m_cache.Delete(victim.SegmentID);//removed this one out of the cache Debug.Assert(t); } if (m_cache.Insert(seg) == false) throw new OOD.Exception.ProgramLogicError( this, "Trying to insert an existing key into CacheHashtable"); seg.BuildLinks(m_LRU, m_LRU.Next); //move it the front of the LRU list }
public override void FreeSegment(Segment seg) { //remove it from cache this.m_cache.Delete(seg.SegmentID); //remove it from LRU list seg.BreakLinks(); uint offset = 0; int length = -1; if (m_segTree.GetAddr(seg.SegmentID, ref offset, ref length)) { Debug.Assert(length != -1); //this segment's addressing info is in the system. //put this segment into the free tree m_spaceTree.SetSegmentFree(offset, length); //remove its addressing information from segTree m_segTree.DeleteSegment(seg.SegmentID); } //if this segment is never written back to disk, just delete it from memory is enough }
public override void GetNewSegment(Segment seg) { seg.SegmentID = m_next_segment_id; seg.Initialize(m_next_segment_id++); _put_in_cache(seg); }
internal void _write_back(Segment seg) { //write it out to the disk byte[] content = seg.Serialize(); //get its offset and length for the segment uint offset = 0; int length = -1; if (m_segTree.GetAddr(seg.SegmentID, ref offset, ref length)) { Debug.Assert(length != -1); if (content.Length > length) { //original space is too small //0. put original one fre m_spaceTree.SetSegmentFree(offset, length); //1. request a new segment with size = cotent.length + m_threshold; if (m_spaceTree.RequireSegment(content.Length+m_threshold, ref offset) == false) throw new OOD.Exception.ProgramLogicError( this, "Error happed while requesting free space."); //3. update the new addressing in m_segTree. if (m_segTree.UpdateAddr(seg.SegmentID, offset, content.Length + m_threshold) == false) throw new OOD.Exception.ProgramLogicError( this, "Erro happened while updating addressing."); } else if (content.Length < length - m_threshold) { //original space is too big, shrink it to length + 256; //1. update the addressing information in seqTree // int newLength = content.Length + m_threshold; // m_segTree.UpdateAddr(seg.SegmentID, offset, newLength); // // //2. insert the left empty space into the spaceTree // uint leftOffset = (uint)(offset + newLength); // newLength = length - newLength; // m_spaceTree.SetSegmentFree(leftOffset, newLength); } } else { Debug.Assert(length == -1); //this is a new segment, it is never assigned adress before //1. Request a free space if (m_spaceTree.RequireSegment(content.Length + m_threshold, ref offset) == false) throw new OOD.Exception.ProgramLogicError( this, "Request space failed."); //2.put this into the m_segTree if (m_segTree.InsertAddr(seg.SegmentID, offset, content.Length + m_threshold)==false) throw new OOD.Exception.ProgramLogicError( this, "put segment addressing info failed in SegTree."); } m_diskFile.SynWrite(content, 0, offset, content.Length); }
public abstract void FreeSegment(Segment seg);
public abstract void GetNewSegment(Segment seg);
/// <summary> /// insert this segment into cache, kick out other if needed /// </summary> /// <param name="seg"></param> /// <precondition>seg is a new page brought in memory</precondition> /// <postcondition>seg is insert into the cache, and the front of the LRU list, kick out one page if needed.</postcondition> internal void _put_in_cache(Segment seg) { //if the cache is full, kick least recently used one out if (m_cache.Count > m_cacheLimit) { //pick least recently used one Segment victim = m_LRU.Prev; Debug.Assert(victim != m_LRU); if (victim.Dirty) { //write it out to the disk byte[] content = victim.Serialize(); Debug.Assert(content.Length <= m_pageSize); m_diskFile.SynWrite(content, 0, victim.SegmentID*m_pageSize, content.Length); } victim.BreakLinks(); bool t = m_cache.Delete(victim.SegmentID);//removed this one out of the cache Debug.Assert(t); } if (m_cache.Insert(seg) == false) throw new OOD.Exception.ProgramLogicError( this, "Trying to insert a existing key into CacheHashtable."); seg.BuildLinks(m_LRU, m_LRU.Next); //move it the front of the LRU list }
public override void FreeSegment(Segment seg) { m_bitmap.SetPageFree(seg.SegmentID); //remove that one from cache m_cache.Delete(seg.SegmentID); //remove it from the LRU list also seg.BreakLinks(); }
public override void GetNewSegment(Segment seg) { uint segId = m_bitmap.GetFirstFreePageID(); seg.Initialize(segId); m_bitmap.SetPageTaken(segId); //put the new node into cache //kick out one if needed _put_in_cache(seg); }
public abstract Segment GetSegment(uint segId, Segment segFactory, object helper);
protected Segment() { m_prev = m_next = this; }