/// <summary> /// RemoveIntersections will check whether an area on disk was already /// inclusive in any of the segment areas stored as entries in a store (addStore). /// If input area is fully inclusive, this function returns null, otherwise /// it will return a region equivalent to the input area minus any intersecting /// area(s) of segment(s) in the store. /// </summary> /// <param name="addStore"></param> /// <param name="key"></param> /// <param name="blockAddress"></param> /// <param name="segmentSize"></param> /// <returns></returns> public Region RemoveIntersections( Collections.Generic.ISortedDictionary <Transaction.Transaction.RecordKey, long> addStore, Transaction.Transaction.RecordKey key, long blockAddress, int segmentSize) { if (addStore.Search(key)) { long size = (long)addStore.CurrentValue; if (size >= segmentSize) { return(null); } } else if (!addStore.MovePrevious()) { addStore.MoveFirst(); } //** Step 1 //** Starting from current block until block whose address is > BlockAddress + SegmentSize... //** long[0] = Address //** long[1] = Size var region = new Region(blockAddress, segmentSize); Transaction.Transaction.RecordKey k2; short passCount = 0; while (!addStore.EndOfTree()) { var de = addStore.CurrentEntry; k2 = de.Value.Key; if (k2.ServerSystemFilename == key.ServerSystemFilename && k2.Filename == key.Filename) // && k2.CollectionName == key.CollectionName) { long size = de.Value.Value; if (k2.Address >= blockAddress + segmentSize) { break; } if (size > int.MaxValue) { throw new InvalidOperationException( string.Format( "Updated segment Size({0} reached > int.MaxValue which isn't supported in a transaction. Keep your transaction smaller by Committing more often", size)); } if (Intersect(k2.Address, (int)size, blockAddress, segmentSize)) { region.Subtract(k2.Address, (int)size); if (region.Count == 0) { return(null); } } else if (++passCount >= 2) { break; } } else if (++passCount >= 2) { break; } if (!addStore.MoveNext()) { break; } } return(region); }
internal static bool DetectAndMerge(Collections.Generic.ISortedDictionary <long, long> store, long dataAddress, long dataSize, int segmentSize = DataBlock.DataBlockDriver.MaxSegmentSize, RegionLogic region = null) { if (store.Count == 0) { if (dataSize > segmentSize) { return(false); } store.Add(dataAddress, dataSize); return(true); } if (store.Search(dataAddress)) { long currSize = store.CurrentValue; if (currSize < dataSize) { store.CurrentValue = dataSize; } return(true); } //** Detect and merge contiguous deleted blocks short passCount = 0; if (!store.MovePrevious()) { store.MoveFirst(); } while (true) { KeyValuePair <long, long>?item = store.CurrentEntry; long k2 = item.Value.Key; long i = 0; long cv = store.CurrentValue; i = cv; if (region != null) { if (region.Equals(dataAddress, dataSize, k2, i) || region.FirstWithinSecond(dataAddress, dataSize, k2, i)) { return(true); } if (region.FirstWithinSecond(k2, i, dataAddress, dataSize)) { store.Remove(k2); store.Add(dataAddress, dataSize); return(true); } } if (dataAddress + dataSize == k2) { long newSize = i + dataSize; if (newSize <= segmentSize) { store.Remove(item.Value.Key); store.Add(dataAddress, newSize); return(true); } return(false); } if (k2 + i == dataAddress) { if (i + dataSize <= segmentSize) { store.CurrentValue = i + dataSize; return(true); } return(false); } if (++passCount >= 2) { break; } if (!store.MoveNext()) { break; } } return(false); }