1 /* Copyright (C) 2004 - 2009 Versant Inc. http://www.db4o.com */ 2 3 using System; 4 using Db4objects.Db4o.Foundation; 5 using Db4objects.Db4o.Internal; 6 using Db4objects.Db4o.Internal.Freespace; 7 using Db4objects.Db4o.Internal.Slots; 8 9 namespace Db4objects.Db4o.Internal.Freespace 10 { 11 public abstract class AbstractFreespaceManager : IFreespaceManager 12 { 13 public const byte FmDebug = 127; 14 15 public const byte FmDefault = 0; 16 17 public const byte FmLegacyRam = 1; 18 19 public const byte FmRam = 2; 20 21 public const byte FmIx = 3; 22 23 public const byte FmBtree = 4; 24 25 private const int IntsInSlot = 12; 26 27 public const int RemainderSizeLimit = 20; 28 CheckType(byte systemType)29 public static byte CheckType(byte systemType) 30 { 31 if (systemType == FmDefault) 32 { 33 return FmRam; 34 } 35 return systemType; 36 } 37 38 protected IProcedure4 _slotFreedCallback; 39 40 private readonly int _discardLimit; 41 AbstractFreespaceManager(IProcedure4 slotFreedCallback, int discardLimit)42 public AbstractFreespaceManager(IProcedure4 slotFreedCallback, int discardLimit) 43 { 44 _slotFreedCallback = slotFreedCallback; 45 _discardLimit = discardLimit; 46 } 47 CreateNew(LocalObjectContainer file)48 public static Db4objects.Db4o.Internal.Freespace.AbstractFreespaceManager CreateNew 49 (LocalObjectContainer file) 50 { 51 return CreateNew(file, file.SystemData().FreespaceSystem()); 52 } 53 CreateNew(LocalObjectContainer file, byte systemType)54 public static Db4objects.Db4o.Internal.Freespace.AbstractFreespaceManager CreateNew 55 (LocalObjectContainer file, byte systemType) 56 { 57 systemType = CheckType(systemType); 58 int unblockedDiscardLimit = file.ConfigImpl.DiscardFreeSpace(); 59 int blockedDiscardLimit = unblockedDiscardLimit == int.MaxValue ? unblockedDiscardLimit 60 : file.BlockConverter().BytesToBlocks(unblockedDiscardLimit); 61 IProcedure4 slotFreedCallback = new _IProcedure4_50(file); 62 switch (systemType) 63 { 64 case FmIx: 65 { 66 return new FreespaceManagerIx(blockedDiscardLimit); 67 } 68 69 case FmBtree: 70 { 71 return new BTreeFreespaceManager(file, slotFreedCallback, blockedDiscardLimit); 72 } 73 74 default: 75 { 76 return new InMemoryFreespaceManager(slotFreedCallback, blockedDiscardLimit); 77 break; 78 } 79 } 80 } 81 82 private sealed class _IProcedure4_50 : IProcedure4 83 { _IProcedure4_50(LocalObjectContainer file)84 public _IProcedure4_50(LocalObjectContainer file) 85 { 86 this.file = file; 87 } 88 Apply(object slot)89 public void Apply(object slot) 90 { 91 file.OverwriteDeletedBlockedSlot(((Slot)slot)); 92 } 93 94 private readonly LocalObjectContainer file; 95 } 96 InitSlot(LocalObjectContainer file)97 public static int InitSlot(LocalObjectContainer file) 98 { 99 int address = file.AllocateSlot(SlotLength()).Address(); 100 SlotEntryToZeroes(file, address); 101 return address; 102 } 103 MigrateTo(IFreespaceManager fm)104 public virtual void MigrateTo(IFreespaceManager fm) 105 { 106 Traverse(new _IVisitor4_72(fm)); 107 } 108 109 private sealed class _IVisitor4_72 : IVisitor4 110 { _IVisitor4_72(IFreespaceManager fm)111 public _IVisitor4_72(IFreespaceManager fm) 112 { 113 this.fm = fm; 114 } 115 Visit(object obj)116 public void Visit(object obj) 117 { 118 fm.Free((Slot)obj); 119 } 120 121 private readonly IFreespaceManager fm; 122 } 123 SlotEntryToZeroes(LocalObjectContainer file, int address)124 internal static void SlotEntryToZeroes(LocalObjectContainer file, int address) 125 { 126 StatefulBuffer writer = new StatefulBuffer(file.SystemTransaction(), address, SlotLength 127 ()); 128 for (int i = 0; i < IntsInSlot; i++) 129 { 130 writer.WriteInt(0); 131 } 132 writer.WriteEncrypt(); 133 } 134 SlotLength()135 internal static int SlotLength() 136 { 137 return Const4.IntLength * IntsInSlot; 138 } 139 TotalFreespace()140 public virtual int TotalFreespace() 141 { 142 IntByRef mint = new IntByRef(); 143 Traverse(new _IVisitor4_97(mint)); 144 return mint.value; 145 } 146 147 private sealed class _IVisitor4_97 : IVisitor4 148 { _IVisitor4_97(IntByRef mint)149 public _IVisitor4_97(IntByRef mint) 150 { 151 this.mint = mint; 152 } 153 Visit(object obj)154 public void Visit(object obj) 155 { 156 Slot slot = (Slot)obj; 157 mint.value += slot.Length(); 158 } 159 160 private readonly IntByRef mint; 161 } 162 DiscardLimit()163 protected virtual int DiscardLimit() 164 { 165 return _discardLimit; 166 } 167 SplitRemainder(int length)168 protected bool SplitRemainder(int length) 169 { 170 if (CanDiscard(length)) 171 { 172 return false; 173 } 174 return length > RemainderSizeLimit; 175 } 176 CanDiscard(int length)177 internal bool CanDiscard(int length) 178 { 179 return length == 0 || length < DiscardLimit(); 180 } 181 Migrate(IFreespaceManager oldFM, IFreespaceManager newFM)182 public static void Migrate(IFreespaceManager oldFM, IFreespaceManager newFM) 183 { 184 oldFM.MigrateTo(newFM); 185 oldFM.FreeSelf(); 186 } 187 DebugCheckIntegrity()188 public virtual void DebugCheckIntegrity() 189 { 190 IntByRef lastStart = new IntByRef(); 191 IntByRef lastEnd = new IntByRef(); 192 Traverse(new _IVisitor4_129(lastEnd, lastStart)); 193 } 194 195 private sealed class _IVisitor4_129 : IVisitor4 196 { _IVisitor4_129(IntByRef lastEnd, IntByRef lastStart)197 public _IVisitor4_129(IntByRef lastEnd, IntByRef lastStart) 198 { 199 this.lastEnd = lastEnd; 200 this.lastStart = lastStart; 201 } 202 Visit(object obj)203 public void Visit(object obj) 204 { 205 Slot slot = (Slot)obj; 206 if (slot.Address() <= lastEnd.value) 207 { 208 throw new InvalidOperationException(); 209 } 210 lastStart.value = slot.Address(); 211 lastEnd.value = slot.Address() + slot.Length(); 212 } 213 214 private readonly IntByRef lastEnd; 215 216 private readonly IntByRef lastStart; 217 } 218 MigrationRequired(byte systemType)219 public static bool MigrationRequired(byte systemType) 220 { 221 return systemType == FmLegacyRam || systemType == FmIx; 222 } 223 SlotFreed(Slot slot)224 public virtual void SlotFreed(Slot slot) 225 { 226 if (_slotFreedCallback == null) 227 { 228 return; 229 } 230 _slotFreedCallback.Apply(slot); 231 } 232 AllocateSafeSlot(int arg1)233 public abstract Slot AllocateSafeSlot(int arg1); 234 AllocateSlot(int arg1)235 public abstract Slot AllocateSlot(int arg1); 236 AllocateTransactionLogSlot(int arg1)237 public abstract Slot AllocateTransactionLogSlot(int arg1); 238 BeginCommit()239 public abstract void BeginCommit(); 240 Commit()241 public abstract void Commit(); 242 EndCommit()243 public abstract void EndCommit(); 244 Free(Slot arg1)245 public abstract void Free(Slot arg1); 246 FreeSafeSlot(Slot arg1)247 public abstract void FreeSafeSlot(Slot arg1); 248 FreeSelf()249 public abstract void FreeSelf(); 250 IsStarted()251 public abstract bool IsStarted(); 252 Listener(IFreespaceListener arg1)253 public abstract void Listener(IFreespaceListener arg1); 254 Read(LocalObjectContainer arg1, Slot arg2)255 public abstract void Read(LocalObjectContainer arg1, Slot arg2); 256 SlotCount()257 public abstract int SlotCount(); 258 Start(int arg1)259 public abstract void Start(int arg1); 260 SystemType()261 public abstract byte SystemType(); 262 Traverse(IVisitor4 arg1)263 public abstract void Traverse(IVisitor4 arg1); 264 Write(LocalObjectContainer arg1)265 public abstract void Write(LocalObjectContainer arg1); 266 } 267 } 268