1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
|
#ifndef _QmfAgent_
#define _QmfAgent_
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include "qmf/QmfImportExport.h"
#include "qmf/Notifiable.h"
#include "qpid/sys/Time.h"
#include "qpid/messaging/Connection.h"
#include "qpid/messaging/Variant.h"
#include <string>
namespace qmf {
class AgentImpl;
class ObjectId;
class AgentObject;
class Event;
class SchemaClass;
class Query;
/**
* AgentHandler is used by agents that select the internalStore=false option (see Agent
* constructor) or by agents that wish to provide access control for queries and methods.
*
* \ingroup qmfapi
*/
class AgentHandler {
QMF_EXTERN virtual ~AgentHandler();
/**
* allowQuery is called before a query operation is executed. If true is returned
* by this function, the query will proceed. If false is returned, the query will
* be forbidden.
*
* @param q The query being requested.
* @param userId The authenticated identity of the user requesting the query.
*/
virtual bool allowQuery(const Query& q, const std::string& userId);
/**
* allowMethod is called before a method call is executed. If true is returned
* by this function, the method call will proceed. If false is returned, the method
* call will be forbidden.
*
* @param name The name of the method being called.
* @param args A value object (of type "map") that contains both input and output arguments.
* @param oid The objectId that identifies the instance of the object being called.
* @param cls The Schema describing the object being called.
* @param userId The authenticated identity of the requesting user.
*/
virtual bool allowMethod(const std::string& name,
const qpid::messaging::Variant::Map& args,
const ObjectId& oid,
const SchemaClass& cls,
const std::string& userId);
/**
* query is called when the agent receives a query request. The handler must invoke
* Agent::queryResponse zero or more times (using the supplied context) followed by
* a single invocation of Agent::queryComplete. These calls do not need to be made
* synchronously in the context of this function. They may occur before or after this
* function returns.
*
* This function will only be invoked if internalStore=false in the Agent's constructor.
*
* @param context A context value to use in resulting calls to queryResponse and quertComplete.
* @param q The query requested by the console.
* @param userId the authenticated identity of the user requesting the query.
*/
virtual void query(uint32_t context, const Query& q, const std::string& userId);
/**
* syncStart is called when a console requests a standing query. This function must
* behave exactly like AgentHandler::query (i.e. send zero or more responses followed
* by a queryComplete) except it then remembers the context and the query and makes
* subsequent queryResponse calls whenever appropriate according the the query.
*
* The standing query shall stay in effect until syncStop is called with the same context
* value or until a specified period of time elapses without receiving a syncTouch for the
* context.
*
* This function will only be invoked if internalStore=false in the Agent's constructor.
*
* @param context A context value to use in resulting calls to queryResponse and queryComplete.
* @param q The query requested by the console.
* @param userId the authenticated identity of the user requesting the query.
*/
virtual void syncStart(uint32_t context, const Query& q, const std::string& userId);
/**
* syncTouch is called when the console that requested a standing query refreshes its
* interest in the query. The console must periodically "touch" a standing query to keep
* it alive. This prevents standing queries from accumulating when the console disconnects
* before it can stop the query.
*
* This function will only be invoked if internalStore=false in the Agent's constructor.
*
* @param context The context supplied in a previous call to syncStart.
* @param userId The authenticated identity of the requesting user.
*/
virtual void syncTouch(uint32_t context, const std::string& userId);
/**
* syncStop is called when the console that requested a standing query no longer wishes to
* receive data associated with that query. The application shall stop processing this
* query and shall remove its record of the context value.
*
* This function will only be invoked if internalStore=false in the Agent's constructor.
*
* @param context The context supplied in a previous call to syncStart.
* @param userId The authenticated identity of the requesting user.
*/
virtual void syncStop(uint32_t context, const std::string& userId);
/**
* methodCall is called when a console invokes a method on a QMF object. The application
* must call Agent::methodResponse once in response to this function. The response does
* not need to be called synchronously in the context of this function. It may be called
* before or after this function returns.
*
* This function will only be invoked if internalStore=false in the Agent's constructor.
*
* @param context A context value to use in resulting call to methodResponse.
* @param name The name of the method being called.
* @param args A value object (of type "map") that contains both input and output arguments.
* @param oid The objectId that identifies the instance of the object being called.
* @param cls The Schema describing the object being called.
* @param userId The authenticated identity of the requesting user.
*/
virtual void methodCall(uint32_t context, const std::string& name, qpid::messaging::Variant::Map& args,
const ObjectId& oid, const SchemaClass& cls, const std::string& userId);
};
/**
* The Agent class is the QMF Agent portal. It should be instantiated once and associated with a
* Connection (setConnection) to connect an agent to the QMF infrastructure.
*
* \ingroup qmfapi
*/
class Agent {
public:
/**
* Create an instance of the Agent class.
*
* @param vendor A string identifying the vendor of the agent application.
* This should follow the reverse-domain-name form (i.e. org.apache).
*
* @param product A string identifying the product provided by the vendor.
*
* @param instance A string that uniquely identifies this instance of the agent.
* If zero, the agent will generate a guid for the instance string.
*
* @param domain A string that defines the QMF domain that this agent should join.
* If zero, the agent will join the default QMF domain.
*
* @param internalStore If true, objects shall be tracked internally by the agent.
* If false, the user of the agent must track the objects.
* If the agent is tracking the objects, queries and syncs are handled by
* the agent. The only involvement the user has is to optionally authorize
* individual operations. If the user is tracking the objects, the user code
* must implement queries and syncs (standing queries).
*
* @param handler A pointer to a class that implements the AgentHandler interface.
* This must be supplied if any of the following conditions are true:
* - The agent model contains methods
* - The user wishes to individually authorize query and sync operations.
* - internalStore = false
*
* @param notifiable A pointer to a class that implements the Notifiable interface.
* This argument is optional (may be supplied as 0). If it is not supplied,
* notification callbacks will not be invoked.
*/
QMF_EXTERN Agent(const std::string& vendor, const std::string& product, const std::string& instance="",
const std::string& domain="", bool internalStore=true,
AgentHandler* handler=0, Notifiable* notifiable=0);
/**
* Destroy an instance of the Agent class.
*/
QMF_EXTERN ~Agent();
/**
* Set an attribute for the agent. Attributes are visible to consoles and can be used to find
* agents.
*
* @param name Name of the attribute to be set (or overwritten)
*
* @param value Value (of any variant type) of the attribute
*/
QMF_EXTERN void setAttribute(const std::string& name, const qpid::messaging::Variant& value);
/**
* Set the persistent store file. This file, if specified, is used to store state information
* about the Agent. For example, if object-ids must be persistent across restarts of the Agent
* program, this file path must be supplied.
*
* @param path Full path to a file that is both writable and readable by the Agent program.
*/
QMF_EXTERN void setStoreDir(const std::string& path);
/**
* Provide a connection (to a Qpid broker) over which the agent can communicate.
*
* @param conn Pointer to a Connection object.
*/
QMF_EXTERN void setConnection(qpid::messaging::Connection& conn);
/**
* Register a class schema (object or event) with the agent. The agent must have a registered
* schema for an object class or an event class before it can handle objects or events of that
* class.
*
* @param cls Pointer to the schema structure describing the class.
*/
QMF_EXTERN void registerClass(SchemaClass* cls);
/**
* Invoke the handler (if supplied in the constructor) with events stored in the Agent's work
* queue. This function call is a way of supplying the Agent with a thread on which to run the
* application's handler (the Agent will never invoke the handler on one of its internal threads).
*
* @param limit The maximum number of handler callbacks to invoke during this call. Zero means
* there will be no limit on the number of invocations.
*
* @param timeout The time this call will block if there are no handler events to process.
*
* @return The number of handler events processed. If the timeout expired, the return value will
* be zero.
*/
QMF_EXTERN uint32_t invokeHandler(uint32_t limit=0, qpid::sys::Duration timeout=qpid::sys::TIME_INFINITE);
/**
* Add an object to the agent (for internal storage mode only).
*
* @param obj Reference to the object to be managed by the agent.
*
* @param persistent Iff true, the object ID assigned to the object shall indicate persistence
* (i.e. the object ID shall be the same across restarts of the agent program).
*
* @param oid 64-bit value for the oid (if zero, the agent will assign the value).
*
* @param oidLo 32-bit value for the lower 32-bits of the oid.
*
* @param oidHi 32-bit value for the upper 32-bits of the oid.
*/
QMF_EXTERN const ObjectId* addObject(AgentObject& obj, bool persistent=false, uint64_t oid=0);
QMF_EXTERN const ObjectId* addObject(AgentObject& obj, bool persistent, uint32_t oidLo, uint32_t oidHi);
/**
* Raise a QMF event.
*
* @param event Reference to an event object to be raised to the QMF infrastructure.
*/
QMF_EXTERN void raiseEvent(Event& event);
/**
* Provide a response to a query (for external storage mode only).
*
* @param context The context value supplied in the query (via the AgentHandler interface).
*
* @param object A reference to the agent that matched the query criteria.
*/
QMF_EXTERN void queryResponse(uint32_t context, AgentObject& object);
/**
* Indicate that a query (or the initial dump of a sync) is complete (for external storage mode only).
*
* @param context The context value supplied in the query/sync (via the AgentHandler interface).
*/
QMF_EXTERN void queryComplete(uint32_t context);
/**
* Provide the response to a method call.
*
* @param context The context value supplied in the method request (via the AgentHandler interface).
*
* @param args The argument list from the method call. Must include the output arguments (may include
* the input arguments).
*
* @param exception Pointer to an exception value. If status is non-null, the exception value is
* sent to the caller. It is optional (i.e. leave the pointer as 0), or may be
* set to any legal value. A string may be supplied, but an unmanaged object of
* any schema may also be passed.
*/
QMF_EXTERN void methodResponse(uint32_t context,
const qpid::messaging::Variant::Map& args,
const qpid::messaging::Variant& exception=qpid::messaging::Variant());
private:
/**
* Private copy constructor and assignment operator ensure that objects of this class cannot
* be copied.
*/
Agent(const Agent&);
const Agent& operator=(const Agent&);
AgentImpl* impl;
};
}
#endif
|