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