ProviewR Programmer's Reference Manual  V6.1.4
rt_qcom.c
Go to the documentation of this file.
1 /*
2  * ProviewR Open Source Process Control.
3  * Copyright (C) 2005-2025 SSAB EMEA AB.
4  *
5  * This file is part of ProviewR.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation, either version 2 of
10  * the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with ProviewR. If not, see <http://www.gnu.org/licenses/>
19  *
20  * Linking ProviewR statically or dynamically with other modules is
21  * making a combined work based on ProviewR. Thus, the terms and
22  * conditions of the GNU General Public License cover the whole
23  * combination.
24  *
25  * In addition, as a special exception, the copyright holders of
26  * ProviewR give you permission to, from the build function in the
27  * ProviewR Configurator, combine ProviewR with modules generated by the
28  * ProviewR PLC Editor to a PLC program, regardless of the license
29  * terms of these modules. You may copy and distribute the resulting
30  * combined work under the terms of your choice, provided that every
31  * copy of the combined work is accompanied by a complete copy of
32  * the source code of ProviewR (the version used to produce the
33  * combined work), being distributed under the terms of the GNU
34  * General Public License plus this exception.
35  */
36 
41 #include <stdlib.h>
42 #include <string.h>
43 
44 #include "rt_errh.h"
45 #include "rt_qdb.h"
46 #include "rt_qmon.h"
47 
48 static void exitHandler();
49 
50 static void sigHandler();
51 
52 static qdb_sBuffer* inPool(pwr_tStatus*, void*);
53 
54 static void exitHandler()
55 {
56  qcom_Exit(NULL);
57 }
58 
59 static void sigHandler()
60 {
61  exit(0);
62 }
63 
64 static qdb_sBuffer* inPool(pwr_tStatus* sts, void* p)
65 {
66  pool_tRef br;
67  qdb_sBuffer* bp;
68 
69  qdb_AssumeLocked;
70 
71  bp = (qdb_sBuffer*)p - 1;
72  if (bp->b.cookie != qdb_cCookie)
73  return NULL;
74 
75  br = pool_InPool(sts, &qdb->pool, bp, bp->b.size + sizeof(*bp));
76  if (br == pool_cNRef)
77  return NULL;
78 
79  return bp;
80 }
81 
85 void* qcom_Alloc(pwr_tStatus* status, unsigned int size)
86 {
87  qdb_sBuffer* bp = NULL;
88  pwr_dStatus(sts, status, QCOM__SUCCESS);
89 
90  qdb_ScopeLock
91  {
92  bp = qdb_Alloc(sts, qdb_eBuffer_base, size);
93  if (bp == NULL)
94  break;
95 
96  qdb->g->call_count++;
97  qdb->ap->call_count++;
98  qdb->ap->alloc_count++;
99  }
100  qdb_ScopeUnlock;
101 
102  if (bp == NULL)
103  return NULL;
104 
105  return (void*)(bp + 1);
106 }
107 
112 {
113  qdb_sQue* qp;
114  pwr_dStatus(sts, status, QCOM__SUCCESS);
115 
116  if (qdb->ap == NULL)
117  pwr_Return(NO, sts, QCOM__NOTINITED);
118 
119  qdb_ScopeLock
120  {
121  qdb->ap->call_count++;
122  qdb->g->call_count++;
123 
124  qp = qdb_Que(sts, qid, NULL);
125  if (qp == NULL)
126  pwr_StatusBreak(*sts, QCOM__NOQ);
127 
128  if (qcom_AidIsNotEqual(&qp->aid, &qcom_cNAid))
129  pwr_StatusBreak(*sts, QCOM__ALLRATTACHED);
130  if (qp->type != qdb_eQue_private)
131  pwr_StatusBreak(*sts, QCOM__NOTATTACHABLE);
132 
133  qdb_AttachQue(sts, qp, qdb->ap);
134  }
135  qdb_ScopeUnlock;
136 
137  return ODD(*sts);
138 }
139 
140 pwr_tBoolean qcom_StealQ(pwr_tStatus *status, const qcom_sQid *qid)
141 {
142  qdb_sQue* qp;
143  pwr_dStatus(sts, status, QCOM__SUCCESS);
144 
145  if (qdb->ap == NULL)
146  pwr_Return(NO, sts, QCOM__NOTINITED);
147 
148  qdb_ScopeLock
149  {
150  qdb->ap->call_count++;
151  qdb->g->call_count++;
152 
153  qp = qdb_Que(sts, qid, NULL);
154  if (qp == NULL)
155  pwr_StatusBreak(*sts, QCOM__NOQ);
156 
157  qp->aid.aix = qdb->my_aix;
158  // TODO insert in sAppl
159  }
160  qdb_ScopeUnlock;
161 
162  return ODD(*sts);
163 }
164 
172  pwr_tStatus* status, const qcom_sQid* tqid, const qcom_sQid* sqid)
173 {
174  qdb_sQbond* bp = NULL;
175  qdb_sQue* sq;
176  qdb_sQue* tq;
177  pwr_dStatus(sts, status, QCOM__SUCCESS);
178 
179  qdb_ScopeLock
180  {
181  if (qdb->ap == NULL)
182  pwr_StatusBreak(*sts, QCOM__NOTINITED);
183  qdb->ap->call_count++;
184  qdb->g->call_count++;
185 
186  sq = qdb_Que(sts, sqid, NULL);
187  if (sq == NULL)
188  pwr_StatusBreak(*sts, QCOM__NOQ);
189 
190  if (sq->type != qdb_eQue_forward)
191  pwr_StatusBreak(*sts, QCOM__NOTBINDABLE);
192 
193  tq = qdb_Que(sts, tqid, NULL);
194  if (tq == NULL)
195  pwr_StatusBreak(*sts, QCOM__NOQ);
196 
197  if (tq->type != qdb_eQue_private)
198  pwr_StatusBreak(*sts, QCOM__NOTBINDABLE);
199 
200  if (qdb_GetBond(sts, sq, tq) != NULL)
201  pwr_StatusBreak(*sts, QCOM__ALRBOUND);
202 
203  bp = qdb_AddBond(sts, sq, tq);
204  }
205  qdb_ScopeUnlock;
206 
207  return bp != NULL;
208 }
209 
214  pwr_tStatus* status, qcom_sQid* qid, qcom_sQattr* attr, const char* qname)
215 {
216  qdb_sQue* qp;
217  qdb_eQue type;
218  qdb_mQue flags;
219  qcom_sQid lqid = qcom_cNQid;
220  pwr_dStatus(sts, status, QCOM__SUCCESS);
221 
222  if (qdb->ap == NULL)
223  pwr_Return(NO, sts, QCOM__NOTINITED);
224 
225  if (qid == NULL)
226  qid = &lqid;
227 
228  flags.m = 0;
229 
230  if (attr != NULL) {
231  switch (attr->type) {
232  case qcom_eQtype_private:
233  type = qdb_eQue_private;
234  break;
235  case qcom_eQtype_forward:
236  type = qdb_eQue_forward;
237  break;
238  case qcom_eQtype_broadcast:
239  type = qdb_eQue_forward;
240  flags.b.broadcast = 1;
241  break;
242  case qcom_eQtype_event:
243  type = qdb_eQue_forward;
244  flags.b.event = 1;
245  break;
246  default:
247  pwr_Return(NO, sts, QCOM__QTYPE);
248  }
249  } else {
250  type = qdb_eQue_private;
251  }
252 
253  qdb_ScopeLock
254  {
255  qdb->ap->call_count++;
256  qdb->g->call_count++;
257 
258  qp = qdb_AddQue(sts, qid->qix);
259  if (qp == NULL)
260  break;
261  qid->qix = qp->qix;
262  qid->nid = qdb->my_nid;
263  qp->type = type;
264  qp->flags.m = flags.m;
265  if (attr)
266  qp->in_quota = attr->quota;
267  qp = qdb_AttachQue(sts, qp, qdb->ap);
268  if (qp == NULL)
269  break;
270  if (flags.b.broadcast) {
271  qdb_AddBond(sts, qp, qdb->exportque);
272  }
273 
274  if (qname != NULL) {
275  strncpy(qp->name, qname, sizeof(qp->name) - 1);
276  qp->name[sizeof(qp->name) - 1] = '\0';
277  } else
278  strcpy(qp->name, "\"unknown name\"");
279  }
280  qdb_ScopeUnlock;
281 
282  return qp != NULL;
283 }
284 
290 {
291  qdb_sQue* qp;
292  pwr_dStatus(sts, status, QCOM__SUCCESS);
293 
294  if (qdb->ap == NULL)
295  pwr_Return(NO, sts, QCOM__NOTINITED);
296 
297  qdb_ScopeLock
298  {
299  qdb->ap->call_count++;
300  qdb->g->call_count++;
301 
302  qp = qdb_Que(sts, qid, NULL);
303  if (qp == NULL)
304  pwr_StatusBreak(*sts, QCOM__NOQ);
305 
306 
307  if (qp->flags.b.broadcast) {
308  qdb_sQbond* bp;
309 
310  if ((bp = qdb_GetBond(sts, qp, qdb->exportque)) != NULL) {
311  pool_Qremove(sts, &qdb->pool, &bp->tgt_ll);
312  pool_Qremove(sts, &qdb->pool, &bp->src_ll);
313  pool_Free(sts, &qdb->pool, bp);
314  }
315  }
316 
317  qdb_RemoveQue(sts, qp);
318  }
319  qdb_ScopeUnlock;
320 
321  return ODD(*sts);
322 }
323 
332 {
333  qdb_sAppl* ap = qdb->ap;
334  pwr_dStatus(sts, status, QCOM__SUCCESS);
335 
336  if (ap == NULL)
337  return YES;
338 
339  qdb_ScopeLock
340  {
341  qdb->ap->call_count++;
342  qdb->g->call_count++;
343 
344  qdb_RemoveAppl(sts, ap);
345  qdb->ap = NULL;
346  }
347  qdb_ScopeUnlock;
348 
349  return YES;
350 }
351 
356 {
357  qdb_sBuffer* bp;
358  pool_tRef br;
359  pwr_dStatus(sts, status, QCOM__SUCCESS);
360 
361  if (p == NULL)
362  pwr_Return(NO, sts, QCOM__NULLBUFF);
363  if (qdb->ap == NULL)
364  pwr_Return(NO, sts, QCOM__NOTINITED);
365 
366  bp = (qdb_sBuffer*)p - 1;
367  if (bp->c.type != qdb_eBuffer_base)
368  pwr_Return(NO, sts, QCOM__NOTALLOC);
369  if (bp->b.cookie != qdb_cCookie)
370  pwr_Return(NO, sts, QCOM__NOTALLOC);
371 
372  qdb_ScopeLock
373  {
374  qdb->ap->call_count++;
375  qdb->g->call_count++;
376 
377  br = pool_InPool(sts, &qdb->pool, bp, bp->b.size + sizeof(*bp));
378  if (br == pool_cNRef)
379  break;
380  qdb_Free(sts, bp);
381  qdb->ap->free_count++;
382  }
383  qdb_ScopeUnlock;
384 
385  return (br != pool_cNRef) && ODD(*sts);
386 }
387 
398 void* qcom_Get(
399  pwr_tStatus* status, const qcom_sQid* qid, qcom_sGet* gp, int tmo)
400 {
401  pwr_tStatus lsts;
402  qdb_sQue* qp = NULL;
403  qdb_sBuffer* bp = NULL;
404  qdb_sBuffer* bbp = NULL;
405  pool_tRef br;
406  void* dp = NULL;
407  pwr_dStatus(sts, status, QCOM__SUCCESS);
408 
409  if (qdb->ap == NULL)
410  pwr_Return(NULL, sts, QCOM__NOTINITED);
411 
412  qdb_ScopeLock
413  {
414  qdb->ap->call_count++;
415  qdb->g->call_count++;
416 
417  /* Check that a given gp or gp->data is not in pool,
418  this could cause serious problems. */
419 
420  if (gp != NULL && gp->data != NULL) {
421  br = pool_InPool(&lsts, &qdb->pool, gp->data, gp->size);
422  if (br != pool_cNRef)
423  break;
424  }
425 
426  qp = qdb_Que(sts, qid, NULL);
427  if (qp == NULL)
428  break;
429 
430  if (qp->aid.aix != qdb->my_aix)
431  pwr_StatusBreak(*sts, QCOM__NOTOWNED);
432  if (qp->type != qdb_eQue_private)
433  pwr_StatusBreak(*sts, QCOM__NOTOWNED);
434 
435  bp = qdb_Get(sts, qp, tmo, gp, 0);
436 
437  if (bp != NULL) {
438  qdb->ap->get_count++;
439  qp->get_count++;
440  }
441  }
442  qdb_ScopeUnlock;
443 
444  if (bp == NULL)
445  return NULL;
446 
447  dp = bp + 1;
448 
449  if (gp == NULL) {
450  ; /* do nothing! */
451  } else if (gp->data == NULL) {
452  gp->data = dp;
453  } else {
454  if (bp->c.type == qdb_eBuffer_reference)
455  bbp = pool_Address(sts, &qdb->pool, bp->r.src);
456  else
457  bbp = bp;
458 
459  dp = qdb_CopyBufferData(sts, bbp, gp);
460 
461  qdb_ScopeLock
462  {
463  if (bp->c.type == qdb_eBuffer_reference)
464  qdb_Free(&lsts, bp);
465  qdb_Free(&lsts, bbp);
466  qdb->ap->free_count++;
467  }
468  qdb_ScopeUnlock;
469  }
470 
471  return dp;
472 }
473 
474 
478 qcom_tBus qcom_MyBus(pwr_tStatus* status)
479 {
480  qcom_tBus bus;
481 
482  pwr_dStatus(sts, status, QCOM__SUCCESS);
483 
484  qdb_ScopeLock
485  {
486  bus = qdb->g->bus;
487  }
488  qdb_ScopeUnlock;
489 
490  return bus;
491 }
492 
497 {
498  pwr_dStatus(sts, status, QCOM__SUCCESS);
499 
500  if (node == NULL)
501  pwr_Return(NO, sts, QCOM__BADARG);
502 
503  qdb_ScopeLock
504  {
505  qdb_NodeInfo(NULL, node, qdb->my_node);
506  }
507  qdb_ScopeUnlock;
508 
509  return YES;
510 }
511 
516 {
517  static char name[80];
518  qcom_sNode node;
519  pwr_tStatus sts;
520 
521  qcom_Node(&sts, &node, nid);
522  if (EVEN(sts))
523  strcpy(name, "");
524  else
525  strncpy(name, node.name, sizeof(name));
526 
527  return name;
528 }
529 
534 {
535  qdb_sNode* np = NULL;
536  pwr_dStatus(sts, status, QCOM__SUCCESS);
537 
538  if (node == NULL)
539  pwr_Return(NO, sts, QCOM__BADARG);
540 
541  qdb_ScopeLock
542  {
543  np = hash_Search(sts, &qdb->nid_ht, &nid);
544  if (np == NULL)
545  *sts = QCOM__NOSUCHNODE;
546  else
547  qdb_NodeInfo(NULL, node, np);
548  }
549  qdb_ScopeUnlock;
550 
551  return (np != NULL);
552 }
553 
566  pwr_tStatus* status, qcom_sNode* node, pwr_tNodeId nid)
567 {
568  pool_sQlink* nl = NULL;
569  qdb_sNode* np = NULL;
570  pwr_dStatus(sts, status, QCOM__SUCCESS);
571 
572  if (node == NULL)
573  pwr_Return(NO, sts, QCOM__BADARG);
574 
575  qdb_ScopeLock
576  {
577  if (nid == pwr_cNNodeId) {
578  nl = pool_Qsucc(NULL, &qdb->pool, &qdb->g->node_lh);
579  if (nl == &qdb->g->node_lh) {
580  *sts = QCOM__NO_NODE;
581  break;
582  } else {
583  np = pool_Qitem(nl, qdb_sNode, node_ll);
584  if (np == NULL)
585  break;
586 
587  qdb_NodeInfo(NULL, node, np);
588  break;
589  }
590  } else {
591  np = hash_Search(sts, &qdb->nid_ht, &nid);
592  if (np == NULL) {
593  *sts = QCOM__NOSUCHNODE;
594  } else {
595  nl = &np->node_ll;
596  }
597  }
598 
599  if (nl == NULL)
600  break;
601 
602  while (TRUE) {
603  /* loop over no node */
604  np = NULL;
605  nl = pool_Qsucc(NULL, &qdb->pool, nl);
606  if (nl == &qdb->g->node_lh) {
607  *sts = QCOM__NO_NODE;
608  break;
609  } else {
610  np = pool_Qitem(nl, qdb_sNode, node_ll);
611  if (np->nid == pwr_cNNodeId) {
612  continue;
613  } else {
614  break;
615  }
616  }
617  }
618 
619  if (np == NULL)
620  break;
621 
622  qdb_NodeInfo(NULL, node, np);
623  }
624  qdb_ScopeUnlock;
625 
626  return (np != NULL);
627 }
628 
643 pwr_tBoolean qcom_Init(pwr_tStatus* status, qcom_sAid* aid, const char* aname)
644 {
645  qdb_sAppl* ap = NULL;
646  pwr_tStatus lsts;
647  qcom_sAid laid;
648  pwr_tBoolean added = 0;
649  struct sigaction sa;
650  sigset_t ss;
651  pwr_dStatus(sts, status, QCOM__SUCCESS);
652 
653  if (aid == NULL) {
654  memset(&laid, 0, sizeof(laid));
655  aid = &laid;
656  }
657 
658  qdb = qdb_MapDb(sts);
659  if (qdb == NULL || (EVEN(*sts) && *sts != QDB__ALRMAP))
660  return NO;
661 
662  qdb_ScopeLock
663  {
664  qdb->g->call_count++;
665 
666  if (qdb->ap == NULL) {
667  ap = hash_Search(sts, &qdb->pid_ht, &qdb->my_pid);
668  if (ap != NULL) {
669  qdb->ap = ap;
670  qdb_RemoveAppl(&lsts, ap);
671  qdb->ap = NULL;
672  }
673 
674  ap = qdb_AddAppl(sts, NO);
675  if (ap == NULL)
676  break;
677 
678  added = 1;
679 
680  ap->call_count = 1;
681  if (aname != NULL) {
682  strncpy(ap->name, aname, sizeof(ap->name) - 1);
683  ap->name[sizeof(ap->name) - 1] = '\0';
684  } else {
685  strcpy(ap->name, "\"unknown name\"");
686  }
687  } else {
688  ap = qdb->ap;
689  }
690  }
691  qdb_ScopeUnlock;
692 
693  if (ap == NULL)
694  return NO;
695 
696  qdb->ap = ap;
697 
698  if (!added)
699  return YES;
700 
701  *aid = ap->aid;
702 
703  errh_Info("Adding application. aix: %d", ap->aid.aix);
704  atexit(exitHandler);
705  sa.sa_handler = sigHandler;
706  sa.sa_flags = 0;
707  sigemptyset(&sa.sa_mask);
708  sigaction(SIGHUP, &sa, NULL);
709  sigaction(SIGINT, &sa, NULL);
710  sigemptyset(&ss);
711  sigaddset(&ss, qdb_cSigMsg);
712  sigprocmask(SIG_BLOCK, &ss, NULL);
713 
714  qdb_ScopeLock
715  {
716  qdb_ApplEvent(NULL, ap, qcom_eStype_applConnect);
717  }
718  qdb_ScopeUnlock;
719 
720  return YES;
721 }
722 
748 {
749  qdb_sBuffer* bp = NULL;
750  qdb_sNode* np = NULL;
751  qdb_sQue* qp = NULL;
752  pwr_dStatus(sts, status, QCOM__SUCCESS);
753  pwr_tStatus lsts;
754 
755  pwr_Assert(pp != NULL);
756 
757  if (qdb->ap == NULL)
758  pwr_Return(NO, sts, QCOM__NOTINITED);
759 
760  qdb_ScopeLock
761  {
762  qdb->ap->call_count++;
763  qdb->g->call_count++;
764 
765  qp = qdb_Que(sts, qidp, &np);
766  if (qp == NULL)
767  break;
768 
769  if (!pp->allocate)
770  bp = inPool(sts, pp->data);
771  if (pp->allocate || bp == NULL) {
772  bp = qdb_Alloc(sts, qdb_eBuffer_base, pp->size);
773  if (bp == NULL) {
774  *sts = QDB__QUOTAEXCEEDED;
775  break;
776  }
777  memcpy((char*)(bp + 1), pp->data, pp->size);
778  } else {
779  /* check that this buffer is really owned by this process */
780  }
781 
782  qdb_PutInfo(bp, pp, qidp, 0);
783 
784  if (qp->qix == qdb_cIexport) {
785  bp->c.flags.b.remote = 1;
786  bp->b.noderef = pool_Reference(sts, &qdb->pool, np);
787  bp->b.msg_id = pp->msg_id;
788  bp->b.prio = pp->prio;
789  } else {
790  bp->b.msg_id = pp->msg_id;
791  bp->b.prio = pp->prio;
792  }
793 
794  qdb_Put(sts, bp, qp);
795  if (*sts == QDB__QUOTAEXCEEDED)
796  qdb_Free(&lsts, bp);
797  else if (ODD(*sts))
798  qdb->ap->put_count++;
799  }
800  qdb_ScopeUnlock;
801 
802  return ODD(*sts);
803 }
804 
812  pwr_tStatus* status, const qcom_sQid* sqid, const qcom_sQid* tqid)
813 {
814  qdb_sQue* sq;
815  qdb_sQue* tq;
816  qdb_sQbond* bp;
817  pwr_dStatus(sts, status, QCOM__SUCCESS);
818 
819  if (qdb->ap == NULL)
820  pwr_Return(NO, sts, QCOM__NOTINITED);
821 
822  qdb_ScopeLock
823  {
824  qdb->ap->call_count++;
825  qdb->g->call_count++;
826 
827  /* Make sure queues exists. */
828 
829  sq = qdb_Que(sts, sqid, NULL);
830  if (sq == NULL)
831  pwr_StatusBreak(*sts, QCOM__NOQ);
832 
833  tq = qdb_Que(sts, tqid, NULL);
834  if (tq == NULL)
835  pwr_StatusBreak(*sts, QCOM__NOQ);
836 
837  if ((bp = qdb_GetBond(sts, sq, tq)) == NULL)
838  pwr_StatusBreak(*sts, QCOM__NOTBOUND);
839 
840  pool_Qremove(sts, &qdb->pool, &bp->tgt_ll);
841  pool_Qremove(sts, &qdb->pool, &bp->src_ll);
842  pool_Free(sts, &qdb->pool, bp);
843  }
844  qdb_ScopeUnlock;
845 
846  return ODD(*sts);
847 }
848 
858 int qcom_QidCompare(const qcom_sQid* q1, const qcom_sQid* q2)
859 {
860  if (q1->nid == q2->nid) {
861  if (q1->qix == q2->qix)
862  return 0;
863  else if (q1->qix < q2->qix)
864  return -1;
865  else
866  return 1;
867  } else if (q1->nid < q2->nid)
868  return -1;
869  else
870  return 1;
871 }
872 
881 {
882  return (q1->nid == q2->nid) && (q1->qix == q2->qix);
883 }
884 
893 {
894  return (q1->nid != q2->nid) || (q1->qix != q2->qix);
895 }
896 
906 {
907  return (q->nid == qcom_cNQid.nid) && (q->qix == qcom_cNQid.qix);
908 }
909 
919 {
920  return (q->nid != qcom_cNQid.nid) || (q->qix != qcom_cNQid.qix);
921 }
922 
932 int qcom_AidCompare(const qcom_sAid* a1, const qcom_sAid* a2)
933 {
934  if (a1->nid == a2->nid) {
935  if (a1->aix == a2->aix)
936  return 0;
937  else if (a1->aix < a2->aix)
938  return -1;
939  else
940  return 1;
941  } else if (a1->nid < a2->nid)
942  return -1;
943  else
944  return 1;
945 }
946 
956 {
957  return (a1->nid == a2->nid) && (a1->aix == a2->aix);
958 }
959 
969 {
970  return (a1->nid != a2->nid) || (a1->aix != a2->aix);
971 }
972 
982 {
983  return (a->nid == qcom_cNAid.nid) && (a->aix == qcom_cNAid.aix);
984 }
985 
994 {
995  return (a->nid != qcom_cNAid.nid) || (a->aix != qcom_cNAid.aix);
996 }
997 
998 /*
999  pwr_tBoolean qcom_Put (
1000  pwr_tStatus *sts,
1001  const qcom_sQid *receiver,
1002  qcom_sPut *put
1003  );
1004  void* qcom_Get (
1005  pwr_tStatus *sts,
1006  const qcom_sQid *myQ,
1007  qcom_sGet *get,
1008  int tmo_ms
1009  );
1010 */
1011 
1022 void* qcom_Request(pwr_tStatus* status, const qcom_sQid* pqid, qcom_sPut* pp,
1023  const qcom_sQid* gqid, qcom_sGet* gp, int tmo, pwr_tBitMask flags)
1024 {
1025  qdb_sBuffer* pbp;
1026  qdb_sNode* np = NULL;
1027  qdb_sQue* pqp = NULL;
1028  pwr_tStatus lsts;
1029  qdb_sQue* gqp = NULL;
1030  qdb_sBuffer* gbp = NULL;
1031  qdb_sBuffer* gbbp = NULL;
1032  pool_tRef gbr;
1033  void* dp = NULL;
1034  pwr_dStatus(sts, status, QCOM__SUCCESS);
1035 
1036  pwr_Assert(pp != NULL);
1037 
1038  if (tmo < 0) {
1039  pwr_Return(NULL, sts, QCOM__HIGHTMO);
1040  }
1041 
1042  if (qdb->ap == NULL)
1043  pwr_Return(NULL, sts, QCOM__NOTINITED);
1044 
1045  qdb_ScopeLock
1046  {
1047  qdb->ap->call_count++;
1048  qdb->g->call_count++;
1049 
1050  pqp = qdb_Que(sts, pqid, &np);
1051  if (pqp == NULL)
1052  break;
1053 
1054  /* Check that a given gp or gp->data is not in pool,
1055  this could cause serious problems. */
1056 
1057  if (gp != NULL && gp->data != NULL) {
1058  gbr = pool_InPool(&lsts, &qdb->pool, gp->data, gp->size);
1059  if (gbr != pool_cNRef)
1060  return NULL;
1061  }
1062 
1063  gqp = qdb_Que(sts, gqid, NULL);
1064  if (gqp == NULL)
1065  break;
1066 
1067  if (gqp->aid.aix != qdb->my_aix)
1068  pwr_StatusBreak(*sts, QCOM__NOTOWNED);
1069  if (gqp->type != qdb_eQue_private)
1070  pwr_StatusBreak(*sts, QCOM__NOTOWNED);
1071 
1072  pbp = inPool(sts, pp->data);
1073  if (pbp == NULL) {
1074  pbp = qdb_Alloc(sts, qdb_eBuffer_base, pp->size);
1075  memcpy((char*)(pbp + 1), pp->data, pp->size);
1076  } else {
1077  /* check that this buffer is really owned by this process */
1078  }
1079 
1080  pbp->c.flags.b.request = 1;
1081  qdb_PutInfo(pbp, pp, pqid, 0);
1082 
1083  if (pqp->qix == qdb_cIexport) {
1084  pbp->c.flags.b.remote = 1;
1085  pbp->b.noderef = pool_Reference(sts, &qdb->pool, np);
1086  }
1087 
1088  gbp = qdb_Request(sts, pbp, pqp, gqp, tmo, gp, flags);
1089  if (ODD(*sts))
1090  qdb->ap->request_count++;
1091  }
1092  qdb_ScopeUnlock;
1093 
1094  if (gbp == NULL)
1095  return NULL;
1096 
1097  dp = gbp + 1;
1098 
1099  if (gp == NULL) {
1100  ; /* do nothing! */
1101  } else if (gp->data == NULL) {
1102  gp->data = dp;
1103  } else {
1104  if (gbp->c.type == qdb_eBuffer_reference)
1105  gbbp = pool_Address(sts, &qdb->pool, gbp->r.src);
1106  else
1107  gbbp = gbp;
1108 
1109  dp = qdb_CopyBufferData(sts, gbbp, gp);
1110 
1111  qdb_ScopeLock
1112  {
1113  if (gbp->c.type == qdb_eBuffer_reference)
1114  qdb_Free(&lsts, gbp);
1115  qdb_Free(&lsts, gbbp);
1116  qdb->ap->free_count++;
1117  }
1118  qdb_ScopeUnlock;
1119  }
1120 
1121  return dp;
1122 }
1123 
1132 {
1133  qdb_sBuffer* bp;
1134  qdb_sNode* np = NULL;
1135  qdb_sQue* qp = NULL;
1136  pwr_dStatus(sts, status, QCOM__SUCCESS);
1137 
1138  pwr_Assert(gp != NULL);
1139  pwr_Assert(pp != NULL);
1140 
1141  if (qdb->ap == NULL)
1142  pwr_Return(NO, sts, QCOM__NOTINITED);
1143 
1144  qdb_ScopeLock
1145  {
1146  qdb->ap->call_count++;
1147  qdb->g->call_count++;
1148 
1149  qp = qdb_Que(sts, &gp->reply, &np);
1150  if (qp == NULL)
1151  break;
1152 
1153  bp = inPool(sts, pp->data);
1154  if (bp == NULL) {
1155  bp = qdb_Alloc(sts, qdb_eBuffer_base, pp->size);
1156  memcpy((char*)(bp + 1), pp->data, pp->size);
1157  } else {
1158  /* check that this buffer is really owned by this process */
1159  }
1160 
1161  qdb_PutInfo(bp, pp, &gp->reply, 0);
1162 
1163  bp->c.flags.b.reply = 1;
1164  bp->c.flags.b.request = 0;
1165  bp->b.info.rid = gp->rid;
1166  bp->b.info.flags.b.reply = 1;
1167  bp->b.info.flags.b.request = 0;
1168  bp->b.info.status = QCOM__SUCCESS;
1169 
1170  if (qp->qix == qdb_cIexport) {
1171  bp->c.flags.b.remote = 1;
1172  bp->b.noderef = pool_Reference(sts, &qdb->pool, np);
1173  }
1174 
1175  qdb_Put(sts, bp, qp);
1176 
1177  qdb->ap->reply_count++;
1178  }
1179  qdb_ScopeUnlock;
1180 
1181  return ODD(*sts);
1182 }
1183 
1199 char* qcom_QidToString(char* s, qcom_sQid* qid, int prefix)
1200 {
1201  cdh_uObjid loid;
1202  static char ls[sizeof("_Q255.255.255.255:4294967295")];
1203 
1204  loid.pwr.vid = (pwr_tVolumeId)qid->nid;
1205  loid.pwr.oix = (pwr_tObjectIx)qid->qix;
1206 
1207  sprintf(ls, "%s%u.%u.%u.%u:%u", (prefix ? "_Q" : ""), loid.o.vid_3,
1208  loid.o.vid_2, loid.o.vid_1, loid.o.vid_0, loid.o.oix);
1209 
1210  if (s != NULL)
1211  return strcat(s, ls);
1212  else
1213  return ls;
1214 }
1215 
1229  const qcom_sQid* eid, int mask, int tmo, int* event)
1230 {
1231  int result = 0;
1232  qdb_sQue* qp;
1233  qdb_sQue* ep;
1234  pwr_dStatus(sts, status, QCOM__SUCCESS);
1235 
1236  qdb_ScopeLock
1237  {
1238  qp = qdb_Que(sts, qid, NULL);
1239  if (qp == NULL)
1240  break;
1241  ep = qdb_Que(sts, eid, NULL);
1242  if (ep == NULL)
1243  break;
1244 
1245  if (qp->aid.aix != qdb->my_aix)
1246  pwr_StatusBreak(*sts, QCOM__NOTOWNED);
1247  if (qp->type != qdb_eQue_private)
1248  pwr_StatusBreak(*sts, QCOM__NOTOWNED);
1249 
1250  result = ep->mask & mask;
1251  if (result)
1252  break;
1253 
1254  qp->or_event = 1;
1255  qp->mask = mask;
1256  result = qdb_Wait(sts, qp, ep, tmo);
1257  *event = ep->mask & mask;
1258  }
1259  qdb_ScopeUnlock;
1260 
1261  return result != 0;
1262 }
1263 
1277  const qcom_sQid* eid, int mask, int tmo)
1278 {
1279  int result = 0;
1280  qdb_sQue* qp;
1281  qdb_sQue* ep;
1282  pwr_dStatus(sts, status, QCOM__SUCCESS);
1283 
1284  qdb_ScopeLock
1285  {
1286  qp = qdb_Que(sts, qid, NULL);
1287  if (qp == NULL)
1288  break;
1289  ep = qdb_Que(sts, eid, NULL);
1290  if (ep == NULL)
1291  break;
1292 
1293  if (qp->aid.aix != qdb->my_aix)
1294  pwr_StatusBreak(*sts, QCOM__NOTOWNED);
1295  if (qp->type != qdb_eQue_private)
1296  pwr_StatusBreak(*sts, QCOM__NOTOWNED);
1297 
1298  result = (ep->mask & mask) == mask;
1299  if (result)
1300  break;
1301 
1302  qp->or_event = 0;
1303  qp->mask = mask;
1304  result = qdb_Wait(sts, qp, ep, tmo);
1305  }
1306  qdb_ScopeUnlock;
1307 
1308  return result != 0;
1309 }
1310 
1311 pwr_tBoolean qcom_SignalAnd(pwr_tStatus* status, const qcom_sQid* eid, int mask)
1312 {
1313  qdb_sQue* ep;
1314 
1315  pwr_dStatus(sts, status, QCOM__SUCCESS);
1316 
1317  qdb_ScopeLock
1318  {
1319  ep = qdb_Que(sts, eid, NULL);
1320  if (ep == NULL)
1321  break;
1322 
1323  ep->mask &= mask;
1324 
1325  qdb_Eput(sts, ep);
1326  qdb_Signal(sts, ep);
1327  }
1328  qdb_ScopeUnlock;
1329 
1330  return ODD(*sts);
1331 }
1332 
1333 pwr_tBoolean qcom_SignalOr(pwr_tStatus* status, const qcom_sQid* eid, int mask)
1334 {
1335  qdb_sQue* ep;
1336 
1337  pwr_dStatus(sts, status, QCOM__SUCCESS);
1338 
1339  qdb_ScopeLock
1340  {
1341  ep = qdb_Que(sts, eid, NULL);
1342  if (ep == NULL)
1343  break;
1344 
1345  ep->mask |= mask;
1346 
1347  qdb_Eput(sts, ep);
1348  qdb_Signal(sts, ep);
1349  }
1350  qdb_ScopeUnlock;
1351 
1352  return ODD(*sts);
1353 }
1354 
1355 pwr_tBitMask qcom_EventMask(pwr_tStatus* status, const qcom_sQid* eid)
1356 {
1357  int result = 0;
1358  qdb_sQue* ep;
1359  pwr_dStatus(sts, status, QCOM__SUCCESS);
1360 
1361  qdb_ScopeLock
1362  {
1363  ep = qdb_Que(sts, eid, NULL);
1364  if (ep == NULL)
1365  break;
1366 
1367  result = ep->mask;
1368  }
1369  qdb_ScopeUnlock;
1370 
1371  return result;
1372 }
1373 
1374 void qcom_SetRedundancyState(pwr_eRedundancyState state)
1375 {
1376  qdb->my_node->redundancy_state = state;
1377 }
1378 
1383 {
1384  pwr_tStatus sts;
1385  qcom_sPut put;
1386  qcom_sQid qmon_qid = { qcom_cImonAction, 0 };
1387 
1388  memset(&put, 0, sizeof(put));
1389  put.type.b = (qcom_eBtype)qmon_cMsgClassAction;
1390  put.type.s = (qcom_eStype)qmon_eMsgTypeAction_Connect;
1391  put.size = sizeof(pwr_tNodeId);
1392  put.data = qcom_Alloc(&sts, put.size);
1393  *(pwr_tNodeId*)put.data = nid;
1394  put.allocate = 0;
1395 
1396  qcom_Put(&sts, &qmon_qid, &put);
1397 }
1398 
1403 {
1404  pwr_tStatus sts;
1405  qcom_sPut put;
1406  qcom_sQid qmon_qid = { qcom_cImonAction, 0 };
1407 
1408  memset(&put, 0, sizeof(put));
1409  put.type.b = (qcom_eBtype)qmon_cMsgClassAction;
1410  put.type.s = (qcom_eStype)qmon_eMsgTypeAction_Disconnect;
1411  put.size = sizeof(pwr_tNodeId);
1412  put.data = qcom_Alloc(&sts, put.size);
1413  *(pwr_tNodeId*)put.data = nid;
1414  put.allocate = 0;
1415 
1416  qcom_Put(&sts, &qmon_qid, &put);
1417 }
1418 
1419 /*
1420 * XDR Routines
1421 */
1422 
1423 bool_t xdr_qcom_sAid(XDR* xdrs, qcom_sAid* objp)
1424 {
1425  if (!xdr_int(xdrs, &objp->aix))
1426  return FALSE;
1427  if (!xdr_int(xdrs, (int*)&objp->nid))
1428  return FALSE;
1429 
1430  return TRUE;
1431 }
1432 
1433 bool_t xdr_qcom_sQid(XDR* xdrs, qcom_sQid* objp)
1434 {
1435  if (!xdr_int(xdrs, &objp->qix))
1436  return FALSE;
1437  if (!xdr_int(xdrs, (int*)&objp->nid))
1438  return FALSE;
1439 
1440  return TRUE;
1441 }
void errh_Info(const char *msg,...)
Log an info message. The function has a variable argument list similar to sprintf.
Definition: rt_errh.c:301
int qcom_QidCompare(const qcom_sQid *q1, const qcom_sQid *q2)
Compare two queue identities;.
Definition: rt_qcom.c:858
pwr_tBoolean qcom_Reply(pwr_tStatus *status, qcom_sGet *gp, qcom_sPut *pp)
Reply to a qcom_Request. The qcom_Reply() call looks almost like a qcom_Put(), but the queue id is re...
Definition: rt_qcom.c:1131
pwr_tBoolean qcom_WaitAnd(pwr_tStatus *status, const qcom_sQid *qid, const qcom_sQid *eid, int mask, int tmo)
Wait for an event or a message.
Definition: rt_qcom.c:1276
pwr_tBoolean qcom_AttachQ(pwr_tStatus *status, const qcom_sQid *qid)
Attach to an allready created queue.
Definition: rt_qcom.c:111
pwr_tBoolean qcom_AidIsNotEqual(const qcom_sAid *a1, const qcom_sAid *a2)
Test if two application identities are different.
Definition: rt_qcom.c:968
pwr_tBoolean qcom_NextNode(pwr_tStatus *status, qcom_sNode *node, pwr_tNodeId nid)
Get the next qcom node. If nid is pwr_cNNodeId the first node is returned.
Definition: rt_qcom.c:565
void qcom_LinkConnect(pwr_tNodeId nid)
Definition: rt_qcom.c:1382
pwr_tBoolean qcom_AidIsEqual(const qcom_sAid *a1, const qcom_sAid *a2)
Test if two application identities are equal.
Definition: rt_qcom.c:955
pwr_tBoolean qcom_QidIsEqual(const qcom_sQid *q1, const qcom_sQid *q2)
Test if two queue identities are equal.
Definition: rt_qcom.c:880
pwr_tBoolean qcom_MyNode(pwr_tStatus *status, qcom_sNode *node)
Get the local qcom node.
Definition: rt_qcom.c:496
qcom_tBus qcom_MyBus(pwr_tStatus *status)
Get the current qcom bus number.
Definition: rt_qcom.c:478
pwr_tBoolean qcom_Unbind(pwr_tStatus *status, const qcom_sQid *sqid, const qcom_sQid *tqid)
Disconnect a target queue from a bound source queue.
Definition: rt_qcom.c:811
pwr_tBoolean qcom_Exit(pwr_tStatus *status)
Disconnect from QCom. Disconnects an application from the Qcom message bus, all resources such as,...
Definition: rt_qcom.c:331
pwr_tBoolean qcom_QidIsNotNull(const qcom_sQid *q)
Test if queue identity is not null.
Definition: rt_qcom.c:918
pwr_tBoolean qcom_Put(pwr_tStatus *status, const qcom_sQid *qidp, qcom_sPut *pp)
Put a new message.
Definition: rt_qcom.c:747
pwr_tBoolean qcom_Bind(pwr_tStatus *status, const qcom_sQid *tqid, const qcom_sQid *sqid)
Bind one queue to another.
Definition: rt_qcom.c:171
pwr_tBoolean qcom_CreateQ(pwr_tStatus *status, qcom_sQid *qid, qcom_sQattr *attr, const char *qname)
Create a queue and make an implicit connect to it.
Definition: rt_qcom.c:213
pwr_tBoolean qcom_WaitOr(pwr_tStatus *status, const qcom_sQid *qid, const qcom_sQid *eid, int mask, int tmo, int *event)
Wait for an event or a message.
Definition: rt_qcom.c:1228
pwr_tBoolean qcom_Node(pwr_tStatus *status, qcom_sNode *node, pwr_tNodeId nid)
Get qcom node from node identity.
Definition: rt_qcom.c:533
pwr_tBoolean qcom_QidIsNull(const qcom_sQid *q)
Test if queue identity is null.
Definition: rt_qcom.c:905
pwr_tBoolean qcom_Free(pwr_tStatus *status, void *p)
Free a previously allocated buffer.
Definition: rt_qcom.c:355
void * qcom_Request(pwr_tStatus *status, const qcom_sQid *pqid, qcom_sPut *pp, const qcom_sQid *gqid, qcom_sGet *gp, int tmo, pwr_tBitMask flags)
Put a request and return the reply.
Definition: rt_qcom.c:1022
int qcom_AidCompare(const qcom_sAid *a1, const qcom_sAid *a2)
Compare two application identities;.
Definition: rt_qcom.c:932
void * qcom_Get(pwr_tStatus *status, const qcom_sQid *qid, qcom_sGet *gp, int tmo)
Get a new message.
Definition: rt_qcom.c:398
void qcom_LinkDisconnect(pwr_tNodeId nid)
Definition: rt_qcom.c:1402
pwr_tBoolean qcom_QidIsNotEqual(const qcom_sQid *q1, const qcom_sQid *q2)
Test if two queue identities are different.
Definition: rt_qcom.c:892
pwr_tBoolean qcom_Init(pwr_tStatus *status, qcom_sAid *aid, const char *aname)
Connect to QCom.
Definition: rt_qcom.c:643
pwr_tBoolean qcom_AidIsNotNull(const qcom_sAid *a)
Test if application identity is not null.
Definition: rt_qcom.c:993
pwr_tBoolean qcom_DeleteQ(pwr_tStatus *status, const qcom_sQid *qid)
Delete a queue. Delete a queue and release all resources held by the queue.
Definition: rt_qcom.c:289
void * qcom_Alloc(pwr_tStatus *status, unsigned int size)
Allocate a buffer in the qcom pool.
Definition: rt_qcom.c:85
char * qcom_QidToString(char *s, qcom_sQid *qid, int prefix)
Converts a queue identifier, 'qid' to a string.
Definition: rt_qcom.c:1199
pwr_tBoolean qcom_AidIsNull(const qcom_sAid *a)
Test if application identity is null.
Definition: rt_qcom.c:981
char * qcom_NodeName(pwr_tNodeId nid)
Get the name of a qcom node.
Definition: rt_qcom.c:515
#define EVEN(a)
Check if value is even.
Definition: pwr.h:623
pwr_tNid pwr_tNodeId
Node identity type.
Definition: pwr.h:298
pwr_tOix pwr_tObjectIx
Object index type.
Definition: pwr.h:244
unsigned int pwr_tBitMask
Bitmask type.
Definition: pwr.h:123
unsigned int pwr_tBoolean
Boolean type.
Definition: pwr.h:127
int pwr_tStatus
Status type.
Definition: pwr.h:284
pwr_tVid pwr_tVolumeId
Volume identity type.
Definition: pwr.h:238
#define ODD(a)
Check if value is odd.
Definition: pwr.h:618
Include file for Errh System log messages.
unsigned int vid_3
Object index.
Definition: co_cdh.h:151
Application identity.
Definition: rt_qcom.h:141
pwr_tNodeId nid
Definition: rt_qcom.h:143
qcom_tAix aix
Definition: rt_qcom.h:142
Get data structure.
Definition: rt_qcom.h:185
Data for a Qcom node.
Definition: rt_qcom.h:219
char name[80]
node name
Definition: rt_qcom.h:222
Put data structure.
Definition: rt_qcom.h:174
Queue attributes.
Definition: rt_qcom.h:162
Queue identity.
Definition: rt_qcom.h:125
qcom_tQix qix
Definition: rt_qcom.h:126
pwr_tNodeId nid
Definition: rt_qcom.h:127
Type for representions of object identity.
Definition: co_cdh.h:340
cdh_mObjid o
Common object representation.
Definition: co_cdh.h:342
pwr_tOid pwr
Extern representation.
Definition: co_cdh.h:341