1 /*****************************************************************************/
2 /* Software Testing Automation Framework (STAF) */
3 /* (C) Copyright IBM Corp. 2001, 2004, 2005 */
4 /* */
5 /* This software is licensed under the Eclipse Public License (EPL) V1.0. */
6 /*****************************************************************************/
7
8 #include "STAF.h"
9 #include "STAFProc.h"
10 #include "STAFProcUtil.h"
11 #include "STAFQueueService.h"
12 #include "STAFHandleQueue.h"
13 #include "STAFHandleManager.h"
14 #include "STAFVariablePool.h"
15 #include "STAFUtil.h"
16 // XXX: Remove STAFServiceManager.h if pass in default authenticator via
17 // LocalRequest()
18 #include "STAFServiceManager.h"
19
20 static const STAFString sColon(kUTF8_COLON);
21 static STAFString sHelpMsg;
22
STAFQueueService()23 STAFQueueService::STAFQueueService() : STAFService("QUEUE")
24 {
25 // Assign the help text string for the service
26
27 sHelpMsg = STAFString("*** QUEUE Service Help ***") +
28 *gLineSeparatorPtr + *gLineSeparatorPtr +
29 "QUEUE MESSAGE <Message>" +
30 *gLineSeparatorPtr +
31 " [HANDLE <Handle>] | [NAME <Name>] [PRIORITY <Priority>] [TYPE <Type>]" +
32 *gLineSeparatorPtr + *gLineSeparatorPtr +
33 "GET [PRIORITY <Priority>]... [MACHINE <Endpoint>]... [NAME <Name>]..." +
34 *gLineSeparatorPtr +
35 " [HANDLE <Handle>]... [USER <User>]... [TYPE <Type>]..." +
36 *gLineSeparatorPtr +
37 " [CONTAINS <String>]... [ICONTAINS <String>]... " +
38 *gLineSeparatorPtr +
39 " [FIRST <Number> | ALL]" +
40 *gLineSeparatorPtr +
41 " [WAIT [<Number>[s|m|h|d|w]]]" +
42 *gLineSeparatorPtr + *gLineSeparatorPtr +
43 "PEEK [PRIORITY <Priority>]... [MACHINE <Endpoint>]... [NAME <Name>]..." +
44 *gLineSeparatorPtr +
45 " [HANDLE <Handle>]... [USER <User>]... [TYPE <Type>]..." +
46 *gLineSeparatorPtr +
47 " [CONTAINS <String>]... [ICONTAINS <String>]... " +
48 *gLineSeparatorPtr +
49 " [FIRST <Number> | ALL]" +
50 *gLineSeparatorPtr +
51 " [WAIT [<Number>[s|m|h|d|w]]]" +
52 *gLineSeparatorPtr + *gLineSeparatorPtr +
53 "DELETE [PRIORITY <Priority>]... [MACHINE <Endpoint>]... [NAME <Name>]..." +
54 *gLineSeparatorPtr +
55 " [HANDLE <Handle>]... [USER <User>]... [TYPE <Type>]..." +
56 *gLineSeparatorPtr +
57 " [CONTAINS <String>]... [ICONTAINS <String>]... " +
58 *gLineSeparatorPtr + *gLineSeparatorPtr +
59 "LIST [HANDLE <Handle>]" +
60 *gLineSeparatorPtr + *gLineSeparatorPtr +
61 "HELP";
62
63 // Create the command request parsers
64
65 // queue options
66
67 fQueueParser.addOption("QUEUE", 1,
68 STAFCommandParser::kValueNotAllowed);
69 fQueueParser.addOption("HANDLE", 1,
70 STAFCommandParser::kValueRequired);
71 fQueueParser.addOption("NAME", 1,
72 STAFCommandParser::kValueRequired);
73 fQueueParser.addOption("PRIORITY", 1,
74 STAFCommandParser::kValueRequired);
75 fQueueParser.addOption("MESSAGE", 1,
76 STAFCommandParser::kValueRequired);
77 fQueueParser.addOption("TYPE", 1,
78 STAFCommandParser::kValueRequired);
79
80 // queue option groups
81
82 fQueueParser.addOptionGroup("HANDLE NAME", 0, 1);
83 fQueueParser.addOptionGroup("MESSAGE", 1, 1);
84
85 // get / peek options
86
87 fGetParser.addOption("GET", 1,
88 STAFCommandParser::kValueNotAllowed);
89 fGetParser.addOption("PEEK", 1,
90 STAFCommandParser::kValueNotAllowed);
91 fGetParser.addOption("PRIORITY", 0,
92 STAFCommandParser::kValueRequired);
93 fGetParser.addOption("MACHINE", 0,
94 STAFCommandParser::kValueRequired);
95 fGetParser.addOption("NAME", 0,
96 STAFCommandParser::kValueRequired);
97 fGetParser.addOption("HANDLE", 0,
98 STAFCommandParser::kValueRequired);
99 fGetParser.addOption("USER", 0,
100 STAFCommandParser::kValueRequired);
101 fGetParser.addOption("TYPE", 0,
102 STAFCommandParser::kValueRequired);
103 fGetParser.addOption("CONTAINS", 0,
104 STAFCommandParser::kValueRequired);
105 fGetParser.addOption("ICONTAINS", 0,
106 STAFCommandParser::kValueRequired);
107 fGetParser.addOption("WAIT", 1,
108 STAFCommandParser::kValueAllowed);
109 fGetParser.addOption("FIRST", 1,
110 STAFCommandParser::kValueRequired);
111 fGetParser.addOption("ALL", 1,
112 STAFCommandParser::kValueNotAllowed);
113
114 fGetParser.addOptionGroup("FIRST ALL", 0, 1);
115
116 // delete options
117
118 fDeleteParser.addOption("DELETE", 1,
119 STAFCommandParser::kValueNotAllowed);
120 fDeleteParser.addOption("PRIORITY", 0,
121 STAFCommandParser::kValueRequired);
122 fDeleteParser.addOption("MACHINE", 0,
123 STAFCommandParser::kValueRequired);
124 fDeleteParser.addOption("NAME", 0,
125 STAFCommandParser::kValueRequired);
126 fDeleteParser.addOption("HANDLE", 0,
127 STAFCommandParser::kValueRequired);
128 fDeleteParser.addOption("USER", 0,
129 STAFCommandParser::kValueRequired);
130 fDeleteParser.addOption("TYPE", 0,
131 STAFCommandParser::kValueRequired);
132 fDeleteParser.addOption("CONTAINS", 0,
133 STAFCommandParser::kValueRequired);
134 fDeleteParser.addOption("ICONTAINS", 0,
135 STAFCommandParser::kValueRequired);
136
137 // list options
138
139 fListParser.addOption("LIST", 1,
140 STAFCommandParser::kValueNotAllowed);
141 fListParser.addOption("HANDLE", 1,
142 STAFCommandParser::kValueRequired);
143
144 // Construct map class for an entry in a queue
145
146 fQueueEntryMapClass = STAFMapClassDefinition::create(
147 "STAF/Service/Queue/Entry");
148
149 fQueueEntryMapClass->addKey("priority", "Priority");
150 fQueueEntryMapClass->setKeyProperty("priority", "display-short-name", "P");
151 fQueueEntryMapClass->addKey("timestamp", "Date-Time");
152 fQueueEntryMapClass->addKey("machine", "Machine");
153 fQueueEntryMapClass->addKey("handleName", "Handle Name");
154 fQueueEntryMapClass->setKeyProperty(
155 "handleName", "display-short-name", "Name");
156 fQueueEntryMapClass->addKey("handle", "Handle");
157 fQueueEntryMapClass->setKeyProperty("handle", "display-short-name", "H#");
158 fQueueEntryMapClass->addKey("user", "User");
159 fQueueEntryMapClass->addKey("type", "Type");
160 fQueueEntryMapClass->addKey("message", "Message");
161
162 // Construct map classes for handles with a full queue error
163
164 fQueueFullMapClass = STAFMapClassDefinition::create(
165 "STAF/Service/Queue/FullInfo");
166 fQueueFullMapClass->addKey("handle", "Handle");
167 fQueueFullMapClass->addKey("queueSize", "Queue Size");
168
169 fQueueErrorMapClass = STAFMapClassDefinition::create(
170 "STAF/Service/Queue/Error");
171 fQueueErrorMapClass->addKey("numberQueued", "Number Queued");
172 fQueueErrorMapClass->addKey("fullQueueList", "Handles with Full Queues");
173 }
174
175
~STAFQueueService()176 STAFQueueService::~STAFQueueService()
177 {
178 /* Do Nothing */
179 }
180
181
info(unsigned int) const182 STAFString STAFQueueService::info(unsigned int) const
183 {
184 return name() + ": Internal";
185 }
186
187
acceptRequest(const STAFServiceRequest & requestInfo)188 STAFServiceResult STAFQueueService::acceptRequest(
189 const STAFServiceRequest &requestInfo)
190 {
191 STAFString action = requestInfo.fRequest.subWord(0, 1).lowerCase();
192
193 if (action == "queue") return handleQueue(requestInfo);
194 else if (action == "get") return handleGetPeek(requestInfo, true);
195 else if (action == "peek") return handleGetPeek(requestInfo, false);
196 else if (action == "delete") return handleDelete(requestInfo);
197 else if (action == "list") return handleList(requestInfo);
198 else if (action == "help") return handleHelp(requestInfo);
199 else
200 {
201 STAFString errMsg = STAFString("'") +
202 requestInfo.fRequest.subWord(0, 1) +
203 "' is not a valid command request for the " + name() +
204 " service" + *gLineSeparatorPtr + *gLineSeparatorPtr +
205 sHelpMsg;
206
207 return STAFServiceResult(kSTAFInvalidRequestString, errMsg);
208 }
209 }
210
211
handleQueue(const STAFServiceRequest & requestInfo)212 STAFServiceResult STAFQueueService::handleQueue(
213 const STAFServiceRequest &requestInfo)
214 {
215 // Verify that the requesting machine/user has at least trust level 3
216
217 IVALIDATE_TRUST(3, "QUEUE");
218
219 // Parse the request
220
221 STAFCommandParseResultPtr parsedResult = fQueueParser.parse(
222 requestInfo.fRequest);
223
224 if (parsedResult->rc != kSTAFOk)
225 {
226 return STAFServiceResult(kSTAFInvalidRequestString,
227 parsedResult->errorBuffer, 0);
228 }
229
230 STAFString errorBuffer;
231
232 // HANDLE may only default if the request came from this machine
233
234 if ((parsedResult->optionTimes("HANDLE") == 0) &&
235 (parsedResult->optionTimes("NAME") == 0) &&
236 !requestInfo.fIsLocalRequest)
237 {
238 return STAFServiceResult(kSTAFInvalidRequestString);
239 }
240
241 DEFINE_VAR_POOL_LIST(varPoolList, varPoolListSize, requestInfo);
242 STAFString name;
243 STAFHandle_t theHandle = requestInfo.fHandle;
244 unsigned int priority = 5;
245 STAFString type;
246
247 STAFRC_t rc = RESOLVE_OPTIONAL_STRING_OPTION("NAME", name);
248
249 if (!rc) rc = RESOLVE_OPTIONAL_UINT_OPTION_RANGE(
250 "HANDLE", theHandle, gHandleManagerPtr->getMinHandleNumber(),
251 gHandleManagerPtr->getMaxHandleNumber());
252
253 if (!rc) rc = RESOLVE_OPTIONAL_UINT_OPTION("PRIORITY", priority);
254 if (!rc) rc = RESOLVE_OPTIONAL_STRING_OPTION("TYPE", type);
255
256 if (rc) return STAFServiceResult(rc, errorBuffer);
257
258 // Currently we won't resolve variables in MESSAGE
259
260 STAFHandleQueuePtr handleQueue;
261 STAFString machine = requestInfo.fEndpoint;
262
263 STAFString result;
264
265 STAFHandleQueue::Message message(priority, machine,
266 requestInfo.fAuthenticator,
267 requestInfo.fUserIdentifier,
268 requestInfo.fHandleName,
269 requestInfo.fHandle,
270 parsedResult->optionValue("MESSAGE"),
271 type);
272
273 if (parsedResult->optionTimes("NAME") == 0)
274 {
275 rc = gHandleManagerPtr->handleQueue(theHandle, handleQueue);
276
277 if (rc) return STAFServiceResult(rc);
278
279 STAFMutexSemLock queueLock(handleQueue->fQueueSem);
280
281 if (handleQueue->fQueue.size() >= gMaxQueueSize)
282 {
283 return STAFServiceResult(kSTAFQueueFull,
284 STAFString(handleQueue->fQueue.size()));
285 }
286
287 handleQueue->fQueue.insert(STAFHandleQueue::HandleQueue::value_type(
288 message.priority, message));
289 handleQueue->fNotify->post();
290 }
291 else
292 {
293 std::vector<STAFHandle_t> handles =
294 gHandleManagerPtr->handlesWithName(name);
295
296 std::vector<STAFHandle_t>::iterator iter;
297
298 unsigned int numberQueued = handles.size();
299
300 STAFObjectPtr fullQueueErrorList = STAFObject::createList();
301
302 for (iter = handles.begin(); iter != handles.end(); iter++)
303 {
304 if (gHandleManagerPtr->handleQueue(*iter, handleQueue))
305 --numberQueued;
306 else
307 {
308 STAFMutexSemLock queueLock(handleQueue->fQueueSem);
309
310 if (handleQueue->fQueue.size() >= gMaxQueueSize)
311 {
312 --numberQueued;
313
314 // Add information about the handle's full queue to the
315 // error list
316
317 STAFObjectPtr errorMap = fQueueFullMapClass->createInstance();
318 errorMap->put("handle", STAFString(*iter));
319 errorMap->put("queueSize", handleQueue->fQueue.size());
320 fullQueueErrorList->append(errorMap);
321 }
322 else
323 {
324 handleQueue->fQueue.insert(
325 STAFHandleQueue::HandleQueue::value_type(
326 message.priority, message));
327 handleQueue->fNotify->post();
328 }
329 }
330 }
331
332 if (fullQueueErrorList->size() > 0)
333 {
334 // At least one message was not successfully queued
335
336 // Create a marshalled map containing error information including
337 // the number of handles that the message was successfully queued
338 // to and a list of the handles where the message could not be
339 // queued because the queues were full
340
341 STAFObjectPtr mc = STAFObject::createMarshallingContext();
342 mc->setMapClassDefinition(fQueueErrorMapClass->reference());
343 mc->setMapClassDefinition(fQueueFullMapClass->reference());
344 STAFObjectPtr errorMap = fQueueErrorMapClass->createInstance();
345 errorMap->put("numberQueued", STAFString(numberQueued));
346 errorMap->put("fullQueueList", fullQueueErrorList);
347
348 mc->setRootObject(errorMap);
349
350 return STAFServiceResult(kSTAFQueueFull, mc->marshall());
351 }
352 else if (numberQueued == 0)
353 {
354 // No handles exist with the specified handle name
355
356 return STAFServiceResult(kSTAFHandleDoesNotExist);
357 }
358
359 result = STAFString(numberQueued);
360 }
361
362 return STAFServiceResult(kSTAFOk, result);
363 }
364
365
handleGetPeek(const STAFServiceRequest & requestInfo,bool isGet)366 STAFServiceResult STAFQueueService::handleGetPeek(
367 const STAFServiceRequest &requestInfo, bool isGet)
368 {
369 // Verify that this request came from the local machine
370 // No check of trust is needed since these commands are only valid
371 // with respect to the submitting process' queue so just set
372 // required trust level to 0.
373
374 if (isGet)
375 {
376 IVALIDATE_LOCAL_TRUST(0, "GET");
377 }
378 else
379 {
380 IVALIDATE_LOCAL_TRUST(0, "PEEK");
381 }
382
383 // Parse the request
384
385 STAFCommandParseResultPtr parsedResult = fGetParser.parse(
386 requestInfo.fRequest);
387
388 if (parsedResult->rc != kSTAFOk)
389 {
390 return STAFServiceResult(kSTAFInvalidRequestString,
391 parsedResult->errorBuffer, 0);
392 }
393
394 DEFINE_VAR_POOL_LIST(varPoolList, varPoolListSize, requestInfo);
395 STAFString errorBuffer;
396 STAFHandleQueuePtr handleQueue;
397 STAFRC_t rc = gHandleManagerPtr->handleQueue(requestInfo.fHandle,
398 handleQueue);
399 if (rc) return STAFServiceResult(rc);
400
401 // Check if the ALL or FIRST option was specified
402
403 bool first = false; // Indicates if the FIRST option is specified
404 bool all = false; // Indicates if the ALL option is specified
405 unsigned int firstNum = 0; // Number of queue entries to obtain
406
407 if (parsedResult->optionTimes("ALL") > 0)
408 {
409 all = true;
410 }
411 else if (parsedResult->optionTimes("FIRST") > 0)
412 {
413 rc = RESOLVE_UINT_OPTION_RANGE("FIRST", firstNum, 1, UINT_MAX);
414
415 if (rc) return STAFServiceResult(rc, errorBuffer);
416
417 first = true;
418 }
419 else
420 {
421 // Default to FIRST 1 if neither the ALL or FIRST option is
422 // specified
423
424 firstNum = 1;
425 }
426
427 std::vector<unsigned int> priorityList;
428 std::vector<unsigned int> handleList;
429 std::vector<STAFString> machineList;
430 std::vector<STAFString> nameList;
431 std::vector<STAFString> userList;
432 std::vector<STAFString> typeList;
433 std::vector<STAFString> containsList;
434 std::vector<STAFString> icontainsList;
435
436 unsigned int index = 0;
437 unsigned int optionCount = 0;
438 unsigned int priority = 0;
439
440 for (index = 1, optionCount = parsedResult->optionTimes("PRIORITY");
441 (index <= optionCount) && !rc; ++index)
442 {
443 rc = RESOLVE_INDEXED_UINT_OPTION("PRIORITY", index, priority);
444 if (!rc) priorityList.push_back(priority);
445 }
446
447 STAFHandle_t theHandle = 0;
448
449 for (index = 1, optionCount = parsedResult->optionTimes("HANDLE");
450 (index <= optionCount) && !rc; ++index)
451 {
452 rc = RESOLVE_INDEXED_UINT_OPTION_RANGE(
453 "HANDLE", index, theHandle,
454 gHandleManagerPtr->getMinHandleNumber(),
455 gHandleManagerPtr->getMaxHandleNumber());
456
457 if (!rc) handleList.push_back(theHandle);
458 }
459
460 STAFString machine;
461
462 for (index = 1, optionCount = parsedResult->optionTimes("MACHINE");
463 (index <= optionCount) && !rc; ++index)
464 {
465 rc = RESOLVE_INDEXED_STRING_OPTION("MACHINE", index, machine);
466 if (!rc) machineList.push_back(machine.toLowerCase());
467 }
468
469 STAFString name;
470
471 for (index = 1, optionCount = parsedResult->optionTimes("NAME");
472 (index <= optionCount) && !rc; ++index)
473 {
474 rc = RESOLVE_INDEXED_STRING_OPTION("NAME", index, name);
475 if (!rc) nameList.push_back(name.toLowerCase());
476 }
477
478 STAFString user;
479
480 for (index = 1, optionCount = parsedResult->optionTimes("USER");
481 (index <= optionCount) && !rc; ++index)
482 {
483 rc = RESOLVE_INDEXED_STRING_OPTION("USER", index, user);
484
485 if (!rc)
486 {
487 // Check if authenticator was specified in the user value
488
489 unsigned int sepIndex = user.find(gSpecSeparator);
490
491 if (sepIndex == STAFString::kNPos)
492 {
493 // No authenticator specified
494 // Use lower-cased default authenticator
495 user = gServiceManagerPtr->getDefaultAuthenticator().
496 toLowerCase() + gSpecSeparator + user;
497 }
498 else
499 {
500 // User specified in form of Authenticator://UserIdentifier
501 // Change authenticator to lower-case.
502 user = user.subString(0, sepIndex).toLowerCase() +
503 user.subString(sepIndex);
504 }
505
506 userList.push_back(user);
507 }
508 }
509
510 STAFString type;
511
512 for (index = 1, optionCount = parsedResult->optionTimes("TYPE");
513 (index <= optionCount) && !rc; ++index)
514 {
515 rc = RESOLVE_INDEXED_STRING_OPTION("TYPE", index, type);
516 if (!rc) typeList.push_back(type.toLowerCase());
517 }
518
519 STAFString contains;
520
521 for (index = 1, optionCount = parsedResult->optionTimes("CONTAINS");
522 (index <= optionCount) && !rc; ++index)
523 {
524 rc = RESOLVE_INDEXED_STRING_OPTION("CONTAINS", index, contains);
525 if (!rc) containsList.push_back(contains);
526 }
527
528 STAFString icontains;
529
530 for (index = 1, optionCount = parsedResult->optionTimes("ICONTAINS");
531 (index <= optionCount) && !rc; ++index)
532 {
533 rc = RESOLVE_INDEXED_STRING_OPTION("ICONTAINS", index, icontains);
534 if (!rc) icontainsList.push_back(icontains.toLowerCase());
535 }
536
537 // Set the timeout variable. If no WAIT option is specified, don't wait
538 // for a message to appear on the queue.
539
540 unsigned int timeout = 0;
541
542 if (!rc) rc = RESOLVE_DEFAULT_DURATION_OPTION(
543 "WAIT", timeout, STAF_EVENT_SEM_INDEFINITE_WAIT);
544
545 if (rc) return STAFServiceResult(rc, errorBuffer);
546
547 STAFHandleQueue::Message message;
548 unsigned int doWait = 0;
549 STAFEventSemPtr event;
550
551 if (parsedResult->optionTimes("WAIT") != 0)
552 {
553 STAFMutexSemLock queueLock(handleQueue->fQueueSem);
554
555 event = handleQueue->fNotify;
556 doWait = 1;
557 }
558
559 STAFObjectPtr mc = STAFObject::createMarshallingContext();
560 mc->setMapClassDefinition(fQueueEntryMapClass->reference());
561
562 STAFObjectPtr resultList;
563
564 if (all | first)
565 {
566 // A list of queue elements that match the search criteria will
567 // be returned
568
569 resultList = STAFObject::createList();
570 }
571
572 // The number of elements in the queue that match the search criteria
573 unsigned int numFound = 0;
574
575 STAFTimestamp startTime = STAFTimestamp::now();
576 unsigned int currTimeout = timeout;
577 bool retry = true;
578
579 // We enter into a loop here waiting for one or more queue element(s)
580 // that match the search criteria to become available
581
582 while (retry)
583 {
584 // Create a block so that the lock on the handle's queue is only
585 // held while within this block
586 {
587 // Get a lock on the handle's queue while getting/peeking
588 // messages from it
589
590 STAFMutexSemLock queueLock(handleQueue->fQueueSem);
591
592 bool done = false; // Indicates if done iterating the queue
593
594 // Used if isGet to keep track of the number of entries in the
595 // queue to skip since they have already been processed (to speed
596 // up things if not all queue elements match the criteria
597 unsigned int entriesToSkip = 0;
598
599 while (!done && (all || (numFound < firstNum)))
600 {
601 unsigned int foundIt = 0;
602
603 STAFHandleQueue::HandleQueue::iterator iter;
604 unsigned int i = 0;
605 bool readQueueFromBeginning = true;
606
607 for (iter = handleQueue->fQueue.begin();
608 (iter != handleQueue->fQueue.end()) &&
609 ((isGet && !foundIt) ||
610 (!isGet && (all || (numFound < firstNum)))); ++iter)
611 {
612 if (isGet)
613 {
614 // Skip entries that we already know don't match
615
616 if (readQueueFromBeginning)
617 {
618 if (i < entriesToSkip)
619 {
620 ++i;
621 continue;
622 }
623 else
624 {
625 readQueueFromBeginning = false;
626 entriesToSkip = 0;
627 }
628 }
629 }
630
631 foundIt = 1;
632
633 if (priorityList.size() != 0)
634 {
635 unsigned int checkPriority = iter->second.priority;
636
637 for (foundIt = 0, index = 0;
638 index < priorityList.size(); ++index)
639 {
640 if (priorityList[index] == checkPriority)
641 foundIt = 1;
642 }
643 }
644
645 if (foundIt && (handleList.size() != 0))
646 {
647 STAFHandle_t checkHandle = iter->second.handle;
648
649 for (foundIt = 0, index = 0;
650 index < handleList.size(); ++index)
651 {
652 if (handleList[index] == checkHandle)
653 foundIt = 1;
654 }
655 }
656
657 if (foundIt && (machineList.size() != 0))
658 {
659 STAFString lowerMachine = iter->second.machine.
660 toLowerCase();
661
662 for (foundIt = 0, index = 0;
663 index < machineList.size(); ++index)
664 {
665 // Do a wildcard match
666
667 if (lowerMachine.matchesWildcards(
668 machineList[index]))
669 {
670 foundIt = 1;
671 }
672 }
673 }
674
675 if (foundIt && (nameList.size() != 0))
676 {
677 STAFString lowerName =
678 iter->second.process.toLowerCase();
679
680 for (foundIt = 0, index = 0;
681 index < nameList.size(); ++index)
682 {
683 if (nameList[index] == lowerName)
684 foundIt = 1;
685 }
686 }
687
688 if (foundIt && (userList.size() != 0))
689 {
690 STAFString user =
691 iter->second.authenticator.toLowerCase()+
692 gSpecSeparator + iter->second.userIdentifier;
693
694 for (foundIt = 0, index = 0;
695 index < userList.size(); ++index)
696 {
697 // Do a wildcard match
698
699 // if (user.matchesWildcards(userList[index]))
700 if (userList[index] == user)
701 foundIt = 1;
702 }
703 }
704
705 if (foundIt && (typeList.size() != 0))
706 {
707 STAFString lowerType = iter->second.type.toLowerCase();
708
709 for (foundIt = 0, index = 0;
710 index < typeList.size(); ++index)
711 {
712 if (typeList[index] == lowerType)
713 foundIt = 1;
714 }
715 }
716
717 if (foundIt && (containsList.size() != 0))
718 {
719 STAFString &msg = iter->second.message;
720
721 for (foundIt = 0, index = 0;
722 index < containsList.size(); ++index)
723 {
724 if (msg.find(containsList[index]) !=
725 STAFString::kNPos)
726 {
727 foundIt = 1;
728 }
729 }
730 }
731
732 if (foundIt && (icontainsList.size() != 0))
733 {
734 STAFString lowerMsg = iter->second.message.
735 toLowerCase();
736
737 for (foundIt = 0, index = 0;
738 index < icontainsList.size(); ++index)
739 {
740 if (lowerMsg.find(icontainsList[index]) !=
741 STAFString::kNPos)
742 {
743 foundIt = 1;
744 }
745 }
746 }
747
748 if (!foundIt)
749 {
750 // This queue element doesn't match search criteria
751 // so skip it next time if doing a GET request
752
753 if (isGet) ++entriesToSkip;
754
755 // Continue to process the next element in the queue
756 continue;
757 }
758
759 // This queue element matches the search criteria
760
761 numFound++;
762
763 // Create the queueEntryMap for the queued message
764
765 STAFObjectPtr queueEntryMap = fQueueEntryMapClass->
766 createInstance();
767
768 queueEntryMap->put("priority",
769 STAFString(iter->second.priority));
770 queueEntryMap->put("timestamp",
771 iter->second.timestamp.asString());
772 queueEntryMap->put("machine", iter->second.machine);
773
774 if (iter->second.process.length() == 0)
775 {
776 queueEntryMap->put("handleName",
777 STAFObject::createNone());
778 }
779 else
780 {
781 queueEntryMap->put("handleName",
782 iter->second.process);
783 }
784
785 queueEntryMap->put("handle",
786 STAFString(iter->second.handle));
787 queueEntryMap->put("user",
788 iter->second.authenticator +
789 gSpecSeparator +
790 iter->second.userIdentifier);
791
792 if (iter->second.type.length() != 0)
793 queueEntryMap->put("type", iter->second.type);
794
795 queueEntryMap->put("message", iter->second.message);
796
797 if (all || first)
798 resultList->append(queueEntryMap);
799 else
800 mc->setRootObject(queueEntryMap);
801
802 if (isGet)
803 {
804 // Remove the message from the queue
805 handleQueue->fQueue.erase(iter);
806 }
807
808 if (!all && !first)
809 {
810 // Return information about this queue element
811 return STAFServiceResult(kSTAFOk, mc->marshall());
812 }
813
814 // If GET, break out of the for loop so that iter won't be
815 // incremented at the end of the loop as that can cause an
816 // exception since an element was removed from the
817 // iterated queue list
818
819 if (isGet) break;
820
821 } // end for loop
822
823 if (!isGet)
824 {
825 // Peek - Finished iterating through the queue
826 done = true;
827 }
828 else
829 {
830 // Get - Have to keep checking for matching messages
831 // if found a message last time since the message
832 // was removed and can't continue using the iterator
833 // for a list that has changed
834
835 if (!foundIt)
836 {
837 // No more matching messages in the queue
838 done = true;
839 }
840 }
841 } // end while loop
842
843 if (doWait && (numFound == 0))
844 {
845 // WAIT option was specified and no matching queue elements
846 // have been found yet. Check if should continue waiting.
847
848 unsigned int deltaTime = (STAFTimestamp::now() - startTime) *
849 1000;
850
851 if (deltaTime >= timeout)
852 {
853 return STAFServiceResult(kSTAFTimeout);
854 }
855 else
856 {
857 currTimeout = timeout - deltaTime;
858 event->reset();
859 }
860 }
861 else
862 {
863 retry = false;
864 }
865
866 } // end lock on handle's queue
867
868 if (retry)
869 {
870 // Check if the handle still exists in case it has been
871 // unregistered/deleted in which case we want to return a
872 // Request Cancelled error and stop waiting
873
874 STAFHandleQueuePtr queuePtr;
875
876 rc = gHandleManagerPtr->handleQueue(requestInfo.fHandle,
877 queuePtr);
878
879 if (rc == kSTAFHandleDoesNotExist)
880 return STAFServiceResult(kSTAFRequestCancelled);
881
882 // Wait until an element is placed on the queue or times out
883
884 if (event->wait(currTimeout))
885 {
886 return STAFServiceResult(kSTAFTimeout);
887 }
888 }
889 }
890
891 if (numFound == 0)
892 {
893 return STAFServiceResult(kSTAFNoQueueElement);
894 }
895
896 mc->setRootObject(resultList);
897 return STAFServiceResult(kSTAFOk, mc->marshall());
898 }
899
900
handleDelete(const STAFServiceRequest & requestInfo)901 STAFServiceResult STAFQueueService::handleDelete(
902 const STAFServiceRequest &requestInfo)
903 {
904 // Verify that this request came from the local machine
905 // No check of trust is needed since these commands are only valid
906 // with respect to the submitting process' queue so just set
907 // required trust level to 0.
908
909 IVALIDATE_LOCAL_TRUST(0, "DELETE");
910
911 // Parse the request
912
913 STAFCommandParseResultPtr parsedResult = fDeleteParser.parse(
914 requestInfo.fRequest);
915
916 if (parsedResult->rc != kSTAFOk)
917 {
918 return STAFServiceResult(kSTAFInvalidRequestString,
919 parsedResult->errorBuffer, 0);
920 }
921
922 STAFString errorBuffer;
923
924 unsigned int checkPriority = parsedResult->optionTimes("PRIORITY");
925 unsigned int checkMachine = parsedResult->optionTimes("MACHINE");
926 unsigned int checkName = parsedResult->optionTimes("NAME");
927 unsigned int checkHandle = parsedResult->optionTimes("HANDLE");
928 unsigned int checkUser = parsedResult->optionTimes("USER");
929 unsigned int checkType = parsedResult->optionTimes("TYPE");
930 unsigned int checkContains = parsedResult->optionTimes("CONTAINS");
931 unsigned int checkIContains = parsedResult->optionTimes("ICONTAINS");
932
933 DEFINE_VAR_POOL_LIST(varPoolList, varPoolListSize, requestInfo);
934 STAFHandleQueuePtr handleQueue;
935 STAFRC_t rc = gHandleManagerPtr->handleQueue(requestInfo.fHandle,
936 handleQueue);
937 if (rc) return STAFServiceResult(rc);
938
939 unsigned int numDeleted = 0;
940 STAFMutexSemLock queueLock(handleQueue->fQueueSem);
941 STAFHandleQueue::HandleQueue::iterator iter;
942 int foundIt = 0;
943
944 for (iter = handleQueue->fQueue.begin();
945 iter != handleQueue->fQueue.end();)
946 {
947 foundIt = 1;
948
949 if (checkPriority)
950 {
951 unsigned int priority = 0;
952 foundIt = 0;
953
954 for (int i = 1; (i <= parsedResult->optionTimes("PRIORITY")) &&
955 !foundIt; ++i)
956 {
957 rc = RESOLVE_INDEXED_UINT_OPTION("PRIORITY", i, priority);
958 if (rc) return STAFServiceResult(rc, errorBuffer);
959 if (priority == iter->second.priority) foundIt = 1;
960 }
961 }
962
963 if (foundIt && checkMachine)
964 {
965 STAFString machine;
966 foundIt = 0;
967
968 for (int i = 1; (i <= parsedResult->optionTimes("MACHINE")) &&
969 !foundIt; ++i)
970 {
971 rc = RESOLVE_INDEXED_STRING_OPTION("MACHINE", i, machine);
972
973 if (rc) return STAFServiceResult(rc, errorBuffer);
974
975 machine.lowerCase();
976
977 // Do a wildcard match
978
979 STAFString lowerMachine = iter->second.machine.toLowerCase();
980
981 if (lowerMachine.matchesWildcards(machine))
982 {
983 foundIt = 1;
984 }
985 }
986 }
987
988 if (foundIt && checkName)
989 {
990 STAFString name;
991 foundIt = 0;
992
993 for (int i = 1; (i <= parsedResult->optionTimes("NAME")) &&
994 !foundIt; ++i)
995 {
996 rc = RESOLVE_INDEXED_STRING_OPTION("NAME", i, name);
997
998 if (rc) return STAFServiceResult(rc, errorBuffer);
999
1000 name.lowerCase();
1001
1002 if (name == iter->second.process.toLowerCase()) foundIt = 1;
1003 }
1004 }
1005
1006 if (foundIt && checkHandle)
1007 {
1008 unsigned int theHandle = 0;
1009 foundIt = 0;
1010
1011 for (int i = 1; (i <= parsedResult->optionTimes("HANDLE")) &&
1012 !foundIt; ++i)
1013 {
1014 rc = RESOLVE_INDEXED_UINT_OPTION_RANGE(
1015 "HANDLE", i, theHandle,
1016 gHandleManagerPtr->getMinHandleNumber(),
1017 gHandleManagerPtr->getMaxHandleNumber());
1018
1019 if (rc) return STAFServiceResult(rc, errorBuffer);
1020
1021 if (theHandle == iter->second.handle) foundIt = 1;
1022 }
1023 }
1024
1025 if (foundIt && checkUser)
1026 {
1027 STAFString user;
1028 foundIt = 0;
1029
1030 for (int i = 1; (i <= parsedResult->optionTimes("USER")) &&
1031 !foundIt; ++i)
1032 {
1033 rc = RESOLVE_INDEXED_STRING_OPTION("USER", i, user);
1034
1035 if (rc) return STAFServiceResult(rc, errorBuffer);
1036
1037 // Check if authenticator was specified in the user value
1038
1039 unsigned int sepIndex = user.find(gSpecSeparator);
1040
1041 if (sepIndex == STAFString::kNPos)
1042 {
1043 // No authenticator specified
1044 // Use lower-case default authenticator
1045 user = gServiceManagerPtr->getDefaultAuthenticator().
1046 toLowerCase() + gSpecSeparator + user;
1047 }
1048 else
1049 {
1050 // User specified in form of Authenticator://UserIdentifier
1051 // Change authenticator to lower-case.
1052 user = user.subString(0, sepIndex).toLowerCase() +
1053 user.subString(sepIndex);
1054 }
1055
1056 // Do a wildcard match
1057
1058 STAFString matchString(
1059 iter->second.authenticator.toLowerCase() +
1060 gSpecSeparator + iter->second.userIdentifier);
1061
1062 // if (matchString.matchesWildcards(user)) foundIt = 1;
1063 if (matchString == user) foundIt = 1;
1064 }
1065 }
1066
1067 if (foundIt && checkType)
1068 {
1069 STAFString type;
1070 foundIt = 0;
1071
1072 for (int i = 1; (i <= parsedResult->optionTimes("TYPE")) &&
1073 !foundIt; ++i)
1074 {
1075 rc = RESOLVE_INDEXED_STRING_OPTION("TYPE", i, type);
1076
1077 if (rc) return STAFServiceResult(rc, errorBuffer);
1078
1079 type.lowerCase();
1080
1081 if (type == iter->second.type.toLowerCase()) foundIt = 1;
1082 }
1083 }
1084
1085 if (foundIt && checkContains)
1086 {
1087 STAFString contains;
1088 foundIt = 0;
1089
1090 for (int i = 1; (i <= parsedResult->optionTimes("CONTAINS")) &&
1091 !foundIt; ++i)
1092 {
1093 rc = RESOLVE_INDEXED_STRING_OPTION("CONTAINS", i, contains);
1094
1095 if (rc) return STAFServiceResult(rc, errorBuffer);
1096
1097 if (iter->second.message.find(contains) != STAFString::kNPos)
1098 foundIt = 1;
1099 }
1100 }
1101
1102 if (foundIt && checkIContains)
1103 {
1104 STAFString checkMessage = iter->second.message.toLowerCase();
1105 STAFString icontains;
1106 foundIt = 0;
1107
1108 for (int i = 1; (i <= parsedResult->optionTimes("ICONTAINS")) &&
1109 !foundIt; ++i)
1110 {
1111 rc = RESOLVE_INDEXED_STRING_OPTION("ICONTAINS", i, icontains);
1112
1113 if (rc) return STAFServiceResult(rc, errorBuffer);
1114
1115 if (checkMessage.find(icontains.toLowerCase()) !=
1116 STAFString::kNPos)
1117 {
1118 foundIt = 1;
1119 }
1120 }
1121 }
1122
1123 if (foundIt)
1124 {
1125 ++numDeleted;
1126 handleQueue->fQueue.erase(iter);
1127 iter = handleQueue->fQueue.begin();
1128 }
1129 else
1130 {
1131 ++iter;
1132 }
1133 }
1134
1135 return STAFServiceResult(kSTAFOk, STAFString(numDeleted));
1136 }
1137
1138
handleList(const STAFServiceRequest & requestInfo)1139 STAFServiceResult STAFQueueService::handleList(
1140 const STAFServiceRequest &requestInfo)
1141 {
1142 // Verify that the requesting machine/user has at least trust level 2
1143
1144 IVALIDATE_TRUST(2, "LIST");
1145
1146 // Parse the request
1147
1148 STAFCommandParseResultPtr parsedResult = fListParser.parse(
1149 requestInfo.fRequest);
1150
1151 if (parsedResult->rc != kSTAFOk)
1152 {
1153 return STAFServiceResult(kSTAFInvalidRequestString,
1154 parsedResult->errorBuffer, 0);
1155 }
1156
1157 STAFString errorBuffer;
1158
1159 // HANDLE may only default if the request came from this machine
1160
1161 if ((parsedResult->optionTimes("HANDLE") == 0) &&
1162 !requestInfo.fIsLocalRequest)
1163 {
1164 return STAFServiceResult(kSTAFInvalidRequestString);
1165 }
1166
1167 DEFINE_VAR_POOL_LIST(varPoolList, varPoolListSize, requestInfo);
1168 unsigned int theHandle = requestInfo.fHandle;
1169
1170 STAFRC_t rc = RESOLVE_OPTIONAL_UINT_OPTION_RANGE(
1171 "HANDLE", theHandle, gHandleManagerPtr->getMinHandleNumber(),
1172 gHandleManagerPtr->getMaxHandleNumber());
1173
1174 if (rc) return STAFServiceResult(rc, errorBuffer);
1175
1176 STAFHandleQueuePtr handleQueue;
1177
1178 rc = gHandleManagerPtr->handleQueue(theHandle, handleQueue);
1179
1180 if (rc) return STAFServiceResult(rc);
1181
1182 // Create a marshalled list of maps containing information for entries
1183 // found in the queue
1184
1185 STAFObjectPtr mc = STAFObject::createMarshallingContext();
1186 mc->setMapClassDefinition(fQueueEntryMapClass->reference());
1187 STAFObjectPtr queueList = STAFObject::createList();
1188
1189 // Iterate through the queue
1190
1191 STAFMutexSemLock queueLock(handleQueue->fQueueSem);
1192
1193 STAFHandleQueue::HandleQueue::iterator iter;
1194
1195 for (iter = handleQueue->fQueue.begin();
1196 iter != handleQueue->fQueue.end(); iter++)
1197 {
1198 STAFHandleQueue::Message message = iter->second;
1199
1200 // Create a map for each entry in the queue
1201
1202 STAFObjectPtr queueEntryMap = fQueueEntryMapClass->createInstance();
1203
1204 queueEntryMap->put("priority", STAFString(message.priority));
1205 queueEntryMap->put("timestamp", message.timestamp.asString());
1206 queueEntryMap->put("machine", message.machine);
1207
1208 if (message.process.length() == 0)
1209 queueEntryMap->put("handleName", STAFObject::createNone());
1210 else
1211 queueEntryMap->put("handleName", message.process);
1212
1213 queueEntryMap->put("handle", STAFString(message.handle));
1214 queueEntryMap->put("user", message.authenticator +
1215 gSpecSeparator + message.userIdentifier);
1216
1217 if (message.type.length() != 0)
1218 queueEntryMap->put("type", message.type);
1219
1220 queueEntryMap->put("message",
1221 STAFHandle::maskPrivateData(message.message));
1222
1223 queueList->append(queueEntryMap);
1224 }
1225
1226 // Set the marshalling context's root object
1227
1228 mc->setRootObject(queueList);
1229
1230 return STAFServiceResult(rc, mc->marshall());
1231 }
1232
1233
handleHelp(const STAFServiceRequest & requestInfo)1234 STAFServiceResult STAFQueueService::handleHelp(
1235 const STAFServiceRequest &requestInfo)
1236 {
1237 // Verify that the requesting machine/user has at least trust level 1
1238
1239 IVALIDATE_TRUST(1, "HELP");
1240
1241 return STAFServiceResult(kSTAFOk, sHelpMsg);
1242 }
1243