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.Btree;
7 
8 namespace Db4objects.Db4o.Internal.Btree
9 {
10 	public abstract class BTreeUpdate : BTreePatch
11 	{
12 		protected Db4objects.Db4o.Internal.Btree.BTreeUpdate _next;
13 
BTreeUpdate(Transaction transaction, object obj)14 		public BTreeUpdate(Transaction transaction, object obj) : base(transaction, obj)
15 		{
16 		}
17 
HasNext()18 		protected virtual bool HasNext()
19 		{
20 			return _next != null;
21 		}
22 
ForTransaction(Transaction trans)23 		public override BTreePatch ForTransaction(Transaction trans)
24 		{
25 			if (_transaction == trans)
26 			{
27 				return this;
28 			}
29 			if (_next == null)
30 			{
31 				return null;
32 			}
33 			return _next.ForTransaction(trans);
34 		}
35 
RemoveFor(Transaction trans )36 		public virtual Db4objects.Db4o.Internal.Btree.BTreeUpdate RemoveFor(Transaction trans
37 			)
38 		{
39 			if (_transaction == trans)
40 			{
41 				return _next;
42 			}
43 			if (_next == null)
44 			{
45 				return this;
46 			}
47 			return _next.RemoveFor(trans);
48 		}
49 
Append(Db4objects.Db4o.Internal.Btree.BTreeUpdate patch)50 		public virtual void Append(Db4objects.Db4o.Internal.Btree.BTreeUpdate patch)
51 		{
52 			if (_transaction == patch._transaction)
53 			{
54 				// don't allow two patches for the same transaction
55 				throw new ArgumentException();
56 			}
57 			if (!HasNext())
58 			{
59 				_next = patch;
60 			}
61 			else
62 			{
63 				_next.Append(patch);
64 			}
65 		}
66 
ApplyKeyChange(object obj)67 		protected virtual void ApplyKeyChange(object obj)
68 		{
69 			_object = obj;
70 			if (HasNext())
71 			{
72 				_next.ApplyKeyChange(obj);
73 			}
74 		}
75 
Committed(BTree btree)76 		protected abstract void Committed(BTree btree);
77 
Commit(Transaction trans, BTree btree, BTreeNode node)78 		public override object Commit(Transaction trans, BTree btree, BTreeNode node)
79 		{
80 			Db4objects.Db4o.Internal.Btree.BTreeUpdate patch = (Db4objects.Db4o.Internal.Btree.BTreeUpdate
81 				)ForTransaction(trans);
82 			if (patch is BTreeCancelledRemoval)
83 			{
84 				object obj = patch.GetCommittedObject();
85 				ApplyKeyChange(obj);
86 			}
87 			else
88 			{
89 				if (patch is BTreeRemove)
90 				{
91 					RemovedBy(trans, btree, node);
92 					patch.Committed(btree);
93 					return No4.Instance;
94 				}
95 			}
96 			return InternalCommit(trans, btree);
97 		}
98 
InternalCommit(Transaction trans, BTree btree)99 		protected object InternalCommit(Transaction trans, BTree btree)
100 		{
101 			if (_transaction == trans)
102 			{
103 				Committed(btree);
104 				if (HasNext())
105 				{
106 					return _next;
107 				}
108 				return GetCommittedObject();
109 			}
110 			if (HasNext())
111 			{
112 				SetNextIfPatch(_next.InternalCommit(trans, btree));
113 			}
114 			return this;
115 		}
116 
SetNextIfPatch(object newNext)117 		private void SetNextIfPatch(object newNext)
118 		{
119 			if (newNext is Db4objects.Db4o.Internal.Btree.BTreeUpdate)
120 			{
121 				_next = (Db4objects.Db4o.Internal.Btree.BTreeUpdate)newNext;
122 			}
123 			else
124 			{
125 				_next = null;
126 			}
127 		}
128 
GetCommittedObject()129 		protected abstract object GetCommittedObject();
130 
Rollback(Transaction trans, BTree btree)131 		public override object Rollback(Transaction trans, BTree btree)
132 		{
133 			if (_transaction == trans)
134 			{
135 				if (HasNext())
136 				{
137 					return _next;
138 				}
139 				return GetObject();
140 			}
141 			if (HasNext())
142 			{
143 				SetNextIfPatch(_next.Rollback(trans, btree));
144 			}
145 			return this;
146 		}
147 
Key(Transaction trans)148 		public override object Key(Transaction trans)
149 		{
150 			BTreePatch patch = ForTransaction(trans);
151 			if (patch == null)
152 			{
153 				return GetObject();
154 			}
155 			if (patch.IsRemove())
156 			{
157 				return No4.Instance;
158 			}
159 			return patch.GetObject();
160 		}
161 
ReplacePatch(BTreePatch patch, Db4objects.Db4o.Internal.Btree.BTreeUpdate update)162 		public virtual Db4objects.Db4o.Internal.Btree.BTreeUpdate ReplacePatch(BTreePatch
163 			 patch, Db4objects.Db4o.Internal.Btree.BTreeUpdate update)
164 		{
165 			if (patch == this)
166 			{
167 				update._next = _next;
168 				return update;
169 			}
170 			if (_next == null)
171 			{
172 				throw new InvalidOperationException();
173 			}
174 			_next = _next.ReplacePatch(patch, update);
175 			return this;
176 		}
177 
RemovedBy(Transaction trans, BTree btree, BTreeNode node)178 		public virtual void RemovedBy(Transaction trans, BTree btree, BTreeNode node)
179 		{
180 			if (trans != _transaction)
181 			{
182 				AdjustSizeOnRemovalByOtherTransaction(btree, node);
183 			}
184 			if (HasNext())
185 			{
186 				_next.RemovedBy(trans, btree, node);
187 			}
188 		}
189 
AdjustSizeOnRemovalByOtherTransaction(BTree btree, BTreeNode node)190 		protected abstract void AdjustSizeOnRemovalByOtherTransaction(BTree btree, BTreeNode
191 			 node);
192 
SizeDiff(Transaction trans)193 		public override int SizeDiff(Transaction trans)
194 		{
195 			Db4objects.Db4o.Internal.Btree.BTreeUpdate patchForTransaction = (Db4objects.Db4o.Internal.Btree.BTreeUpdate
196 				)ForTransaction(trans);
197 			if (patchForTransaction == null)
198 			{
199 				return 1;
200 			}
201 			return patchForTransaction.SizeDiff();
202 		}
203 
SizeDiff()204 		protected abstract int SizeDiff();
205 	}
206 }
207