private Bucket SetBucket(byte[] key, int offset, Bucket b) { bool found = false; int pos = FindPointerOrLower(b, new bytearr(key), out found); if (found) { KeyPointer p = b.Pointers[pos]; int v = p.RecordNum; // duplicate found if (v != offset) { p.RecordNum = offset; DirtyBucket(b); } } else { if (b.Pointers.Count < _bucketItems) { KeyPointer k = new KeyPointer(new bytearr(key), offset); pos++; if (pos < b.Pointers.Count) b.Pointers.Insert(pos, k); else b.Pointers.Add(k); DirtyBucket(b); } else { int p = b.NextPageNumber; if (p != -1) { b = LoadBucket(p); SetBucket(key, offset, b); } else { Bucket newb = new Bucket(_indexfile.GetNewPageNumber()); b.NextPageNumber = newb.DiskPageNumber; DirtyBucket(b); SetBucket(key, offset, newb); } } } return b; }
public Bucket LoadBucketFromPage(int page) { SeekPage(page); byte[] b = new byte[_PageLength]; _file.Read(b, 0, _PageLength); if (b[0] == _BlockHeader[0] && b[1] == _BlockHeader[1] && b[2] == _BlockHeader[2] && b[3] == _BlockHeader[3]) { // create node here int bucketnum = Helper.ToInt32(b, 7); List<KeyPointer> list = new List<KeyPointer>(); List<int> dups = new List<int>(); short count = Helper.ToInt16(b, 5); if (count > _PageNodeCount) throw new Exception("Count > node size"); int nextpage = Helper.ToInt32(b, 11); int index = _BlockHeader.Length; if ((b[4] & 4) == 4) { int dupc = Helper.ToInt32(b, index); index += 4; for (int i = 0; i < dupc; i++) { int l = Helper.ToInt32(b, index); dups.Add(l); index += 4; } } else { for (int i = 0; i < count; i++) { int idx = index + _rowSize*i; byte ks = b[idx]; byte[] key = new byte[ks]; Buffer.BlockCopy(b, idx + 1, key, 0, ks); int offset = Helper.ToInt32(b, idx + 1 + _maxKeySize); int duppage = Helper.ToInt32(b, idx + 1 + _maxKeySize + 4); KeyPointer kp = new KeyPointer(new bytearr(key), offset, duppage); list.Add(kp); } } Bucket n = new Bucket(b[4], bucketnum, list, dups, page, nextpage); return n; } throw new Exception("Page read error"); }
public void SaveBucket(Bucket bucket) { int pnum = bucket.DiskPageNumber; if (pnum > _LastPageNumber) throw new Exception("should not be here: page out of bounds"); SeekPage(pnum); byte[] page = new byte[_PageLength]; Buffer.BlockCopy(_BlockHeader, 0, page, 0, _BlockHeader.Length); // bucket type if (bucket.isBucket) page[4] = 8; if (bucket.isOverflow) page[4] += 16; // bucket count byte[] b = Helper.GetBytes(bucket.Count, false); Buffer.BlockCopy(b, 0, page, 5, b.Length); // bucket number b = Helper.GetBytes(bucket.BucketNumber, false); Buffer.BlockCopy(b, 0, page, 7, b.Length); // next page number b = Helper.GetBytes(bucket.NextPageNumber, false); Buffer.BlockCopy(b, 0, page, 11, b.Length); int index = _BlockHeader.Length; if (bucket.isOverflow == true) { b = Helper.GetBytes(bucket.Duplicates.Count, false); Buffer.BlockCopy(b, 0, page, index, b.Length); index += b.Length; foreach (long p in bucket.Duplicates) { b = Helper.GetBytes(p, false); Buffer.BlockCopy(b, 0, page, index, b.Length); index += b.Length; } } else { // bucket children for (int i = 0; i < bucket.Count; i++) { KeyPointer kp = bucket.Pointers[i]; int idx = index + _rowSize*i; byte size = (byte) kp.Key.val.Length; if (size > _maxKeySize) size = _maxKeySize; // key size = 1 byte page[idx] = size; // key bytes Buffer.BlockCopy(bucket.Pointers[i].Key.val, 0, page, idx + 1, page[idx]); // offset = 4 bytes b = Helper.GetBytes(kp.RecordNum, false); Buffer.BlockCopy(b, 0, page, idx + 1 + _maxKeySize, b.Length); // duplicatepage = 4 bytes b = Helper.GetBytes(kp.DuplicatesPage, false); Buffer.BlockCopy(b, 0, page, idx + 1 + _maxKeySize + 4, b.Length); } } bucket.isOverflow = false; _file.Write(page, 0, page.Length); _file.Flush(); }
private Bucket CreateBucket(int bucketNumber) { var b = new Bucket(_indexfile.GetNewPageNumber()) {BucketNumber = bucketNumber}; // get next free indexfile pointer offset return b; }
private int FindPointerOrLower(Bucket b, bytearr key, out bool found) { found = false; if (b.Pointers.Count == 0) return 0; // binary search int lastlower = -1; int first = 0; int last = b.Pointers.Count - 1; int mid = 0; while (first <= last) { mid = (first + last) >> 1; KeyPointer k = b.Pointers[mid]; int compare = Helper.Compare(k.Key, key); if (compare < 0) { lastlower = mid; first = mid + 1; } if (compare == 0) { found = true; return mid; } if (compare > 0) { last = mid - 1; } } return lastlower; }
private void DirtyBucket(Bucket b) { if (b.isDirty) return; b.isDirty = true; if (_cachedBuckets.ContainsKey(b.DiskPageNumber) == false) _cachedBuckets.Add(b.DiskPageNumber, b); }
private bool SearchBucket(Bucket b, byte[] key, ref int offset) { bool found = false; int pos = FindPointerOrLower(b, new bytearr(key), out found); if (found) { KeyPointer k = b.Pointers[pos]; offset = k.RecordNum; return true; } else { if (b.NextPageNumber != -1) { b = LoadBucket(b.NextPageNumber); return SearchBucket(b, key, ref offset); } } return false; }