1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
8 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
13 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
18 **
19 ** See the Apache 2 License for the specific language governing permissions
20 ** and limitations under the License.
21 **
22 mike 1.1 **==============================================================================
23 */
24
25 #include "client.h"
26 #include <base/packing.h>
27 #include <protocol/protocol.h>
28 #include <base/time.h>
29 #include <base/paths.h>
30 #include "thread.h"
31
32 #define TRACE printf("TRACE: %s(%u)\n", __FILE__, __LINE__)
33
34 #if 0
35 # define D(X) X
36 #else
37 # define D(X) /* empty */
38 #endif
39
40 MI_BEGIN_NAMESPACE
41
42 //==============================================================================
43 mike 1.1 //
44 // Local definitions.
45 //
46 //==============================================================================
47
48 Uint64 _NextMsgID()
49 {
50 static Mutex mutex;
51 mutex.Lock();
52 static Uint64 _msgID = 10000;
53 Uint64 x = _msgID++;
54 mutex.Unlock();
55
56 return x;
57 }
58
59 static char* _StringToStr(const String& str)
60 {
61 Uint32 n = str.GetSize();
62 char* r = new char[n + 1];
63
64 mike 1.1 if (!r)
65 return NULL;
66
67 for (Uint32 i = 0; i < n; i++)
68 {
69 r[i] = char(str[i]);
70 }
71
72 r[n] = '\0';
73
74 return r;
75 }
76
77 //==============================================================================
78 //
79 // class EnvelopeHandler
80 //
81 //==============================================================================
82
83 class EnvelopeHandler : public Handler
84 {
85 mike 1.1 public:
86
87 EnvelopeHandler(Handler* handler) : m_handler(handler)
88 {
89 }
90
91 virtual void HandleConnect()
92 {
93 if (m_handler)
94 m_handler->HandleConnect();
95 }
96
97 virtual void HandleConnectFailed()
98 {
99 if (m_handler)
100 m_handler->HandleConnectFailed();
101 }
102
103 virtual void HandleDisconnect()
104 {
105 if (m_handler)
106 mike 1.1 m_handler->HandleDisconnect();
107 }
108
109 virtual void HandleNoOp(Uint64 msgID)
110 {
111 if (m_handler)
112 m_handler->HandleNoOp(msgID);
113 }
114
115 virtual void HandleInstance(Uint64 msgID, const DInstance& instance)
116 {
117 if (m_handler)
118 m_handler->HandleInstance(msgID, instance);
119 }
120
121 virtual void HandleResult(Uint64 msgID, MI_Result result)
122 {
123 if (m_handler)
124 m_handler->HandleResult(msgID, result);
125 }
126
127 mike 1.1 private:
128 Handler* m_handler;
129 };
130
131 //==============================================================================
132 //
133 // class NoOpHandler
134 //
135 //==============================================================================
136
137 class NoOpHandler : public EnvelopeHandler
138 {
139 public:
140
141 enum State { START, DONE, FAILED };
142
143 NoOpHandler(Handler* handler, Uint64 msgID) :
144 EnvelopeHandler(handler), m_state(START), m_msgID(msgID)
145 {
146 }
147
148 mike 1.1 virtual void HandleNoOp(Uint64 msgID)
149 {
150 if (msgID != m_msgID)
151 {
152 EnvelopeHandler::HandleNoOp(msgID);
153 return;
154 }
155
156 if (m_state != START)
157 {
158 m_state = FAILED;
159 return;
160 }
161
162 m_state = DONE;
163 }
164
165 State m_state;
166 Uint64 m_msgID;
167 };
168
169 mike 1.1 //==============================================================================
170 //
171 // class ResultHandler
172 //
173 //==============================================================================
174
175 class ResultHandler : public EnvelopeHandler
176 {
177 public:
178
179 enum State { START, DONE, FAILED };
180
181 ResultHandler(Handler* handler, Uint64 msgID) :
182 EnvelopeHandler(handler),
183 m_state(START),
184 m_msgID(msgID),
185 m_result(MI_RESULT_OK)
186 {
187 }
188
189 virtual void HandleResult(Uint64 msgID, Result result)
190 mike 1.1 {
191 if (msgID != m_msgID)
192 {
193 EnvelopeHandler::HandleResult(msgID, result);
194 return;
195 }
196
197 if (m_state != START)
198 {
199 m_state = FAILED;
200 return;
201 }
202
203 m_result = result;
204 m_state = DONE;
205 }
206
207 State m_state;
208 Uint64 m_msgID;
209 Result m_result;
210 };
211 mike 1.1
212 //==============================================================================
213 //
214 // class InstanceHandler
215 //
216 //==============================================================================
217
218 class InstanceHandler : public EnvelopeHandler
219 {
220 public:
221
222 enum State { INSTANCE, RESULT, DONE, FAILED };
223
224 InstanceHandler(
225 Handler* handler,
226 Uint64 msgID,
227 DInstance& instance)
228 :
229 EnvelopeHandler(handler),
230 m_state(INSTANCE),
231 m_msgID(msgID),
232 mike 1.1 m_instance(instance),
233 m_result(MI_RESULT_OK)
234 {
235 }
236
237 virtual void HandleInstance(Uint64 msgID, const DInstance& instance)
238 {
239 if (msgID != m_msgID)
240 {
241 EnvelopeHandler::HandleInstance(msgID, instance);
242 return;
243 }
244
245 if (m_state != INSTANCE)
246 {
247 m_state = FAILED;
248 return;
249 }
250
251 m_instance = instance;
252 m_state = RESULT;
253 mike 1.1 }
254
255 virtual void HandleResult(Uint64 msgID, Result result)
256 {
257 if (msgID != m_msgID)
258 {
259 EnvelopeHandler::HandleResult(msgID, result);
260 return;
261 }
262
263 if (m_state != INSTANCE && m_state != RESULT)
264 {
265 m_state = FAILED;
266 return;
267 }
268
269 m_result = result;
270 m_state = DONE;
271 }
272
273 State m_state;
274 mike 1.1 Uint64 m_msgID;
275 DInstance& m_instance;
276 Result m_result;
277 };
278
279 //==============================================================================
280 //
281 // class InstancesHandler
282 //
283 //==============================================================================
284
285 class InstancesHandler : public EnvelopeHandler
286 {
287 public:
288
289 enum State { INSTANCES, RESULT, DONE, FAILED };
290
291 InstancesHandler(
292 Handler* handler,
293 Uint64 msgID,
294 Array<DInstance>& instances)
295 mike 1.1 :
296 EnvelopeHandler(handler),
297 m_state(INSTANCES),
298 m_msgID(msgID),
299 m_instances(instances),
300 m_result(MI_RESULT_OK)
301 {
302 }
303
304 virtual void HandleInstance(Uint64 msgID, const DInstance& instance)
305 {
306 if (msgID != m_msgID)
307 {
308 EnvelopeHandler::HandleInstance(msgID, instance);
309 return;
310 }
311
312 if (m_state != INSTANCES)
313 {
314 m_state = FAILED;
315 return;
316 mike 1.1 }
317
318 m_instances.PushBack(instance);
319 }
320
321 virtual void HandleResult(Uint64 msgID, Result result)
322 {
323 if (msgID != m_msgID)
324 {
325 EnvelopeHandler::HandleResult(msgID, result);
326 return;
327 }
328
329 if (m_state != INSTANCES)
330 {
331 m_state = FAILED;
332 return;
333 }
334
335 m_result = result;
336 m_state = DONE;
337 mike 1.1 }
338
339 State m_state;
340 Uint64 m_msgID;
341 Array<DInstance>& m_instances;
342 Result m_result;
343 };
344
345 //==============================================================================
346 //
347 // class ClientRep
348 //
349 //==============================================================================
350
351 class ClientRep
352 {
353 public:
354 enum ConnectState
355 {
356 CONNECTSTATE_PENDING,
357 CONNECTSTATE_FAILED,
358 mike 1.1 CONNECTSTATE_CONNECTED,
359 CONNECTSTATE_DISCONNECTED
360 };
361
362 Protocol* protocol;
363 Handler* handler;
364 ConnectState connectState;
365
366 static void EventCallback(
367 Protocol* protocol,
368 ProtocolEvent event,
369 void* data);
370
371 static MI_Boolean MessageCallback(
372 Protocol* protocol,
373 Message* msg,
374 void* data);
375
376 bool NoOpAsync(
377 Uint64 msgID);
378
379 mike 1.1 bool GetInstanceAsync(
380 const String& nameSpace,
381 const DInstance& instanceName,
382 Uint64 msgID);
383
384 bool CreateInstanceAsync(
385 const String& nameSpace,
386 const DInstance& instance,
387 Uint64 msgID);
388
389 bool ModifyInstanceAsync(
390 const String& nameSpace,
391 const DInstance& instance,
392 Uint64 msgID);
393
394 bool DeleteInstanceAsync(
395 const String& nameSpace,
396 const DInstance& instanceName,
397 Uint64 msgID);
398
399 bool EnumerateInstancesAsync(
400 mike 1.1 const String& nameSpace,
401 const String& className,
402 bool deepInheritance,
403 const String& queryLanguage,
404 const String& queryExpression,
405 Uint64 msgID);
406
407 bool InvokeAsync(
408 const String& nameSpace,
409 const DInstance& instanceName,
410 const String& methodName,
411 const DInstance& inParameters,
412 DInstance& outParameters,
413 Uint64 msgID);
414
415 bool AssociatorInstancesAsync(
416 const String& nameSpace,
417 const DInstance& instanceName,
418 const String& assocClass,
419 const String& resultClass,
420 const String& role,
421 mike 1.1 const String& resultRole,
422 Uint64& msgID);
423
424 bool ReferenceInstancesAsync(
425 const String& nameSpace,
426 const DInstance& instanceName,
427 const String& assocClass,
428 const String& role,
429 Uint64& msgID);
430 };
431
432 void ClientRep::EventCallback(
433 Protocol* protocol,
434 ProtocolEvent event,
435 void* data)
436 {
437 ClientRep* clientRep = (ClientRep*)data;
438 Handler* handler = clientRep->handler;
439
440 D( printf("==== ClientRep::EventCallback()\n"); )
441
442 mike 1.1
443 if (event == PROTOCOLEVENT_CONNECT)
444 {
445 D( printf("==== EventCallback() PROTOCOLEVENT_CONNECT\n"); )
446 clientRep->connectState = ClientRep::CONNECTSTATE_CONNECTED;
447 if (handler)
448 handler->HandleConnect();
449 return;
450 }
451
452 if (event == PROTOCOLEVENT_CONNECT_FAILED)
453 {
454 D( printf("==== EventCallback() PROTOCOLEVENT_CONNECT_FAILED\n"); )
455 if (handler)
456 handler->HandleConnectFailed();
457 clientRep->connectState = ClientRep::CONNECTSTATE_FAILED;
458 return;
459 }
460
461 if (event == PROTOCOLEVENT_DISCONNECT)
462 {
463 mike 1.1 D( printf("==== EventCallback() PROTOCOLEVENT_DISCONNECT\n"); )
464 if (handler)
465 handler->HandleDisconnect();
466 clientRep->connectState = ClientRep::CONNECTSTATE_DISCONNECTED;
467 return;
468 }
469 }
470
471 MI_Boolean ClientRep::MessageCallback(
472 Protocol* protocol,
473 Message* msg,
474 void* data)
475 {
476 ClientRep* clientRep = (ClientRep*)data;
477 Handler* handler = clientRep->handler;
478
479 DEBUG_ASSERT(msg != 0);
480
481 switch (msg->tag)
482 {
483 case NoOpRspTag:
484 mike 1.1 {
485 D( printf("ClientRep::MessageCallback(): NoOpRspTag\n"); )
486 NoOpRsp* rsp = (NoOpRsp*)msg;
487 MI_UNUSED(rsp);
488 if (handler)
489 handler->HandleNoOp(rsp->base.msgID);
490 break;
491 }
492 case PostInstanceMsgTag:
493 {
494 D( printf("ClientRep::MessageCallback(): PostInstanceMsgTag\n"); )
495 PostInstanceMsg* rsp = (PostInstanceMsg*)msg;
496
497 if (rsp->instance)
498 {
499 DInstance di(rsp->instance, DInstance::CLONE);
500 if (handler)
501 handler->HandleInstance(rsp->base.msgID, di);
502 }
503
504 break;
505 mike 1.1 }
506 case SubscribeResTag:
507 {
508 D( printf("ClientRep::MessageCallback(): SubscribeResTag\n"); )
509 SubscribeRes* rsp = (SubscribeRes*)msg;
510 MI_UNUSED(rsp);
511 break;
512 }
513 case PostResultMsgTag:
514 {
515 D( printf("ClientRep::MessageCallback(): PostResultMsgTag\n"); )
516 PostResultMsg* rsp = (PostResultMsg*)msg;
517 if (handler)
518 handler->HandleResult(rsp->base.msgID, rsp->result);
519 break;
520 }
521 default:
522 {
523 D( printf("ClientRep::MessageCallback(): default\n"); )
524 break;
525 }
526 mike 1.1 }
527 return MI_TRUE;
528 }
529
530 bool ClientRep::NoOpAsync(
531 Uint64 msgID)
532 {
533 NoOpReq* req = 0;
534 bool result = true;
535
536 // Fail if not connected:
537 if (!protocol)
538 {
539 result = false;
540 goto done;
541 }
542
543 // Create request message:
544 {
545 req = NoOpReq_New(msgID);
546
547 mike 1.1 if (!req)
548 {
549 result = false;
550 goto done;
551 }
552 }
553
554 // Send the message:
555 {
556 Result r = Protocol_Send(protocol, &req->base);
557
558 if (r != MI_RESULT_OK)
559 {
560 result = false;
561 goto done;
562 }
563 }
564
565 done:
566
567 if (req)
568 mike 1.1 NoOpReq_Release(req);
569
570 return result;
571 }
572
573 bool ClientRep::GetInstanceAsync(
574 const String& nameSpace,
575 const DInstance& instanceName,
576 Uint64 msgID)
577 {
578 GetInstanceReq* req = 0;
579 bool result = true;
580
581 // Fail if not connected.
582 if (!protocol)
583 {
584 result = false;
585 goto done;
586 }
587
588 // Create the request message:
589 mike 1.1 {
590 req = GetInstanceReq_New(msgID, BinaryProtocolFlag);
591
592 if (!req)
593 {
594 result = false;
595 goto done;
596 }
597 }
598
599 // Set nameSpace:
600 req->nameSpace = Batch_Zdup(req->base.batch, nameSpace.Str());
601
602 // Pack the instance name into the message's batch.
603 {
604 Result r = InstanceToBatch(
605 instanceName.m_self,
606 NULL,
607 NULL,
608 req->base.batch,
609 &req->packedInstanceNamePtr,
610 mike 1.1 &req->packedInstanceNameSize);
611
612 if (r != MI_RESULT_OK)
613 {
614 result = false;
615 goto done;
616 }
617 }
618
619 // Send the messages:
620 {
621 Result r = Protocol_Send(protocol, &req->base);
622
623 if (r != MI_RESULT_OK)
624 {
625 result = false;
626 goto done;
627 }
628 }
629
630 done:
631 mike 1.1 if (req)
632 GetInstanceReq_Release(req);
633
634 return result;
635 }
636
637 bool ClientRep::CreateInstanceAsync(
638 const String& nameSpace,
639 const DInstance& instance,
640 Uint64 msgID)
641 {
642 CreateInstanceReq* req = 0;
643 bool result = true;
644
645 // Fail if not connected.
646 if (!protocol)
647 {
648 result = false;
649 goto done;
650 }
651
652 mike 1.1 // Create the request message:
653 {
654 req = CreateInstanceReq_New(msgID, BinaryProtocolFlag);
655
656 if (!req)
657 {
658 result = false;
659 goto done;
660 }
661 }
662
663 // Set nameSpace:
664 req->nameSpace = Batch_Zdup(req->base.batch, nameSpace.Str());
665
666 // Pack the instance name into the message's batch.
667 {
668 Result r = InstanceToBatch(
669 instance.m_self,
670 NULL,
671 NULL,
672 req->base.batch,
673 mike 1.1 &req->packedInstancePtr,
674 &req->packedInstanceSize);
675
676 if (r != MI_RESULT_OK)
677 {
678 result = false;
679 goto done;
680 }
681 }
682
683 // Send the messages:
684 {
685 Result r = Protocol_Send(protocol, &req->base);
686
687 if (r != MI_RESULT_OK)
688 {
689 result = false;
690 goto done;
691 }
692 }
693
694 mike 1.1 done:
695 if (req)
696 CreateInstanceReq_Release(req);
697
698 return result;
699 }
700
701 bool ClientRep::ModifyInstanceAsync(
702 const String& nameSpace,
703 const DInstance& instance,
704 Uint64 msgID)
705 {
706 ModifyInstanceReq* req = 0;
707 bool result = true;
708
709 // Fail if not connected.
710 if (!protocol)
711 {
712 result = false;
713 goto done;
714 }
715 mike 1.1
716 // Create the request message:
717 {
718 req = ModifyInstanceReq_New(msgID, BinaryProtocolFlag);
719
720 if (!req)
721 {
722 result = false;
723 goto done;
724 }
725 }
726
727 // Set nameSpace:
728 req->nameSpace = Batch_Zdup(req->base.batch, nameSpace.Str());
729
730 // Pack the instance name into the message's batch.
731 {
732 Result r = InstanceToBatch(
733 instance.m_self,
734 NULL,
735 NULL,
736 mike 1.1 req->base.batch,
737 &req->packedInstancePtr,
738 &req->packedInstanceSize);
739
740 if (r != MI_RESULT_OK)
741 {
742 result = false;
743 goto done;
744 }
745 }
746
747 // Send the messages:
748 {
749 Result r = Protocol_Send(protocol, &req->base);
750
751 if (r != MI_RESULT_OK)
752 {
753 result = false;
754 goto done;
755 }
756 }
757 mike 1.1
758 done:
759 if (req)
760 ModifyInstanceReq_Release(req);
761
762 return result;
763 }
764
765 bool ClientRep::DeleteInstanceAsync(
766 const String& nameSpace,
767 const DInstance& instanceName,
768 Uint64 msgID)
769 {
770 DeleteInstanceReq* req = 0;
771 bool result = true;
772
773 // Fail if not connected.
774 if (!protocol)
775 {
776 result = false;
777 goto done;
778 mike 1.1 }
779
780 // Create the request message:
781 {
782 req = DeleteInstanceReq_New(msgID, BinaryProtocolFlag);
783
784 if (!req)
785 {
786 result = false;
787 goto done;
788 }
789 }
790
791 // Set nameSpace:
792 req->nameSpace = Batch_Zdup(req->base.batch, nameSpace.Str());
793
794 // Pack the instance name into the message's batch.
795 {
796 Result r = InstanceToBatch(
797 instanceName.m_self,
798 NULL,
799 mike 1.1 NULL,
800 req->base.batch,
801 &req->packedInstanceNamePtr,
802 &req->packedInstanceNameSize);
803
804 if (r != MI_RESULT_OK)
805 {
806 result = false;
807 goto done;
808 }
809 }
810
811 // Send the messages:
812 {
813 Result r = Protocol_Send(protocol, &req->base);
814
815 if (r != MI_RESULT_OK)
816 {
817 result = false;
818 goto done;
819 }
820 mike 1.1 }
821
822 done:
823 if (req)
824 DeleteInstanceReq_Release(req);
825
826 return result;
827 }
828
829 bool ClientRep::EnumerateInstancesAsync(
830 const String& nameSpace,
831 const String& className,
832 bool deepInheritance,
833 const String& queryLanguage,
834 const String& queryExpression,
835 Uint64 msgID)
836 {
837 EnumerateInstancesReq* req = 0;
838 bool result = true;
839
840 // Fail if not connected.
841 mike 1.1 if (!protocol)
842 {
843 result = false;
844 goto done;
845 }
846
847 // Create the request message:
848 {
849 req = EnumerateInstancesReq_New(msgID, BinaryProtocolFlag);
850
851 if (!req)
852 {
853 result = false;
854 goto done;
855 }
856 }
857
858 // Populate the fields of the request message:
859 {
860 req->nameSpace = Batch_Zdup(req->base.batch, nameSpace.Str());
861 req->className = Batch_Zdup(req->base.batch, className.Str());
862 mike 1.1
863 if (queryLanguage.GetSize())
864 {
865 req->queryLanguage =
866 Batch_Zdup(req->base.batch, queryLanguage.Str());
867 }
868
869 if (queryExpression.GetSize())
870 {
871 req->queryExpression =
872 Batch_Zdup(req->base.batch, queryExpression.Str());
873 }
874
875 req->deepInheritance = deepInheritance;
876 }
877
878 // Send the messages:
879 {
880 Result r = Protocol_Send(protocol, &req->base);
881
882 if (r != MI_RESULT_OK)
883 mike 1.1 {
884 result = false;
885 goto done;
886 }
887 }
888
889 done:
890 if (req)
891 EnumerateInstancesReq_Release(req);
892
893 return result;
894 }
895
896 bool ClientRep::InvokeAsync(
897 const String& nameSpace,
898 const DInstance& instanceName,
899 const String& methodName,
900 const DInstance& inParameters,
901 DInstance& outParameters,
902 Uint64 msgID)
903 {
904 mike 1.1 InvokeReq* req = 0;
905 bool result = true;
906
907 // Fail if not connected.
908 if (!protocol)
909 {
910 result = false;
911 goto done;
912 }
913
914 // Create the request message:
915 {
916 req = InvokeReq_New(msgID, BinaryProtocolFlag);
917
918 if (!req)
919 {
920 result = false;
921 goto done;
922 }
923 }
924
925 mike 1.1 // Set nameSpace:
926 req->nameSpace = Batch_Zdup(req->base.batch, nameSpace.Str());
927
928 // Set className:
929 req->className = Batch_Zdup(req->base.batch,
930 instanceName.GetClassName().Str());
931
932 // Set methodName:
933 req->function = Batch_Zdup(req->base.batch, methodName.Str());
934
935 // Pack instanceName:
936 if (instanceName.Count())
937 {
938 Result r = InstanceToBatch(
939 instanceName.m_self,
940 NULL,
941 NULL,
942 req->base.batch,
943 &req->packedInstancePtr,
944 &req->packedInstanceSize);
945
946 mike 1.1 if (r != MI_RESULT_OK)
947 {
948 result = false;
949 goto done;
950 }
951 }
952
953 // Pack inParameters:
954 {
955 Result r = InstanceToBatch(
956 inParameters.m_self,
957 NULL,
958 NULL,
959 req->base.batch,
960 &req->packedInstanceParamsPtr,
961 &req->packedInstanceParamsSize);
962
963 if (r != MI_RESULT_OK)
964 {
965 result = false;
966 goto done;
967 mike 1.1 }
968 }
969
970 // Send the messages:
971 {
972 Result r = Protocol_Send(protocol, &req->base);
973
974 if (r != MI_RESULT_OK)
975 {
976 result = false;
977 goto done;
978 }
979 }
980
981 done:
982 if (req)
983 InvokeReq_Release(req);
984
985 return result;
986 }
987
988 mike 1.1 bool ClientRep::AssociatorInstancesAsync(
989 const String& nameSpace,
990 const DInstance& instanceName,
991 const String& assocClass,
992 const String& resultClass,
993 const String& role,
994 const String& resultRole,
995 Uint64& msgID)
996 {
997 AssociatorsOfReq* req = 0;
998 bool result = true;
999
1000 // Fail if not connected.
1001 if (!protocol)
1002 {
1003 result = false;
1004 goto done;
1005 }
1006
1007 // Create the request message:
1008 {
1009 mike 1.1 req = AssociatorsOfReq_New(msgID, BinaryProtocolFlag);
1010
1011 if (!req)
1012 {
1013 result = false;
1014 goto done;
1015 }
1016 }
1017
1018 // Set nameSpace:
1019 req->nameSpace = Batch_Zdup(req->base.batch, nameSpace.Str());
1020
1021 // Set assocClass:
1022 if (assocClass.GetSize())
1023 req->assocClass = Batch_Zdup(req->base.batch, assocClass.Str());
1024
1025 // Set resultClass:
1026 if (resultClass.GetSize())
1027 req->resultClass = Batch_Zdup(req->base.batch,resultClass.Str());
1028
1029 // Set role:
1030 mike 1.1 if (role.GetSize())
1031 req->role = Batch_Zdup(req->base.batch, role.Str());
1032
1033 // Set resultRole:
1034 if (resultRole.GetSize())
1035 req->resultRole = Batch_Zdup(req->base.batch, resultRole.Str());
1036
1037 // Pack the instance name into the message's batch.
1038 {
1039 Result r = InstanceToBatch(
1040 instanceName.m_self,
1041 NULL,
1042 NULL,
1043 req->base.batch,
1044 &req->packedInstancePtr,
1045 &req->packedInstanceSize);
1046
1047 if (r != MI_RESULT_OK)
1048 {
1049 result = false;
1050 goto done;
1051 mike 1.1 }
1052 }
1053
1054 // Send the messages:
1055 {
1056 Result r = Protocol_Send(protocol, &req->base);
1057
1058 if (r != MI_RESULT_OK)
1059 {
1060 result = false;
1061 goto done;
1062 }
1063 }
1064
1065 done:
1066 if (req)
1067 {
1068 AssociatorsOfReq_Release(req);
1069 }
1070
1071 return result;
1072 mike 1.1 }
1073
1074 bool ClientRep::ReferenceInstancesAsync(
1075 const String& nameSpace,
1076 const DInstance& instanceName,
1077 const String& assocClass,
1078 const String& role,
1079 Uint64& msgID)
1080 {
1081 ReferencesOfReq* req = 0;
1082 bool result = true;
1083
1084 // Fail if not connected.
1085 if (!protocol)
1086 {
1087 result = false;
1088 goto done;
1089 }
1090
1091 // Create the request message:
1092 {
1093 mike 1.1 req = ReferencesOfReq_New(msgID, BinaryProtocolFlag);
1094
1095 if (!req)
1096 {
1097 result = false;
1098 goto done;
1099 }
1100 }
1101
1102 // Set nameSpace:
1103 req->nameSpace = Batch_Zdup(req->base.batch, nameSpace.Str());
1104
1105 // Set assocClass:
1106 if (assocClass.GetSize())
1107 req->assocClass = Batch_Zdup(req->base.batch, assocClass.Str());
1108
1109 // Set role:
1110 if (role.GetSize())
1111 req->role = Batch_Zdup(req->base.batch, role.Str());
1112
1113 // Pack the instance name into the message's batch.
1114 mike 1.1 {
1115 Result r = InstanceToBatch(
1116 instanceName.m_self,
1117 NULL,
1118 NULL,
1119 req->base.batch,
1120 &req->packedInstancePtr,
1121 &req->packedInstanceSize);
1122
1123 if (r != MI_RESULT_OK)
1124 {
1125 result = false;
1126 goto done;
1127 }
1128 }
1129
1130 // Send the messages:
1131 {
1132 Result r = Protocol_Send(protocol, &req->base);
1133
1134 if (r != MI_RESULT_OK)
1135 mike 1.1 {
1136 result = false;
1137 goto done;
1138 }
1139 }
1140
1141 done:
1142 if (req)
1143 ReferencesOfReq_Release(req);
1144
1145 return result;
1146 }
1147
1148 //==============================================================================
1149 //
1150 // class Client
1151 //
1152 //==============================================================================
1153
1154 Client::Client(Handler* handler)
1155 {
1156 mike 1.1 m_rep = new ClientRep;
1157 m_rep->protocol = 0;
1158 m_rep->connectState = ClientRep::CONNECTSTATE_DISCONNECTED;
1159 m_rep->handler = handler;
1160 }
1161
1162 Client::~Client()
1163 {
1164 Disconnect();
1165 delete m_rep->handler;
1166 delete m_rep;
1167 }
1168
1169 bool Client::ConnectAsync(
1170 const String& locatorIn,
1171 const String& user,
1172 const String& password)
1173 {
1174 Result r;
1175 bool result = true;
1176 String locator = locatorIn;
1177 mike 1.1 char* locator_ = NULL;
1178 char* user_ = NULL;
1179 char* password_ = NULL;
1180
1181 // Fail if already connected:
1182 if (m_rep->protocol)
1183 {
1184 result = false;
1185 goto done;
1186 }
1187
1188 // Locator defaults to SOCKETFILE:
1189 if (locator.GetSize() == 0)
1190 {
1191 #ifdef CONFIG_POSIX
1192 locator = GetPath(ID_SOCKETFILE);
1193 #else
1194 locator = MI_T("localhost:7777");
1195 #endif
1196 }
1197
1198 mike 1.1 // Convert host to 'char' type:
1199 locator_ = _StringToStr(locator);
1200 if (!locator_)
1201 {
1202 goto done;
1203 }
1204 user_ = _StringToStr(user);
1205 if (!user_)
1206 {
1207 goto done;
1208 }
1209 password_ = _StringToStr(password);
1210 if (!password_)
1211 {
1212 goto done;
1213 }
1214
1215 // Set connection state to pending.
1216 m_rep->connectState = ClientRep::CONNECTSTATE_PENDING;
1217
1218 // Establish connection with server:
1219 mike 1.1 {
1220 Protocol* protocol = NULL;
1221 r = Protocol_New_Connector(
1222 &protocol,
1223 NULL,
1224 locator_,
1225 (ProtocolCallback)ClientRep::MessageCallback,
1226 m_rep,
1227 (ProtocolEventCallback)ClientRep::EventCallback,
1228 m_rep,
1229 user_,
1230 password_);
1231
1232 if (r != MI_RESULT_OK)
1233 {
1234 result = false;
1235 goto done;
1236 }
1237
1238 m_rep->protocol = protocol;
1239 }
1240 mike 1.1
1241 done:
1242
1243 if (locator_)
1244 delete [] locator_;
1245 if (user_)
1246 delete [] user_;
1247 if (password_)
1248 delete [] password_;
1249 return result;
1250 }
1251
1252 bool Client::Connect(
1253 const String& locator,
1254 const String& user,
1255 const String& password,
1256 Uint64 timeOutUsec)
1257 {
1258 m_rep->connectState = ClientRep::CONNECTSTATE_PENDING;
1259
1260 if (!ConnectAsync(locator, user, password))
1261 mike 1.1 return false;
1262
1263 Uint64 endTime, now;
1264
1265 if (Time_Now(&now) != MI_RESULT_OK)
1266 return false;
1267
1268 endTime = now + timeOutUsec;
1269
1270 // Wait for connection establishment or timeout.
1271 for (;endTime >= now;)
1272 {
1273 Protocol_Run(m_rep->protocol, 1000);
1274
1275 if (m_rep->connectState != ClientRep::CONNECTSTATE_PENDING)
1276 break;
1277
1278 if (Time_Now(&now) != MI_RESULT_OK)
1279 break;
1280 }
1281
1282 mike 1.1 if (m_rep->connectState != ClientRep::CONNECTSTATE_CONNECTED)
1283 return false;
1284
1285 return true;
1286 }
1287
1288 bool Client::Disconnect()
1289 {
1290 bool result = true;
1291
1292 // Fail if not connected:
1293 if (!m_rep->protocol)
1294 {
1295 result = false;
1296 goto done;
1297 }
1298
1299 // Delete the protocol object.
1300 {
1301 Result r = Protocol_Delete(m_rep->protocol);
1302
1303 mike 1.1 if (r != MI_RESULT_OK)
1304 {
1305 result = false;
1306 goto done;
1307 }
1308
1309 m_rep->protocol = 0;
1310 }
1311
1312 m_rep->connectState = ClientRep::CONNECTSTATE_DISCONNECTED;
1313
1314 done:
1315 return result;
1316 }
1317
1318 bool Client::Connected() const
1319 {
1320 return m_rep->protocol ? true : false;
1321 }
1322
1323 bool Client::Run(Uint64 timeOutUsec)
1324 mike 1.1 {
1325 bool result = true;
1326
1327 // Fail if not connected.
1328 if (!m_rep->protocol)
1329 {
1330 result = false;
1331 goto done;
1332 }
1333
1334 // Process events.
1335 // ATTN: what can this return?
1336 Protocol_Run(m_rep->protocol, timeOutUsec);
1337
1338 done:
1339 return result;
1340 }
1341
1342 bool Client::NoOpAsync(
1343 Uint64& msgID)
1344 {
1345 mike 1.1 msgID = _NextMsgID();
1346 return m_rep->NoOpAsync(msgID);
1347 }
1348
1349 bool Client::GetInstanceAsync(
1350 const String& nameSpace,
1351 const DInstance& instanceName,
1352 Uint64& msgID)
1353 {
1354 msgID = _NextMsgID();
1355 return m_rep->GetInstanceAsync(nameSpace, instanceName, msgID);
1356 }
1357
1358 bool Client::CreateInstanceAsync(
1359 const String& nameSpace,
1360 const DInstance& instance,
1361 Uint64& msgID)
1362 {
1363 msgID = _NextMsgID();
1364 return m_rep->CreateInstanceAsync(nameSpace, instance, msgID);
1365 }
1366 mike 1.1
1367 bool Client::ModifyInstanceAsync(
1368 const String& nameSpace,
1369 const DInstance& instance,
1370 Uint64& msgID)
1371 {
1372 msgID = _NextMsgID();
1373 return m_rep->ModifyInstanceAsync(nameSpace, instance, msgID);
1374 }
1375
1376 bool Client::DeleteInstanceAsync(
1377 const String& nameSpace,
1378 const DInstance& instanceName,
1379 Uint64& msgID)
1380 {
1381 msgID = _NextMsgID();
1382 return m_rep->DeleteInstanceAsync(nameSpace, instanceName, msgID);
1383 }
1384
1385 bool Client::EnumerateInstancesAsync(
1386 const String& nameSpace,
1387 mike 1.1 const String& className,
1388 bool deepInheritance,
1389 const String& queryLanguage,
1390 const String& queryExpression,
1391 Uint64& msgID)
1392 {
1393 msgID = _NextMsgID();
1394 return m_rep->EnumerateInstancesAsync(nameSpace, className,
1395 deepInheritance, queryLanguage, queryExpression, msgID);
1396 }
1397
1398 bool Client::InvokeAsync(
1399 const String& nameSpace,
1400 const DInstance& instanceName,
1401 const String& methodName,
1402 const DInstance& inParameters,
1403 DInstance& outParameters,
1404 Uint64 msgID)
1405 {
1406 msgID = _NextMsgID();
1407 return m_rep->InvokeAsync(nameSpace, instanceName, methodName, inParameters,
1408 mike 1.1 outParameters, msgID);
1409 }
1410
1411 bool Client::AssociatorInstancesAsync(
1412 const String& nameSpace,
1413 const DInstance& instanceName,
1414 const String& assocClass,
1415 const String& resultClass,
1416 const String& role,
1417 const String& resultRole,
1418 Uint64& msgID)
1419 {
1420 msgID = _NextMsgID();
1421 return m_rep->AssociatorInstancesAsync(nameSpace, instanceName, assocClass,
1422 resultClass, role, resultRole, msgID);
1423 }
1424
1425 bool Client::ReferenceInstancesAsync(
1426 const String& nameSpace,
1427 const DInstance& instanceName,
1428 const String& assocClass,
1429 mike 1.1 const String& role,
1430 Uint64& msgID)
1431 {
1432 msgID = _NextMsgID();
1433 return m_rep->ReferenceInstancesAsync(nameSpace, instanceName, assocClass,
1434 role, msgID);
1435 }
1436
1437 bool Client::GetInstance(
1438 const String& nameSpace,
1439 const DInstance& instanceName,
1440 Uint64 timeOutUsec,
1441 DInstance& instance,
1442 Result& result)
1443 {
1444 Handler* oldHandler = m_rep->handler;
1445 Uint64 msgID = _NextMsgID();
1446 InstanceHandler handler(oldHandler, msgID, instance);
1447 m_rep->handler = &handler;
1448 bool flag = true;
1449
1450 mike 1.1 if (!m_rep->GetInstanceAsync(nameSpace, instanceName, msgID))
1451 {
1452 flag = false;
1453 goto done;
1454 }
1455
1456 Uint64 endTime, now;
1457
1458 if (Time_Now(&now) != MI_RESULT_OK)
1459 return false;
1460
1461 endTime = now + timeOutUsec;
1462
1463 for (;endTime >= now;)
1464 {
1465 Protocol_Run(m_rep->protocol, 1000);
1466
1467 if (handler.m_state == InstanceHandler::FAILED ||
1468 handler.m_state == InstanceHandler::DONE)
1469 {
1470 break;
1471 mike 1.1 }
1472
1473 if (Time_Now(&now) != MI_RESULT_OK)
1474 break;
1475 }
1476
1477 if (handler.m_state == InstanceHandler::DONE)
1478 result = handler.m_result;
1479 else
1480 flag = false;
1481
1482 done:
1483 m_rep->handler = oldHandler;
1484 return flag;
1485 }
1486
1487 bool Client::CreateInstance(
1488 const String& nameSpace,
1489 const DInstance& instance,
1490 Uint64 timeOutUsec,
1491 DInstance& instanceName,
1492 mike 1.1 Result& result)
1493 {
1494 Handler* oldHandler = m_rep->handler;
1495 Uint64 msgID = _NextMsgID();
1496 InstanceHandler handler(oldHandler, msgID, instanceName);
1497 m_rep->handler = &handler;
1498 bool flag = true;
1499
1500 if (!m_rep->CreateInstanceAsync(nameSpace, instance, msgID))
1501 {
1502 flag = false;
1503 goto done;
1504 }
1505
1506 Uint64 endTime, now;
1507
1508 if (Time_Now(&now) != MI_RESULT_OK)
1509 return false;
1510
1511 endTime = now + timeOutUsec;
1512
1513 mike 1.1 for (;endTime >= now;)
1514 {
1515 Protocol_Run(m_rep->protocol, 1000);
1516
1517 if (handler.m_state == InstanceHandler::FAILED ||
1518 handler.m_state == InstanceHandler::DONE)
1519 {
1520 break;
1521 }
1522
1523 if (Time_Now(&now) != MI_RESULT_OK)
1524 break;
1525 }
1526
1527 if (handler.m_state == InstanceHandler::DONE)
1528 result = handler.m_result;
1529 else
1530 flag = false;
1531
1532 done:
1533 m_rep->handler = oldHandler;
1534 mike 1.1 return flag;
1535 }
1536
1537 bool Client::ModifyInstance(
1538 const String& nameSpace,
1539 const DInstance& instance,
1540 Uint64 timeOutUsec,
1541 Result& result)
1542 {
1543 Handler* oldHandler = m_rep->handler;
1544 Uint64 msgID = _NextMsgID();
1545 ResultHandler handler(oldHandler, msgID);
1546 m_rep->handler = &handler;
1547 bool flag = true;
1548
1549 if (!m_rep->ModifyInstanceAsync(nameSpace, instance, msgID))
1550 {
1551 flag = false;
1552 goto done;
1553 }
1554
1555 mike 1.1 Uint64 endTime, now;
1556
1557 if (Time_Now(&now) != MI_RESULT_OK)
1558 return false;
1559
1560 endTime = now + timeOutUsec;
1561
1562 for (;endTime >= now;)
1563 {
1564 Protocol_Run(m_rep->protocol, 1000);
1565
1566 if (handler.m_state == ResultHandler::FAILED ||
1567 handler.m_state == ResultHandler::DONE)
1568 {
1569 break;
1570 }
1571
1572 if (Time_Now(&now) != MI_RESULT_OK)
1573 break;
1574 }
1575
1576 mike 1.1 if (handler.m_state == ResultHandler::DONE)
1577 result = handler.m_result;
1578 else
1579 flag = false;
1580
1581 done:
1582 m_rep->handler = oldHandler;
1583 return flag;
1584 }
1585
1586 bool Client::DeleteInstance(
1587 const String& nameSpace,
1588 const DInstance& instanceName,
1589 Uint64 timeOutUsec,
1590 Result& result)
1591 {
1592 Handler* oldHandler = m_rep->handler;
1593 Uint64 msgID = _NextMsgID();
1594 ResultHandler handler(oldHandler, msgID);
1595 m_rep->handler = &handler;
1596 bool flag = true;
1597 mike 1.1
1598 if (!m_rep->DeleteInstanceAsync(nameSpace, instanceName, msgID))
1599 {
1600 flag = false;
1601 goto done;
1602 }
1603
1604 Uint64 endTime, now;
1605
1606 if (Time_Now(&now) != MI_RESULT_OK)
1607 return false;
1608
1609 endTime = now + timeOutUsec;
1610
1611 for (;endTime >= now;)
1612 {
1613 Protocol_Run(m_rep->protocol, 1000);
1614
1615 if (handler.m_state == ResultHandler::FAILED ||
1616 handler.m_state == ResultHandler::DONE)
1617 {
1618 mike 1.1 break;
1619 }
1620
1621 if (Time_Now(&now) != MI_RESULT_OK)
1622 break;
1623 }
1624
1625 if (handler.m_state == ResultHandler::DONE)
1626 result = handler.m_result;
1627 else
1628 flag = false;
1629
1630 done:
1631 m_rep->handler = oldHandler;
1632 return flag;
1633 }
1634
1635 bool Client::NoOp(Uint64 timeOutUsec)
1636 {
1637 Handler* oldHandler = m_rep->handler;
1638 Uint64 msgID = _NextMsgID();
1639 mike 1.1 NoOpHandler handler(oldHandler, msgID);
1640 m_rep->handler = &handler;
1641 bool flag = true;
1642
1643 if (!m_rep->NoOpAsync(msgID))
1644 {
1645 flag = false;
1646 goto done;
1647 }
1648
1649 Uint64 endTime, now;
1650
1651 if (Time_Now(&now) != MI_RESULT_OK)
1652 return false;
1653
1654 endTime = now + timeOutUsec;
1655
1656 for (;endTime >= now;)
1657 {
1658 Protocol_Run(m_rep->protocol, 1000);
1659
1660 mike 1.1 if (handler.m_state == NoOpHandler::FAILED ||
1661 handler.m_state == NoOpHandler::DONE)
1662 {
1663 break;
1664 }
1665
1666 if (Time_Now(&now) != MI_RESULT_OK)
1667 break;
1668 }
1669
1670 if (handler.m_state != NoOpHandler::DONE)
1671 flag = false;
1672
1673 done:
1674 m_rep->handler = oldHandler;
1675 return flag;
1676 }
1677
1678 bool Client::EnumerateInstances(
1679 const String& nameSpace,
1680 const String& className,
1681 mike 1.1 bool deepInheritance,
1682 Uint64 timeOutUsec,
1683 Array<DInstance>& instances,
1684 const String& queryLanguage,
1685 const String& queryExpression,
1686 Result& result)
1687 {
1688 Handler* oldHandler = m_rep->handler;
1689 Uint64 msgID = _NextMsgID();
1690 InstancesHandler handler(oldHandler, msgID, instances);
1691 m_rep->handler = &handler;
1692 bool flag = true;
1693
1694 if (!m_rep->EnumerateInstancesAsync(nameSpace, className, deepInheritance,
1695 queryLanguage, queryExpression, msgID))
1696 {
1697 flag = false;
1698 goto done;
1699 }
1700
1701 Uint64 endTime, now;
1702 mike 1.1
1703 if (Time_Now(&now) != MI_RESULT_OK)
1704 return false;
1705
1706 endTime = now + timeOutUsec;
1707
1708 for (;endTime >= now;)
1709 {
1710 Protocol_Run(m_rep->protocol, 1000);
1711
1712 if (handler.m_state == InstancesHandler::FAILED ||
1713 handler.m_state == InstancesHandler::DONE)
1714 {
1715 break;
1716 }
1717
1718 if (Time_Now(&now) != MI_RESULT_OK)
1719 break;
1720 }
1721
1722 if (handler.m_state == InstancesHandler::DONE)
1723 mike 1.1 result = handler.m_result;
1724 else
1725 flag = false;
1726
1727 done:
1728 m_rep->handler = oldHandler;
1729 return flag;
1730 }
1731
1732 bool Client::Invoke(
1733 const String& nameSpace,
1734 const DInstance& instanceName,
1735 const String& methodName,
1736 const DInstance& inParameters,
1737 Uint64 timeOutUsec,
1738 DInstance& outParameters,
1739 Result& result)
1740 {
1741 Handler* oldHandler = m_rep->handler;
1742 Uint64 msgID = _NextMsgID();
1743 InstanceHandler handler(oldHandler, msgID, outParameters);
1744 mike 1.1 m_rep->handler = &handler;
1745 bool flag = true;
1746
1747 if (!m_rep->InvokeAsync(nameSpace, instanceName, methodName, inParameters,
1748 outParameters, msgID))
1749 {
1750 flag = false;
1751 goto done;
1752 }
1753
1754 Uint64 endTime, now;
1755
1756 if (Time_Now(&now) != MI_RESULT_OK)
1757 return false;
1758
1759 endTime = now + timeOutUsec;
1760
1761 for (;endTime >= now;)
1762 {
1763 Protocol_Run(m_rep->protocol, 1000);
1764
1765 mike 1.1 if (handler.m_state == InstanceHandler::FAILED ||
1766 handler.m_state == InstanceHandler::DONE)
1767 {
1768 break;
1769 }
1770
1771 if (Time_Now(&now) != MI_RESULT_OK)
1772 break;
1773 }
1774
1775 if (handler.m_state == InstanceHandler::DONE)
1776 result = handler.m_result;
1777 else
1778 flag = false;
1779
1780 done:
1781 m_rep->handler = oldHandler;
1782 return flag;
1783 }
1784
1785 bool Client::AssociatorInstances(
1786 mike 1.1 const String& nameSpace,
1787 const DInstance& instanceName,
1788 const String& assocClass,
1789 const String& resultClass,
1790 const String& role,
1791 const String& resultRole,
1792 Uint64 timeOutUsec,
1793 Array<DInstance>& instances,
1794 Result& result)
1795 {
1796 Handler* oldHandler = m_rep->handler;
1797 Uint64 msgID = _NextMsgID();
1798 InstancesHandler handler(oldHandler, msgID, instances);
1799 m_rep->handler = &handler;
1800 bool flag = true;
1801
1802 if (!m_rep->AssociatorInstancesAsync(nameSpace, instanceName, assocClass,
1803 resultClass, role, resultRole, msgID))
1804 {
1805 flag = false;
1806 goto done;
1807 mike 1.1 }
1808
1809 Uint64 endTime, now;
1810
1811 if (Time_Now(&now) != MI_RESULT_OK)
1812 return false;
1813
1814 endTime = now + timeOutUsec;
1815
1816 for (;endTime >= now;)
1817 {
1818 Protocol_Run(m_rep->protocol, 1000);
1819
1820 if (handler.m_state == InstancesHandler::FAILED ||
1821 handler.m_state == InstancesHandler::DONE)
1822 {
1823 break;
1824 }
1825
1826 if (Time_Now(&now) != MI_RESULT_OK)
1827 break;
1828 mike 1.1 }
1829
1830 if (handler.m_state == InstancesHandler::DONE)
1831 result = handler.m_result;
1832 else
1833 flag = false;
1834
1835 done:
1836 m_rep->handler = oldHandler;
1837 return flag;
1838 }
1839
1840 bool Client::ReferenceInstances(
1841 const String& nameSpace,
1842 const DInstance& instanceName,
1843 const String& assocClass,
1844 const String& role,
1845 Uint64 timeOutUsec,
1846 Array<DInstance>& instances,
1847 Result& result)
1848 {
1849 mike 1.1 Handler* oldHandler = m_rep->handler;
1850 Uint64 msgID = _NextMsgID();
1851 InstancesHandler handler(oldHandler, msgID, instances);
1852 m_rep->handler = &handler;
1853 bool flag = true;
1854
1855 if (!m_rep->ReferenceInstancesAsync(nameSpace, instanceName, assocClass,
1856 role, msgID))
1857 {
1858 flag = false;
1859 goto done;
1860 }
1861
1862 Uint64 endTime, now;
1863
1864 if (Time_Now(&now) != MI_RESULT_OK)
1865 return false;
1866
1867 endTime = now + timeOutUsec;
1868
1869 for (;endTime >= now;)
1870 mike 1.1 {
1871 Protocol_Run(m_rep->protocol, 1000);
1872
1873 if (handler.m_state == InstancesHandler::FAILED ||
1874 handler.m_state == InstancesHandler::DONE)
1875 {
1876 break;
1877 }
1878
1879 if (Time_Now(&now) != MI_RESULT_OK)
1880 break;
1881 }
1882
1883 if (handler.m_state == InstancesHandler::DONE)
1884 result = handler.m_result;
1885 else
1886 flag = false;
1887
1888 done:
1889 m_rep->handler = oldHandler;
1890 return flag;
1891 mike 1.1 }
1892
1893 MI_END_NAMESPACE
|