1 /* Copyright (C) 2004 - 2009 Versant Inc. http://www.db4o.com */ 2 3 using System; 4 using Db4objects.Db4o; 5 using Db4objects.Db4o.Ext; 6 using Db4objects.Db4o.Foundation; 7 using Db4objects.Db4o.Internal; 8 using Db4objects.Db4o.Internal.Btree; 9 using Db4objects.Db4o.Internal.Ids; 10 using Db4objects.Db4o.Internal.Slots; 11 using Db4objects.Db4o.Marshall; 12 13 namespace Db4objects.Db4o.Internal.Ids 14 { 15 /// <exclude></exclude> 16 public class BTreeIdSystem : IStackableIdSystem 17 { 18 private const int BtreeIdIndex = 0; 19 20 private const int IdGeneratorIndex = 1; 21 22 private const int ChildIdIndex = 2; 23 24 private readonly LocalObjectContainer _container; 25 26 private readonly IStackableIdSystem _parentIdSystem; 27 28 private readonly ITransactionalIdSystem _transactionalIdSystem; 29 30 private readonly SequentialIdGenerator _idGenerator; 31 32 private BTree _bTree; 33 34 private PersistentIntegerArray _persistentState; 35 BTreeIdSystem(LocalObjectContainer container, IStackableIdSystem parentIdSystem , int maxValidId)36 public BTreeIdSystem(LocalObjectContainer container, IStackableIdSystem parentIdSystem 37 , int maxValidId) 38 { 39 _container = container; 40 _parentIdSystem = parentIdSystem; 41 _transactionalIdSystem = container.NewTransactionalIdSystem(null, new _IClosure4_40 42 (parentIdSystem)); 43 int persistentArrayId = parentIdSystem.ChildId(); 44 if (persistentArrayId == 0) 45 { 46 InitializeNew(); 47 } 48 else 49 { 50 InitializeExisting(persistentArrayId); 51 } 52 _idGenerator = new SequentialIdGenerator(new _IFunction4_52(this), IdGeneratorValue 53 (), _container.Handlers.LowestValidId(), maxValidId); 54 } 55 56 private sealed class _IClosure4_40 : IClosure4 57 { _IClosure4_40(IStackableIdSystem parentIdSystem)58 public _IClosure4_40(IStackableIdSystem parentIdSystem) 59 { 60 this.parentIdSystem = parentIdSystem; 61 } 62 Run()63 public object Run() 64 { 65 return parentIdSystem; 66 } 67 68 private readonly IStackableIdSystem parentIdSystem; 69 } 70 71 private sealed class _IFunction4_52 : IFunction4 72 { _IFunction4_52(BTreeIdSystem _enclosing)73 public _IFunction4_52(BTreeIdSystem _enclosing) 74 { 75 this._enclosing = _enclosing; 76 } 77 Apply(object start)78 public object Apply(object start) 79 { 80 return this._enclosing.FindFreeId((((int)start))); 81 } 82 83 private readonly BTreeIdSystem _enclosing; 84 } 85 BTreeIdSystem(LocalObjectContainer container, IStackableIdSystem idSystem)86 public BTreeIdSystem(LocalObjectContainer container, IStackableIdSystem idSystem) 87 : this(container, idSystem, int.MaxValue) 88 { 89 } 90 InitializeExisting(int persistentArrayId)91 private void InitializeExisting(int persistentArrayId) 92 { 93 _persistentState = new PersistentIntegerArray(SlotChangeFactory.IdSystem, _transactionalIdSystem 94 , persistentArrayId); 95 _persistentState.Read(Transaction()); 96 _bTree = new BTree(Transaction(), BTreeConfiguration(), BTreeId(), new BTreeIdSystem.IdSlotMappingHandler 97 ()); 98 } 99 BTreeConfiguration()100 private Db4objects.Db4o.Internal.Btree.BTreeConfiguration BTreeConfiguration() 101 { 102 return new Db4objects.Db4o.Internal.Btree.BTreeConfiguration(_transactionalIdSystem 103 , SlotChangeFactory.IdSystem, 64, false); 104 } 105 IdGeneratorValue()106 private int IdGeneratorValue() 107 { 108 return _persistentState.Array()[IdGeneratorIndex]; 109 } 110 IdGeneratorValue(int value)111 private void IdGeneratorValue(int value) 112 { 113 _persistentState.Array()[IdGeneratorIndex] = value; 114 } 115 BTreeId()116 private int BTreeId() 117 { 118 return _persistentState.Array()[BtreeIdIndex]; 119 } 120 InitializeNew()121 private void InitializeNew() 122 { 123 _bTree = new BTree(Transaction(), BTreeConfiguration(), new BTreeIdSystem.IdSlotMappingHandler 124 ()); 125 int idGeneratorValue = _container.Handlers.LowestValidId() - 1; 126 _persistentState = new PersistentIntegerArray(SlotChangeFactory.IdSystem, _transactionalIdSystem 127 , new int[] { _bTree.GetID(), idGeneratorValue, 0 }); 128 _persistentState.Write(Transaction()); 129 _parentIdSystem.ChildId(_persistentState.GetID()); 130 } 131 FindFreeId(int start)132 private int FindFreeId(int start) 133 { 134 throw new NotImplementedException(); 135 } 136 Close()137 public virtual void Close() 138 { 139 } 140 CommittedSlot(int id)141 public virtual Slot CommittedSlot(int id) 142 { 143 IdSlotMapping mapping = (IdSlotMapping)_bTree.Search(Transaction(), new IdSlotMapping 144 (id, 0, 0)); 145 if (mapping == null) 146 { 147 throw new InvalidIDException(id); 148 } 149 return mapping.Slot(); 150 } 151 CompleteInterruptedTransaction(int transactionId1, int transactionId2 )152 public virtual void CompleteInterruptedTransaction(int transactionId1, int transactionId2 153 ) 154 { 155 } 156 157 // do nothing NewId()158 public virtual int NewId() 159 { 160 int id = _idGenerator.NewId(); 161 _bTree.Add(Transaction(), new IdSlotMapping(id, 0, 0)); 162 return id; 163 } 164 Transaction()165 private Db4objects.Db4o.Internal.Transaction Transaction() 166 { 167 return _container.SystemTransaction(); 168 } 169 Commit(IVisitable slotChanges, FreespaceCommitter freespaceCommitter )170 public virtual void Commit(IVisitable slotChanges, FreespaceCommitter freespaceCommitter 171 ) 172 { 173 _container.FreespaceManager().BeginCommit(); 174 slotChanges.Accept(new _IVisitor4_129(this)); 175 // TODO: Maybe we want a BTree that doesn't allow duplicates. 176 // Then we could do the following in one step without removing first. 177 _bTree.Commit(Transaction()); 178 IdGeneratorValue(_idGenerator.PersistentGeneratorValue()); 179 if (_idGenerator.IsDirty()) 180 { 181 _idGenerator.SetClean(); 182 _persistentState.SetStateDirty(); 183 } 184 if (_persistentState.IsDirty()) 185 { 186 _persistentState.Write(Transaction()); 187 } 188 _container.FreespaceManager().EndCommit(); 189 _transactionalIdSystem.Commit(freespaceCommitter); 190 _transactionalIdSystem.Clear(); 191 } 192 193 private sealed class _IVisitor4_129 : IVisitor4 194 { _IVisitor4_129(BTreeIdSystem _enclosing)195 public _IVisitor4_129(BTreeIdSystem _enclosing) 196 { 197 this._enclosing = _enclosing; 198 } 199 Visit(object slotChange)200 public void Visit(object slotChange) 201 { 202 if (!((SlotChange)slotChange).SlotModified()) 203 { 204 return; 205 } 206 this._enclosing._bTree.Remove(this._enclosing.Transaction(), new IdSlotMapping((( 207 TreeInt)slotChange)._key, 0, 0)); 208 if (((SlotChange)slotChange).RemoveId()) 209 { 210 return; 211 } 212 this._enclosing._bTree.Add(this._enclosing.Transaction(), new IdSlotMapping(((TreeInt 213 )slotChange)._key, ((SlotChange)slotChange).NewSlot())); 214 if (DTrace.enabled) 215 { 216 DTrace.SlotMapped.LogLength(((TreeInt)slotChange)._key, ((SlotChange)slotChange). 217 NewSlot()); 218 } 219 } 220 221 private readonly BTreeIdSystem _enclosing; 222 } 223 ReturnUnusedIds(IVisitable visitable)224 public virtual void ReturnUnusedIds(IVisitable visitable) 225 { 226 visitable.Accept(new _IVisitor4_167(this)); 227 } 228 229 private sealed class _IVisitor4_167 : IVisitor4 230 { _IVisitor4_167(BTreeIdSystem _enclosing)231 public _IVisitor4_167(BTreeIdSystem _enclosing) 232 { 233 this._enclosing = _enclosing; 234 } 235 Visit(object id)236 public void Visit(object id) 237 { 238 this._enclosing._bTree.Remove(this._enclosing.Transaction(), new IdSlotMapping((( 239 (int)id)), 0, 0)); 240 } 241 242 private readonly BTreeIdSystem _enclosing; 243 } 244 245 public class IdSlotMappingHandler : IIndexable4 246 { DefragIndexEntry(DefragmentContextImpl context)247 public virtual void DefragIndexEntry(DefragmentContextImpl context) 248 { 249 throw new NotImplementedException(); 250 } 251 ReadIndexEntry(IContext context, ByteArrayBuffer buffer)252 public virtual object ReadIndexEntry(IContext context, ByteArrayBuffer buffer) 253 { 254 return IdSlotMapping.Read(buffer); 255 } 256 WriteIndexEntry(IContext context, ByteArrayBuffer buffer, object mapping)257 public virtual void WriteIndexEntry(IContext context, ByteArrayBuffer buffer, object 258 mapping) 259 { 260 ((IdSlotMapping)mapping).Write(buffer); 261 } 262 PrepareComparison(IContext context, object sourceMapping )263 public virtual IPreparedComparison PrepareComparison(IContext context, object sourceMapping 264 ) 265 { 266 return new _IPreparedComparison_190(sourceMapping); 267 } 268 269 private sealed class _IPreparedComparison_190 : IPreparedComparison 270 { _IPreparedComparison_190(object sourceMapping)271 public _IPreparedComparison_190(object sourceMapping) 272 { 273 this.sourceMapping = sourceMapping; 274 } 275 CompareTo(object targetMapping)276 public int CompareTo(object targetMapping) 277 { 278 return ((IdSlotMapping)sourceMapping)._id == ((IdSlotMapping)targetMapping)._id ? 279 0 : (((IdSlotMapping)sourceMapping)._id < ((IdSlotMapping)targetMapping)._id ? - 280 1 : 1); 281 } 282 283 private readonly object sourceMapping; 284 } 285 LinkLength()286 public int LinkLength() 287 { 288 return Const4.IntLength * 3; 289 } 290 } 291 FreespaceIdSystem()292 public virtual ITransactionalIdSystem FreespaceIdSystem() 293 { 294 return _transactionalIdSystem; 295 } 296 ChildId()297 public virtual int ChildId() 298 { 299 return _persistentState.Array()[ChildIdIndex]; 300 } 301 ChildId(int id)302 public virtual void ChildId(int id) 303 { 304 _persistentState.Array()[ChildIdIndex] = id; 305 _persistentState.SetStateDirty(); 306 } 307 TraverseIds(IVisitor4 visitor)308 public virtual void TraverseIds(IVisitor4 visitor) 309 { 310 _bTree.TraverseKeys(_container.SystemTransaction(), visitor); 311 } 312 } 313 } 314