|
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 |
|
17 #include "dummyactivities.h" |
|
18 #include "dummystates.h" |
|
19 #include "dummymessages.h" |
|
20 |
|
21 |
|
22 #ifdef _DEBUG |
|
23 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module |
|
24 // (if it could happen through user error then you should give it an explicit, documented, category + code) |
|
25 _LIT(KSpecAssert_ElemTestingdmyct, "ElemTestingdmyct"); |
|
26 #endif |
|
27 |
|
28 using namespace Dummy; |
|
29 using namespace DummyActivities; |
|
30 using namespace DummyStates; |
|
31 using namespace Messages; |
|
32 using namespace MeshMachine; |
|
33 |
|
34 |
|
35 //(1) CStopActivity constructs itself over the preallocated space |
|
36 //(2) CStopActivity preallocates space for only one originator |
|
37 // (as in our demo only the last client triggers the activity) |
|
38 class CStopActivity : public MeshMachine::CNodeRetryActivity, protected MeshMachine::APreallocatedOriginators<1> |
|
39 { |
|
40 public: |
|
41 static MeshMachine::CNodeActivityBase* New(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode); |
|
42 |
|
43 protected: |
|
44 CStopActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) |
|
45 : CNodeRetryActivity(aActivitySig, aNode), |
|
46 APreallocatedOriginators<1>(iOriginators) |
|
47 { |
|
48 } |
|
49 |
|
50 virtual void Destroy(); |
|
51 }; |
|
52 |
|
53 //(1) CDestroyActivity constructs itself over the preallocated space |
|
54 //(2) CDestroyActivity preallocates space for only one originator |
|
55 // (as in our demo only the host node itself can trigger it) |
|
56 class CDestroyActivity : public MeshMachine::CNodeActivityBase, protected MeshMachine::APreallocatedOriginators<1> |
|
57 { |
|
58 public: |
|
59 static MeshMachine::CNodeActivityBase* New(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode); |
|
60 |
|
61 protected: |
|
62 CDestroyActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) |
|
63 : CNodeActivityBase(aActivitySig, aNode), |
|
64 APreallocatedOriginators<1>(iOriginators) |
|
65 { |
|
66 } |
|
67 |
|
68 virtual void Destroy(); |
|
69 |
|
70 //States, StateForks & StateTransitions specific to the CDestroyActivity |
|
71 protected: |
|
72 typedef DummyStates::TContext TContext; |
|
73 |
|
74 public: |
|
75 DECLARE_SMELEMENT_HEADER( TMarkForDestruction, MeshMachine::TStateTransition<TContext>, NetStateMachine::MStateTransition, TContext ) |
|
76 virtual void DoL(); |
|
77 DECLARE_SMELEMENT_FOOTER( TMarkForDestruction ) |
|
78 private: |
|
79 /* |
|
80 Private NewL with no implementation to hide the CNodeActivityBase::NewL |
|
81 Creation of preallocated activities doesn't fail and hence a non-leaving ::New should be used instead*/ |
|
82 static MeshMachine::CNodeActivityBase* NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode); |
|
83 }; |
|
84 |
|
85 |
|
86 namespace CoreErrorActivity |
|
87 { |
|
88 typedef DummyStates::TContext TContext; |
|
89 |
|
90 DECLARE_SMELEMENT_HEADER( TAwaitingError, MeshMachine::TState<TContext>, NetStateMachine::MState, TContext ) |
|
91 virtual TBool Accept(); |
|
92 DECLARE_SMELEMENT_FOOTER( TAwaitingError ) |
|
93 |
|
94 DEFINE_SMELEMENT(TAwaitingError, NetStateMachine::MState, TContext) |
|
95 TBool TAwaitingError::Accept() |
|
96 { |
|
97 if (!iContext.iMessage.IsMessage<TEBase::TError>()) |
|
98 { |
|
99 return EFalse; |
|
100 } |
|
101 |
|
102 #ifdef _DEBUG |
|
103 //Diagnostic panic only. TError message should not be travelling around with KErrNone. |
|
104 //If you see this panic, please send a proper error code. |
|
105 TEBase::TError& errroMessage = message_cast<TEBase::TError>(iContext.iMessage); |
|
106 __ASSERT_DEBUG(errroMessage.iValue != KErrNone, User::Panic(KSpecAssert_ElemTestingdmyct, 1)); |
|
107 #endif |
|
108 |
|
109 return ETrue; |
|
110 } |
|
111 |
|
112 DECLARE_SMELEMENT_HEADER( TProcessError, MeshMachine::TStateTransition<TContext>, NetStateMachine::MStateTransition, TContext ) |
|
113 virtual void DoL(); |
|
114 DECLARE_SMELEMENT_FOOTER( TProcessError ) |
|
115 |
|
116 DEFINE_SMELEMENT(TProcessError, NetStateMachine::MStateTransition, TContext) |
|
117 void TProcessError::DoL() |
|
118 { |
|
119 //Find matching activity, if any |
|
120 CNodeActivityBase* a = iContext.Node().FindAddressedActivity(iContext); |
|
121 |
|
122 //We do not allow any unsolicited errors here |
|
123 __ASSERT_DEBUG(a, User::Panic(KSpecAssert_ElemTestingdmyct, 2)); |
|
124 |
|
125 //We are started based on the fact the the last message iContext.Node()'s received is TError |
|
126 TEBase::TError& errmsg = message_cast<TEBase::TError>(iContext.iMessage); |
|
127 a->SetError(errmsg.iValue); |
|
128 a->SetIdle(); |
|
129 } |
|
130 } |
|
131 |
|
132 |
|
133 // |
|
134 //Activities |
|
135 //For more information about single-tripple activities see MeshMachineFundamentals.doc (par. 5.2) |
|
136 //For more information about parallel activities see MeshMachineFundamentals.doc (par. TBA) |
|
137 |
|
138 namespace CoreErrorActivity |
|
139 { |
|
140 //This activity can not fail. |
|
141 //This activity must complete within a single call stack or it would need to be a paralel one. |
|
142 //This activity is not cancellable as its actions are irreversible. |
|
143 DECLARE_DEFINE_NODEACTIVITY(EActivityError, CoreError, TEBase::TError) |
|
144 NODEACTIVITY_ENTRY(KNoTag, CoreErrorActivity::TProcessError, CoreErrorActivity::TAwaitingError, MeshMachine::TNoTag) |
|
145 NODEACTIVITY_END() |
|
146 } |
|
147 |
|
148 namespace DummyNodeJoinActivity |
|
149 { |
|
150 //This activity does not require the activity object. |
|
151 //This activity must complete within a single call stack or it would need to be a paralel one. |
|
152 //This activity is cancellable. |
|
153 //since every originator wants to be separately added to the client's list. |
|
154 //When adding of the client is not successful, the first transition will post a self destruct |
|
155 //message to invoke the destroy activity. |
|
156 DECLARE_DEFINE_NODEACTIVITY(EActivityClientJoin, DummyNodeJoin, TBindProtocol::TClientJoiningRequest) |
|
157 //TAddClient posts TError to the Client (and TDestroy to the node) if an error occurs. |
|
158 NODEACTIVITY_ENTRY(KNoTag, DummyStates::TCommenceJoinAndAddClientAndPostJoinComplete, DummyStates::TAwaitingClientJoiningRequest, MeshMachine::TNoTag) |
|
159 NODEACTIVITY_END() |
|
160 } |
|
161 |
|
162 namespace DummyNodeLeaveActivity |
|
163 { |
|
164 //This activity can not fail. |
|
165 //This activity must complete within a single call stack or it would need to be a paralel one. |
|
166 //This activity is not cancellable as its actions are irreversible. |
|
167 //This activity does not require the activity object and it does not allocate any memory. |
|
168 //It "offloads" the object destruction to the destroy activity. |
|
169 DECLARE_DEFINE_NODEACTIVITY(EActivityClientLeave, DummyNodeLeave, TEPeer::TLeaveRequest) |
|
170 NODEACTIVITY_ENTRY(KNoTag, DummyStates::TPostLeaveCompleteAndRemoveClientAndPostDestroyIfLast, MeshMachine::TAwaitingClientLeavingRequest, MeshMachine::TNoTag) |
|
171 NODEACTIVITY_END() |
|
172 } |
|
173 |
|
174 namespace DummyNodeStartActivity |
|
175 { |
|
176 //This activity can fail. |
|
177 //This activity is cancellable by its originators. |
|
178 //This activity is synchronised with the DummyNodeStop activity. |
|
179 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(EActivityStart, DummyNodeStart, TStartProtocol::TStart, CNodeRetryActivity::NewL) |
|
180 FIRST_NODEACTIVITY_ENTRY(DummyStates::TAwaitingStart, DummyStates::TNoTagOrStartedOrNoServiceProviderBlockedByStop) |
|
181 //Started ServiceProvider already present |
|
182 LAST_NODEACTIVITY_ENTRY(KStarted, DummyStates::TPostStarted) |
|
183 //No ServiceProvider present |
|
184 NODEACTIVITY_ENTRY(KNoServiceProvider, DummyStates::TCreateServiceProvider, DummyStates::TAwaitingFactoryObjectCreated, MeshMachine::TTag<KNoServiceProvider>) |
|
185 NODEACTIVITY_ENTRY(KNoServiceProvider, DummyStates::TPostClientJoiningRequest, DummyStates::TAwaitingJoinComplete, MeshMachine::TNoTag) |
|
186 //Non-started ServiceProvider already present |
|
187 //TAddServiceProvider will post TLeaveRequest to the Service Provider should an error occur |
|
188 NODEACTIVITY_ENTRY(KNoTag, DummyStates::TAddServiceProviderAndPostStart, DummyStates::TAwaitingStarted, MeshMachine::TNoTag) |
|
189 LAST_NODEACTIVITY_ENTRY(KNoTag, DummyStates::TPostStarted) |
|
190 NODEACTIVITY_END() |
|
191 } |
|
192 |
|
193 namespace DummyNodeStopActivity |
|
194 { |
|
195 //This activity can not fail but needs the activity object (therefore uses preallocated activity slot). |
|
196 //This activity is not cancellable as its actions are irreversible. |
|
197 //This activity is synchronised with the DummyNodeStart activity. |
|
198 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(EActivityStop, DummyNodeStop, TStopProtocol::TStop, CStopActivity::New) |
|
199 FIRST_NODEACTIVITY_ENTRY(DummyStates::TAwaitingStop, DummyStates::TNoTagOrStartedOrNoServiceProviderBlockedByStart) |
|
200 //Started ServiceProvider present |
|
201 NODEACTIVITY_ENTRY(KStarted, DummyStates::TPostStop, DummyStates::TAwaitingStopped, MeshMachine::TNoTag) |
|
202 //ServiceProvider present |
|
203 NODEACTIVITY_ENTRY(KNoTag, DummyStates::TPostClientLeavingRequest, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TTag<KNoServiceProvider>) |
|
204 //No ServiceProvider present |
|
205 LAST_NODEACTIVITY_ENTRY(KNoServiceProvider, DummyStates::TPostStopped) |
|
206 NODEACTIVITY_END() |
|
207 } |
|
208 |
|
209 namespace DummyNodeDestroyActivity |
|
210 { |
|
211 //For our demonstration purpose this activity implements only an internal protocol |
|
212 //(i.e. nodes do not send TDestroy between each other). |
|
213 |
|
214 //This activity is started when: |
|
215 //1) Join request from our only Client fails (plus there are no "outstanding" Clients |
|
216 // who have already taken a handle to this node from the Factory and are about to |
|
217 // send us TClientJoiningRequest), |
|
218 //2) The last Client sends us TLeaveRequest (and there are no outstanding |
|
219 // Clients who have already taken a handle to this node from the Factory). |
|
220 |
|
221 //This activity can not fail but needs the activity object as it will destruct the host node. |
|
222 //Destroying activities destroy their hosts when going out of scope. |
|
223 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(EActivityDestroy, DummyNodeDestroy, TEChild::TDestroy, CDestroyActivity::New) |
|
224 FIRST_NODEACTIVITY_ENTRY(DummyStates::TAwaitingDestroy, MeshMachine::TNoTag) |
|
225 THROUGH_NODEACTIVITY_ENTRY(KNoTag, CDestroyActivity::TMarkForDestruction, DummyStates::TNoTagOrNoServiceProvider) |
|
226 //The next tripple will loop for as long as there are any Service Providers left |
|
227 NODEACTIVITY_ENTRY(KNoTag, DummyStates::TPostClientLeavingRequest, MeshMachine::TAwaitingLeaveComplete, DummyStates::TNoTagBackwardsOrNoServiceProvider) |
|
228 LAST_NODEACTIVITY_ENTRY(KNoServiceProvider, MeshMachine::TDoNothing) |
|
229 NODEACTIVITY_END() |
|
230 } |
|
231 |
|
232 namespace DummyActivities |
|
233 { |
|
234 DEFINE_EXPORT_ACTIVITY_MAP(dummyActivities) |
|
235 //The error activity must be at the bottom of the activitys' map because |
|
236 //it should see the TError message last, after all of the other activities |
|
237 //got their chances to handle it. |
|
238 ACTIVITY_MAP_ENTRY(CoreErrorActivity, CoreError) |
|
239 ACTIVITY_MAP_ENTRY(DummyNodeJoinActivity, DummyNodeJoin) |
|
240 ACTIVITY_MAP_ENTRY(DummyNodeLeaveActivity, DummyNodeLeave) |
|
241 ACTIVITY_MAP_ENTRY(DummyNodeStartActivity, DummyNodeStart) |
|
242 ACTIVITY_MAP_ENTRY(DummyNodeStopActivity, DummyNodeStop) |
|
243 ACTIVITY_MAP_ENTRY(DummyNodeDestroyActivity, DummyNodeDestroy) |
|
244 ACTIVITY_MAP_END() |
|
245 } |
|
246 |
|
247 CNodeActivityBase* CStopActivity::New(const TNodeActivity& aActivitySig, AMMNodeBase& aNode) |
|
248 { |
|
249 TAny* space = BorrowPreallocatedSpace(aNode, sizeof(CStopActivity)); |
|
250 CStopActivity* self = new (space) CStopActivity(aActivitySig, aNode); |
|
251 self->AppendPreallocatedActivity(); //Non-destructing preallocated activity |
|
252 return self; |
|
253 } |
|
254 |
|
255 void CStopActivity::Destroy() |
|
256 { |
|
257 ReturnPreallocatedSpace(this); |
|
258 this->~CStopActivity(); //Run the destructor |
|
259 } |
|
260 |
|
261 |
|
262 CNodeActivityBase* CDestroyActivity::New(const TNodeActivity& aActivitySig, AMMNodeBase& aNode) |
|
263 { |
|
264 TAny* space = BorrowPreallocatedSpace(aNode, sizeof(CDestroyActivity)); |
|
265 CDestroyActivity* self = new (space) CDestroyActivity(aActivitySig, aNode); |
|
266 self->InsertPreallocatedDestroyActivity(); //Destructing preallocated activity |
|
267 return self; |
|
268 } |
|
269 |
|
270 void CDestroyActivity::Destroy() |
|
271 { |
|
272 ReturnPreallocatedSpace(this); |
|
273 this->~CDestroyActivity(); //Run the destructor |
|
274 |
|
275 //Delete the provider. |
|
276 static_cast<CTestNodeBase&>(iNode).DeleteMeNow(); |
|
277 } |
|
278 |
|
279 DEFINE_SMELEMENT(CDestroyActivity::TMarkForDestruction, NetStateMachine::MStateTransition, CDestroyActivity::TContext) |
|
280 void CDestroyActivity::TMarkForDestruction::DoL() |
|
281 { |
|
282 //Mark the node for deletion, so that it's not served by the factory from now on. |
|
283 iContext.Node().MarkMeForDeletion(); |
|
284 } |
|
285 |