mp_s_message.C 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. //%% (c) Copyright 1993, 1994 Hewlett-Packard Company
  24. //%% (c) Copyright 1993, 1994 International Business Machines Corp.
  25. //%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  26. //%% (c) Copyright 1993, 1994 Novell, Inc.
  27. //%% $TOG: mp_s_message.C /main/4 1999/09/17 18:29:54 mgreess $
  28. /*
  29. *
  30. * @(#)mp_s_message.C 1.53 94/11/17
  31. *
  32. * Tool Talk Message Passer (MP) - mp_s_message.cc
  33. *
  34. * Copyright (c) 1990,1992,1993 by Sun Microsystems, Inc.
  35. */
  36. /*
  37. * Server-specific methods for the _Tt_message class
  38. */
  39. #include "mp_s_global.h"
  40. #include "mp/mp_arg.h"
  41. #include "mp/mp_msg_context.h"
  42. #include "mp_s_file.h"
  43. #include "mp_s_message.h"
  44. #include "mp_s_mp.h"
  45. #include "mp/mp_mp.h"
  46. #include "mp_observer.h"
  47. #include "mp_otype.h"
  48. #include "mp_s_pattern.h"
  49. #include "mp_s_procid.h"
  50. #include "mp_ptype.h"
  51. #include "mp_rpc_implement.h"
  52. #include "mp_s_session.h"
  53. #include "util/tt_enumname.h"
  54. #include "mp/mp_trace.h"
  55. #include "util/tt_global_env.h"
  56. #include <unistd.h>
  57. #include "util/tt_port.h"
  58. _Tt_s_message::
  59. _Tt_s_message()
  60. {
  61. // The active message count is just to enforce the limit
  62. // on the number of active messages. Doing this in the
  63. // constructor was expedient, but because we construct
  64. // a message before _tt_mp is initialized, we have
  65. // to omit it in that case.
  66. if (_tt_s_mp) {
  67. _tt_s_mp->active_messages++;
  68. }
  69. _when_last_matched = 0;
  70. _state_reported = 0;
  71. _num_recipients_yet_to_vote = 0;
  72. }
  73. _Tt_s_message::
  74. ~_Tt_s_message()
  75. {
  76. if (_tt_s_mp && _tt_s_mp->active_messages>0) {
  77. _tt_s_mp->active_messages--;
  78. }
  79. }
  80. //
  81. // Makes a copy of a message. The main reason for copying messages is for
  82. // observers. This is so that the observer will see the message in the
  83. // state in which it was observed (otherwise, a message could be observed
  84. // in one state but when the observer gets around to receiving the
  85. // message the message could have been changed).
  86. //
  87. // If the _Tt_observer_ptr parameter is null then this is a copy of a
  88. // message for a dynamic observer. If it isn't null then this is a copy
  89. // of a message for a static observer. The difference is that static
  90. // observers get to "shadow" certain properties of a message. For
  91. // example, a message may have TT_DISCARD reliability but a static
  92. // observer may request TT_START reliability when observing the message.
  93. // Furthermore, when the static observer receives the message, it expects
  94. // to see the original message (in this case the one with TT_DISCARD as
  95. // the value of the reliability field).
  96. //
  97. // The mechanism to handle this is to have a special field _observer in a
  98. // message. In a message with a non-null _observer, the methods that
  99. // return the value of the "shadowable" properties return the value of
  100. // the observer, otherwise they return the value in the message itself.
  101. // However, when transmitting a message to a recipient the message values
  102. // are always used.
  103. //
  104. _Tt_s_message::
  105. _Tt_s_message(_Tt_s_message *m, _Tt_observer_ptr &o)
  106. {
  107. base_constructor();
  108. _when_last_matched = 0;
  109. _state_reported = 0;
  110. _full_msg_guards = m->_full_msg_guards;
  111. if (o.is_null()) {
  112. _state = m->_state;
  113. _scope = m->_scope;
  114. _reliability = m->_reliability;
  115. _opnum = m->_opnum;
  116. _handler_ptype = m->_handler_ptype;
  117. } else {
  118. _state = m->_state;
  119. o->set_state(_state);
  120. set_scope(o->scope());
  121. set_reliability(o->reliability());
  122. set_opnum(o->opnum());
  123. set_handler_ptype(m->_handler_ptype);
  124. // note: _observer must be set after the above fields,
  125. // otherwise the set_* functions won't set the
  126. // appropiate flags in _full_msg_guards
  127. _observer = o;
  128. }
  129. _status = m->_status;
  130. _status_string = m->_status_string;
  131. // XXX holtz 18 Jul 94 Observers probably see latest args and
  132. // contexts because these two lists are shared, notwithstanding
  133. // comment above about showing observers a message snapshot.
  134. _args = m->_args;
  135. _contexts = m->_contexts;
  136. _message_class = m->_message_class;
  137. _paradigm = m->_paradigm;
  138. _object = m->_object;
  139. _file = m->_file;
  140. _op = m->_op;
  141. _otype = m->_otype;
  142. _session = m->_session;
  143. _sender = m->_sender;
  144. _handler = m->_handler;
  145. // Note: no need for observers to see partial _abstainers etc.
  146. // Note: handler_ptype explicitly not set for observer copy.
  147. _sender_ptype = m->_sender_ptype;
  148. _pattern_id = m->_pattern_id;
  149. _id = m->_id;
  150. _api_id = m->_api_id;
  151. _gid = m->_gid;
  152. _uid = m->_uid;
  153. _flags = m->_flags;
  154. _rsessions = m->_rsessions;
  155. _when_last_matched = m->_when_last_matched;
  156. _original = m;
  157. _num_recipients_yet_to_vote = 0;
  158. }
  159. //
  160. // Called by change_state when invoked with TT_REJECTED. Causes
  161. // re-delivery of the message to attempt to find another handler. The
  162. // deliver method will detect when all possible procids have been tried
  163. // and send the message status to the original message sender.
  164. //
  165. Tt_status _Tt_s_message::
  166. rejected(const _Tt_msg_trace &trace)
  167. {
  168. if (_message_class != TT_REQUEST) { // XXX can only reject requests
  169. return TT_OK;
  170. }
  171. // add handler to list of tried procids for this message.
  172. // This list is never decremented so this insures that this
  173. // handler will never see this message again.
  174. // --> Should a procid be able to accept a message it had
  175. // previously rejected?
  176. if (!_handler.is_null()) {
  177. if (_tried.is_null()) {
  178. _tried = new _Tt_procid_list();
  179. }
  180. // explicitly clear this so that starting will be
  181. // properly handled if rejected.
  182. _state_reported &= ~(1<<TT_STARTED);
  183. _tried->push(_handler);
  184. unset_handler_procid();
  185. }
  186. // attempt re-delivery, but not to observers. The state gets
  187. // changed back to TT_SENT which is what a prospective handler
  188. // will be expecting as the state of an incoming request.
  189. set_state(TT_SENT);
  190. deliver( trace, 0 );
  191. return(TT_OK);
  192. }
  193. //
  194. // Returns 1 if this message needs to be matched against observer
  195. // patterns. This check involves _when_last_matched and the
  196. // _tt_s_mp->when_last_observer_registered.
  197. // _when_last_matched gets updated every
  198. // time this message is matched against observer patterns. Every time
  199. // the message matches an observer pattern a flag called
  200. // _TT_MSG_OBSERVERS_MATCH is set. Thus if _when_last_matched is the same
  201. // as _tt_s_mp->now and this flag is not set then
  202. // re-matching this message against observer patterns would be
  203. // useless. This lets us avoid pattern matching after every state
  204. // change for a message if it is known that no patterns would match
  205. // anyway.
  206. //
  207. int _Tt_s_message::
  208. needs_observer_match()
  209. {
  210. return(_when_last_matched == 0 ||
  211. _flags&(1<<_TT_MSG_OBSERVERS_MATCH) ||
  212. _when_last_matched < _tt_s_mp->when_last_observer_registered);
  213. }
  214. //
  215. // Called by change_state when invoked with TT_QUEUED. Causes
  216. // notification of the sender (if this message is a request). Also,
  217. // re-delivery is done to catch observers of this state and of
  218. // course the message is added to the appropiate queue. Note that
  219. // file-scope queueing of requests is not implemented.
  220. //
  221. Tt_status _Tt_s_message::
  222. queued(const _Tt_msg_trace &trace)
  223. {
  224. _Tt_ptype_ptr ptype;
  225. //
  226. // queueing is only allowed for a message addressed to a
  227. // ptype.
  228. //
  229. if (! handler_ptype().len()) {
  230. return(TT_ERR_PTYPE);
  231. }
  232. if (! _tt_s_mp->ptable->lookup(handler_ptype(), ptype)) {
  233. return(TT_ERR_PTYPE);
  234. }
  235. _Tt_message_ptr m = this;
  236. switch (scope()) {
  237. case TT_SESSION:
  238. case TT_FILE_IN_SESSION:
  239. _tt_s_mp->initial_s_session->queue_message(m);
  240. break;
  241. case TT_FILE:
  242. case TT_BOTH:
  243. set_status((int)TT_ERR_UNIMP);
  244. return(TT_ERR_UNIMP);
  245. case TT_SCOPE_NONE:
  246. default:
  247. return(TT_ERR_SCOPE);
  248. }
  249. report_state_change();
  250. if (needs_observer_match()) {
  251. (void)deliver( trace );
  252. }
  253. return(TT_OK);
  254. }
  255. //
  256. // Called by _Tt_s_message::change_state to change the state of the
  257. // message to TT_STARTED state. In order to do this we invoke the
  258. // _Tt_ptype::start method on the handler ptype to launch a new instance
  259. // of the ptype and then we report the state change to the sender of the
  260. // message. We then redeliver the message to any observers.
  261. //
  262. Tt_status _Tt_s_message::
  263. started(const _Tt_msg_trace &trace)
  264. {
  265. if (! handler_ptype().len()) {
  266. return(TT_ERR_PTYPE);
  267. }
  268. _Tt_ptype_ptr ptype;
  269. _Tt_procid_ptr proc;
  270. _Tt_s_message_ptr mptr = this;
  271. Tt_status status;
  272. if (! _tt_s_mp->ptable->lookup(handler_ptype(), ptype)) {
  273. return(TT_ERR_PTYPE);
  274. }
  275. if ((status = ptype->start(mptr, trace)) != TT_OK) {
  276. return(status);
  277. }
  278. report_state_change();
  279. // re-deliver message to observers.
  280. if (needs_observer_match()) {
  281. (void)deliver( trace );
  282. }
  283. return(TT_OK);
  284. }
  285. //
  286. // Called on to inform the sender of a message about a state change in
  287. // the message. If the sender is local then we just use the
  288. // _Tt_s_procid::add_message method to add the message to the sender's
  289. // undelivered queue. Otherwise, we invoke an rpc call on the remote
  290. // session to send it the message. That remote session is then
  291. // responsible for forwarding the message on to the sender (see
  292. // _tt_rpc_hupdate_msg in mp/mp_rpc_implement.cc for more details).
  293. // Note that only requests will get sent back to the sender.
  294. //
  295. void _Tt_s_message::
  296. report_state_change()
  297. {
  298. if ( (is_handler_copy() && _message_class == TT_REQUEST)
  299. || (_message_class == TT_OFFER))
  300. {
  301. if (! (_flags&(1<<_TT_MSG_IS_REMOTE))) {
  302. ((_Tt_s_procid *)_sender.c_pointer())->add_message(this);
  303. } else {
  304. _Tt_update_args args;
  305. args.message = this;
  306. args.newstate = state();
  307. (void)_session->call(TT_RPC_HUPDATE_MSG,
  308. (xdrproc_t)tt_xdr_update_args,
  309. (char *)&args,
  310. (xdrproc_t)xdr_void,
  311. (char *)0);
  312. }
  313. }
  314. }
  315. //
  316. // Called to change the state of a message to s. The _state_reported
  317. // field in the message keeps track of whether this message has been in
  318. // this state before. If it has then this method just returns. One
  319. // exception to this is the TT_REJECTED state which a message is allowed
  320. // to go to more than once (because eventually all the handlers for the
  321. // message will be exhausted and the message will get either failed or
  322. // handled). The other two exceptions are TT_ACCEPTED and TT_ABSTAINED.
  323. //
  324. // If changer.is_null(), the _sender is assumed to be the changer.
  325. // This probably has no effect, since the absence of a changer usually
  326. // implies TT_FAILED/TT_RETURNED, in which case the changer is
  327. // irrelevant.
  328. //
  329. Tt_status _Tt_s_message::
  330. change_state(const _Tt_procid_ptr &changer, Tt_state s,
  331. const _Tt_msg_trace &trace)
  332. {
  333. Tt_state oldstate = state();
  334. //
  335. // Lots of code calls change_state(TT_FAILED) if the wheels
  336. // come off. TT_OFFERs cannot fail, they just get abstained
  337. // or returned.
  338. //
  339. if ((_message_class == TT_OFFER) && (s == TT_FAILED)) {
  340. if (changer.is_null() || (changer->is_equal( sender() ))) {
  341. s = TT_RETURNED;
  342. } else {
  343. s = TT_ABSTAINED;
  344. }
  345. }
  346. switch (s) {
  347. case TT_REJECTED:
  348. case TT_ACCEPTED:
  349. case TT_ABSTAINED:
  350. break;
  351. default:
  352. if (_state_reported&(1<<s)) {
  353. return TT_OK;
  354. } else {
  355. _state_reported |= (1<<s);
  356. }
  357. break;
  358. }
  359. set_state(s);
  360. _Tt_msg_trace state_trace( *this, oldstate );
  361. Tt_status status = TT_OK;
  362. switch (s) {
  363. case TT_HANDLED:
  364. case TT_FAILED:
  365. case TT_RETURNED:
  366. if (needs_observer_match()) {
  367. /* attempt re-delivery of this message */
  368. // XXX why do this for TT_FAILED?
  369. deliver_to_observers_and_handlers( trace );
  370. }
  371. report_state_change();
  372. break;
  373. case TT_REJECTED:
  374. status = rejected( trace );
  375. break;
  376. case TT_QUEUED:
  377. status = queued( trace );
  378. break;
  379. case TT_STARTED:
  380. status = started( trace );
  381. break;
  382. }
  383. if (! changer.is_null()) {
  384. add_voter( changer, s, trace );
  385. } else if ((! _sender.is_null()) && (s != TT_REJECTED)) {
  386. //
  387. // A null changer means the changer is the sender
  388. // XXX Exclude TT_REJECTED until TT_FILE-scoped
  389. // TT_OFFERs are implemented; see _tt_rpc_hupdate_msg().
  390. //
  391. add_voter( _sender, s, trace );
  392. }
  393. return status;
  394. }
  395. //
  396. // This method gets called just before a message is going to be sent to a
  397. // handler or offeree. It basically sends all the fields of the message that are
  398. // non-empty except for the _state field which is always TT_SENT unless
  399. // this message is a TT_STARTED message indicating it is a start message
  400. // for the handler. The code in _Tt_message::xdr will set the _state of a
  401. // message to TT_SENT if it isn't sent.
  402. //
  403. void _Tt_s_message::
  404. set_send_handler_flags()
  405. {
  406. _flags &= ~(1<<_TT_MSG_UPDATE_XDR_MODE);
  407. _ptr_guards = _full_msg_guards;
  408. SET_PTR_GUARD(_state == TT_STARTED, _TT_MSK_STATE);
  409. }
  410. //
  411. // This method gets called just before a message is going to be xdr'ed to
  412. // its original sender. We can assume that the sender has a copy of this
  413. // message containing the fields that haven't changed when this message
  414. // was failed or handled. Furthermore, tt_message_destroy doesn't destroy
  415. // messages that are in a non-final state. The result is that we can
  416. // assume that fields that weren't changed by the message being handled
  417. // or failed (such as for example the op field) don't need to be sent.
  418. // Furthermore, we don't have to send back fields that have a default
  419. // value such as (_reliability == TT_DISCARD). Most importantly, only
  420. // TT_OUT or TT_INOUT arguments need to be sent back since the TT_IN
  421. // arguments couldn't have changed.
  422. //
  423. void _Tt_s_message::
  424. set_return_sender_flags()
  425. {
  426. const int req_fields = _TT_MSK_ID |
  427. _TT_MSK_STATE |
  428. _TT_MSK_STATUS |
  429. _TT_MSK_FLAGS;
  430. // turn on this flag to let _Tt_message::xdr know that it
  431. // should send out the _out_args field instead of the _args
  432. // field.
  433. _flags |= (1<<_TT_MSG_UPDATE_XDR_MODE);
  434. // initialize the required fields.
  435. _ptr_guards = req_fields;
  436. switch (_paradigm) {
  437. case TT_OTYPE:
  438. case TT_OBJECT:
  439. // scope can change for these messages
  440. _ptr_guards |= _TT_MSK_SCOPE;
  441. // fall into
  442. case TT_PROCEDURE:
  443. // don't send default TT_DISCARD reliability
  444. SET_PTR_GUARD(_reliability != TT_DISCARD, _TT_MSK_RELIABILITY);
  445. break;
  446. default:
  447. break;
  448. }
  449. // collect all TT_OUT and TT_INOUT args
  450. if (_out_args.is_null() && !_args.is_null() && _args->count()) {
  451. _Tt_arg_list_cursor argc(_args);
  452. _out_args = new _Tt_arg_list();
  453. while (argc.next()) {
  454. add_out_arg(*argc);
  455. }
  456. }
  457. // send the following fields only if they're turned on in
  458. // _full_msg_guards which means they have non-default or
  459. // non-empty values.
  460. //
  461. SET_PTR_GUARD(_full_msg_guards&_TT_MSK_SCOPE, _TT_MSK_SCOPE);
  462. SET_PTR_GUARD(_full_msg_guards&_TT_MSK_STATUS_STRING,
  463. _TT_MSK_STATUS_STRING);
  464. SET_PTR_GUARD(_full_msg_guards&_TT_MSK_FILE, _TT_MSK_FILE);
  465. SET_PTR_GUARD(_full_msg_guards&_TT_MSK_OBJECT, _TT_MSK_OBJECT);
  466. SET_PTR_GUARD(_full_msg_guards&_TT_MSK_ARGS, _TT_MSK_ARGS);
  467. SET_PTR_GUARD(_full_msg_guards&_TT_MSK_CONTEXTS, _TT_MSK_CONTEXTS);
  468. SET_PTR_GUARD(_full_msg_guards&_TT_MSK_OFFEREES, _TT_MSK_OFFEREES);
  469. SET_PTR_GUARD(_full_msg_guards&_TT_MSK_HANDLER_PTYPE,
  470. _TT_MSK_HANDLER_PTYPE);
  471. SET_PTR_GUARD(_full_msg_guards&_TT_MSK_HANDLER, _TT_MSK_HANDLER);
  472. SET_PTR_GUARD(_full_msg_guards&_TT_MSK_PATTERN_ID,_TT_MSK_PATTERN_ID);
  473. SET_PTR_GUARD(_full_msg_guards&_TT_MSK_OPNUM, _TT_MSK_OPNUM);
  474. }
  475. //
  476. // Take a message off the wire and set its internal state to
  477. // be consistent with this message server.
  478. // On error, sets status, fails, and returns:
  479. // TT_ERR_PROCID
  480. // TT_ERR_SESSION
  481. //
  482. Tt_status _Tt_s_message::
  483. indoctrinate(const _Tt_msg_trace &trace)
  484. {
  485. if (_sender.is_null()) {
  486. // in principle the client library makes sure the
  487. // sender field is non-null but it doesn't hurt to
  488. // check.
  489. _tt_syslog(0, LOG_ERR, "_sender.is_null()");
  490. set_status((int)TT_ERR_PROCID);
  491. change_state(0, TT_FAILED, trace);
  492. return TT_ERR_PROCID;
  493. }
  494. //
  495. // the _sender field is a _Tt_procid_ptr but it only points to
  496. // an uninitialized _Tt_procid object that just contains an
  497. // id. We use the _Tt_s_mp::find_proc method to map the
  498. // _sender field to the _Tt_procid object that has the same id
  499. // and has already been initialized.
  500. //
  501. _Tt_s_procid_ptr s_sender;
  502. if (! _tt_s_mp->find_proc(_sender, s_sender, 1)) {
  503. set_status((int)TT_ERR_PROCID);
  504. change_state(0, TT_FAILED, trace);
  505. return TT_ERR_PROCID;
  506. }
  507. _sender = s_sender;
  508. // check to see if the message is "local" (in our session) or
  509. // "nonlocal" (sent from another session)
  510. if (_session->address_string() == _tt_s_mp->initial_session->address_string()) {
  511. _flags &= ~(1<<_TT_MSG_IS_REMOTE);
  512. } else {
  513. // if the message is non-local then remap the _session
  514. // pointer to point to an initialized _Tt_session
  515. // object representing the remote session. See
  516. // _Tt_mp::find_session for more details.
  517. //
  518. _flags |= (1<<_TT_MSG_IS_REMOTE);
  519. if (TT_OK != _tt_s_mp->find_session(_session->process_tree_id(),
  520. _session, 1)){
  521. set_status((int)TT_ERR_SESSION);
  522. change_state(0, TT_FAILED, trace);
  523. return TT_ERR_SESSION;
  524. }
  525. }
  526. return TT_OK;
  527. }
  528. //
  529. // Dispatches a message which means that the message is compared against
  530. // all the ptype and otype signatures to determine whether any signatures
  531. // match. The special case of a point-to-point message (ie. a TT_HANDLER
  532. // message) doesn't require matching against signatures. This method is
  533. // also responsible for verifying some message fields such as verifying
  534. // that the _sender field is valid and setting the _TT_MSG_IS_REMOTE flag
  535. // if the message's session field is not the same as the server's session.
  536. // This method is only called for new messages (see _tt_rpc_dispatch and
  537. // _tt_rpc_dispatch_2 in slib/mp_rpc_implement.C for details of how this
  538. // method is invoked).
  539. //
  540. // Errors (in all cases, ::change_state(TT_FAILED) has been called):
  541. // TT_ERR_PROCID unknown sender or handler
  542. // TT_ERR_SESSION unknown original session
  543. // TT_ERR_PTYPE unknown handler_ptype
  544. // TT_ERR_OTYPE unknown otype
  545. // TT_ERR_SCOPE invalid scope
  546. //
  547. Tt_status _Tt_s_message::
  548. dispatch(const _Tt_msg_trace &trace)
  549. {
  550. Tt_status result;
  551. //
  552. // This message is in TT_CREATED state so set the state to
  553. // TT_SENT since this is a new message. _Tt_c_message::dispatch()
  554. // does the same thing on the client side.
  555. //
  556. Tt_state old_state = state();
  557. set_state(TT_SENT);
  558. result = indoctrinate( trace );
  559. {
  560. // indoctrinate() first, to update _sender
  561. _Tt_msg_trace state_trace( *this, old_state );
  562. }
  563. if (result != TT_OK) {
  564. return result;
  565. }
  566. // now dispatch the message according to its address type.
  567. switch (paradigm()) {
  568. case TT_PROCEDURE:
  569. result = procedural_dispatch( trace );
  570. break;
  571. case TT_OBJECT:
  572. case TT_OTYPE:
  573. result = object_oriented_dispatch( trace );
  574. break;
  575. case TT_HANDLER:
  576. result = handler_dispatch( trace );
  577. break;
  578. case TT_ADDRESS_LAST:
  579. default:
  580. result = TT_ERR_ADDRESS;
  581. break;
  582. }
  583. return result;
  584. }
  585. //
  586. // Called to dispatch a TT_HANDLER message. This type of message is
  587. // special in that it contains the specific handler procid that should
  588. // receive the message. Therefore, we just add the message to the
  589. // procid's undelivered queue, regardless of any pattern matching. If we
  590. // fail, we change the state of the message to TT_FAILED to notify the
  591. // sender of the problem.
  592. // We do check the handler\'s patterns for any matches, just to merge in
  593. // the pattern id so any pattern callbacks can get run.
  594. //
  595. Tt_status _Tt_s_message::
  596. handler_dispatch(const _Tt_msg_trace &trace)
  597. {
  598. _Tt_s_procid_ptr s_handler;
  599. int failed = 0;
  600. if (!(_tt_s_mp->find_proc(_handler, s_handler, 0))) {
  601. failed = 1;
  602. } else {
  603. _handler = s_handler;
  604. _Tt_pattern_list_cursor pcursor(s_handler->patterns());
  605. int best_match = 0;
  606. Tt_category best_category = TT_CATEGORY_UNDEFINED;
  607. unsigned int best_timestamp = 0;
  608. // match against this procid\'s patterns, just to get the
  609. // best matching pattern id in the message. This ultimately
  610. // allows any pattern callbacks to be run back on the client
  611. // side.
  612. while (pcursor.next()) {
  613. // In slib, we know they are _Tt_s_patterns
  614. const _Tt_s_pattern *spat = (const _Tt_s_pattern *)
  615. (*pcursor).c_pointer();
  616. if (match_handler(*spat, trace, best_match,
  617. best_category, best_timestamp))
  618. {
  619. set_pattern_id( pcursor->id() );
  620. }
  621. }
  622. // Even if no patterns match, we still just ram the
  623. // point-to-point message down the handler\'s throat.
  624. if (!s_handler->add_message(this)) {
  625. failed = 1;
  626. }
  627. }
  628. if (failed && (scope() != TT_FILE) && (scope() != TT_BOTH)) {
  629. //
  630. // Message send failed, and since no other session
  631. // will get a chance to find the handler, we fail it now.
  632. //
  633. set_status((int)TT_ERR_PROCID);
  634. change_state(0, TT_FAILED, trace);
  635. return(TT_ERR_PROCID);
  636. } else {
  637. return TT_OK;
  638. }
  639. }
  640. //
  641. // Does the dispatch operation on a message with TT_OBJECT or TT_OTYPE
  642. // address. It assumes the otype for the message is filled in. If this is
  643. // a send super call then we replace the otype in the message with it's
  644. // parent otype. Since we implement multiple-inheritance finding the
  645. // parent otype isn't trivial so we use the
  646. // _Tt_s_message::match_super_sig to determine which otype to use. We
  647. // then call _Tt_s_message::procedural_dispatch to finish the dispatch
  648. // process.
  649. //
  650. Tt_status _Tt_s_message::
  651. object_oriented_dispatch(const _Tt_msg_trace &trace)
  652. {
  653. _Tt_otype_ptr ot;
  654. // verify that the otype field in the message is valid.
  655. ot = _tt_s_mp->otable->lookup(_otype);
  656. if (ot.is_null()) {
  657. // can't find otype def for this otype. This could
  658. // happen if the otype databases are not installed
  659. // properly.
  660. set_status((int)TT_ERR_OTYPE);
  661. change_state(0, TT_FAILED, trace);
  662. return(TT_ERR_OTYPE);
  663. }
  664. // if this is a send super call, we need to replace the otype
  665. if (_flags&(1<<_TT_MSG_IS_SUPER)) {
  666. _Tt_signature_ptr sig;
  667. if (!match_super_sig(ot, sig, trace)) {
  668. set_status((int)TT_ERR_OTYPE);
  669. change_state(0, TT_FAILED, trace);
  670. return(TT_ERR_OTYPE);
  671. }
  672. if (sig->super_otid().is_null()) {
  673. set_status((int)TT_ERR_OTYPE);
  674. change_state(0, TT_FAILED, trace);
  675. return(TT_ERR_OTYPE);
  676. }
  677. _otype = sig->super_otid();
  678. _flags &= ~(1<<_TT_MSG_IS_SUPER);
  679. }
  680. // procedural dispatch will now match against the correct
  681. // handler and observer signatures for this message. Matching
  682. // can't be done in this function because it would cause
  683. // duplicate observer signatures to be matched for this otype.
  684. return(procedural_dispatch( trace ));
  685. }
  686. //
  687. // Compares a message against all ptype and otype signatures to determine
  688. // if there is a match. The method _Tt_s_message::match_signatures does
  689. // the actual work of matching the signatures and modifies the message
  690. // accordingly if there is a match. If the message already has a handler
  691. // ptype filled in then it is verfied to be a valid ptype. Otherwise the
  692. // message is failed.
  693. //
  694. Tt_status _Tt_s_message::
  695. procedural_dispatch(const _Tt_msg_trace &trace)
  696. {
  697. int matched_handler = 0;
  698. // if handler_ptype is filled in then verify it is a valid
  699. // ptype.
  700. if (handler_ptype().len() != 0) {
  701. _Tt_ptype_ptr pt;
  702. if (! _tt_s_mp->ptable->lookup(handler_ptype(), pt)) {
  703. //
  704. // notify sender if necessary of failed request.
  705. //
  706. set_status((int)TT_ERR_PTYPE);
  707. (void)change_state(0, TT_FAILED, trace);
  708. return(TT_ERR_PTYPE);
  709. }
  710. }
  711. // now match the relevant signatures for this matching by
  712. // getting a list of otype and ptype signatures that have the
  713. // same op field as this message.
  714. //
  715. if (_op.len()) {
  716. _Tt_sigs_by_op_ptr so;
  717. if (_tt_s_mp->sigs->lookup(_op,so)) {
  718. (void)match_signatures(so->sigs, trace);
  719. }
  720. }
  721. if (scope() == TT_SCOPE_NONE) {
  722. // dispatch hasn't set the scope of this
  723. // message to a valid scope so return
  724. // this message to sender in an undeliverable
  725. // state. (if it's a request)
  726. if ( _message_class == TT_REQUEST
  727. || _message_class == TT_OFFER)
  728. {
  729. set_status((int)TT_ERR_SCOPE);
  730. change_state(0, TT_FAILED, trace);
  731. }
  732. return(TT_ERR_SCOPE);
  733. }
  734. return(TT_OK);
  735. }
  736. //
  737. // Given a set of signatures, this method iterates through the signatures
  738. // until one is found that matches the message.
  739. //
  740. // The scope, message class, op, otype and args are compared against all
  741. // signatures in each ptype or otype. When a match is found, action
  742. // depends on the pattern category specified:
  743. //
  744. // Handle signatures:
  745. //
  746. // At most one ptype should contain a signature that matches the op and
  747. // args and specifies a handler signature. This should be enforced at
  748. // type compile time.
  749. //
  750. // If a handler ptype is found, then fill in opnum, handler_ptype, and
  751. // reliability from the signature.
  752. //
  753. // Observe signatures:
  754. //
  755. // If the signature specifies queue or start, attach a "observer promise"
  756. // record to the message, specifying the ptype and reliability options.
  757. // This is done for all ptype that contain a matching observe signature.
  758. //
  759. // Returns:
  760. // TT_OK
  761. // TT_ERR_NO_MATCH Did not match a handler
  762. //
  763. Tt_status _Tt_s_message::
  764. match_signatures(_Tt_signature_list_ptr &siglist, const _Tt_msg_trace &trace)
  765. {
  766. _Tt_signature_ptr best_sig;
  767. unsigned int best_timestamp = 0;
  768. Tt_category best_category = TT_CATEGORY_UNDEFINED;
  769. int best_match = 0;
  770. _Tt_signature_list_cursor sigC(siglist);
  771. Tt_disposition sr;
  772. Tt_scope sc;
  773. int so;
  774. while (sigC.next()) {
  775. switch (sigC->category()) {
  776. case TT_HANDLE:
  777. case TT_HANDLE_ROTATE:
  778. case TT_HANDLE_PUSH:
  779. if (match_handler(**sigC, trace, best_match,
  780. best_category, best_timestamp))
  781. {
  782. best_sig = *sigC;
  783. }
  784. break;
  785. case TT_OBSERVE:
  786. if (match_observer(**sigC, trace)) {
  787. // add an observer promise to this message
  788. if (_observers.is_null()) {
  789. _observers = new _Tt_observer_list();
  790. }
  791. so = sigC->opnum();
  792. sr = sigC->reliability();
  793. sc = sigC->scope();
  794. _flags |= (1<<_TT_MSG_OBSERVERS_MATCH);
  795. _observers->push(new _Tt_observer(sigC->ptid(),
  796. so,
  797. sr,
  798. sc));
  799. }
  800. break;
  801. }
  802. }
  803. if (best_sig.is_null()) {
  804. return TT_ERR_NO_MATCH;
  805. }
  806. set_opnum(best_sig->opnum());
  807. set_handler_ptype(best_sig->ptid());
  808. set_reliability(best_sig->reliability());
  809. if (best_sig->otid().len() > 0) {
  810. // for obj-oriented methods,
  811. // fill in scope as well as
  812. // other fields.
  813. set_scope(best_sig->scope());
  814. }
  815. return TT_OK;
  816. }
  817. //
  818. // This method is called when we want to determine the parent otype to
  819. // use for a send super call. Since we implement multiple-inheritance we
  820. // have to attempt a match for all the signatures in the given otype. Any
  821. // signature that matches is returned. This signature will then have a
  822. // super_otid field pointing to the correct parent otype.
  823. //
  824. int _Tt_s_message::
  825. match_super_sig(_Tt_otype_ptr ot, _Tt_signature_ptr &sig,
  826. const _Tt_msg_trace &trace)
  827. {
  828. _Tt_signature_list_cursor sigs;
  829. sigs.reset(ot->hsigs());
  830. while (sigs.next()) {
  831. int was_exact;
  832. if (sigs->match(scope(), _message_class, _op, _args, _otype,
  833. _contexts, &trace, was_exact))
  834. {
  835. sig = *sigs;
  836. return 1;
  837. }
  838. }
  839. sigs.reset(ot->osigs());
  840. while (sigs.next()) {
  841. int was_exact;
  842. if (sigs->match(scope(), _message_class, _op, _args, _otype,
  843. _contexts, &trace, was_exact))
  844. {
  845. sig = *sigs;
  846. return 1;
  847. }
  848. }
  849. return 0;
  850. }
  851. //
  852. // Returns 1 if the given procid has already been attempted as a recipient
  853. // of this message.
  854. //
  855. int _Tt_s_message::
  856. already_tried(const _Tt_procid_ptr &proc)
  857. {
  858. _Tt_procid_list_cursor pcursor(_tried);
  859. while (pcursor.next()) {
  860. if (proc->is_equal(*pcursor)) {
  861. return(1);
  862. }
  863. }
  864. return(0);
  865. }
  866. //
  867. // Load up the environment with the entries that need to be
  868. // set when this message causes a start.
  869. //
  870. Tt_status _Tt_s_message::
  871. set_start_env() const
  872. {
  873. _Tt_msg_context_list_cursor cntxtC( _contexts );
  874. while (cntxtC.next()) {
  875. if (cntxtC->isEnvEntry()) {
  876. if (_tt_putenv( cntxtC->enVarName(),
  877. cntxtC->stringRep() ) == 0)
  878. {
  879. return TT_ERR_NOMEM;
  880. }
  881. }
  882. }
  883. return TT_OK;
  884. }
  885. //
  886. // Deliver the message to a handler and make one copy per observer
  887. // promise, which will get delivered if the original does not
  888. // fulfill the promise.
  889. //
  890. void _Tt_s_message::
  891. deliver_to_observers_and_handlers(const _Tt_msg_trace &trace)
  892. {
  893. // deliver copies of the message to any static observers. Note
  894. // that this is done first before invoking deliver on the
  895. // original message since the process of delivering the
  896. // message to a handler may change its state.
  897. if (!_observers.is_null() && _observers->count()) {
  898. _Tt_observer_list_cursor observers(_observers);
  899. _Tt_s_message_ptr m;
  900. while (observers.next()) {
  901. // make a copy of this message taking any
  902. // relevant fields from this observer.
  903. m = new _Tt_s_message(this, *observers);
  904. //
  905. // Fulfill the promise by deliver()ing this
  906. // copy of the message. It will only match
  907. // patterns created as a result of the relevant
  908. // static signature. If no such pattern exists,
  909. // the signature's disposition will be fulfilled.
  910. //
  911. // XXX holtz 93/09/20 It seems wasteful that
  912. // every pattern should be looked at just to
  913. // find a pattern generated by this observer
  914. // promise. Why not just point from the signature
  915. // to the most-recent pattern instantiating
  916. // it? Indeed, there is not enough info in
  917. // a _Tt_observer to tell which promise it is.
  918. //
  919. m->deliver(trace, 1);
  920. }
  921. }
  922. // Now invoke deliver on the original message to locate any
  923. // handlers and deal with any state transitions to this
  924. // message.
  925. (void)deliver(trace, 1);
  926. count_ballots(_sender, trace);
  927. }
  928. //
  929. // Delivers a message to its intended recipients. This method is
  930. // repeatedly invoked until the message is replied to or rejected in the
  931. // case of a request or sent in the case of a notification.
  932. //
  933. // This method returns 1 if the message was processed without queueing.
  934. //
  935. int _Tt_s_message::
  936. deliver(const _Tt_msg_trace &trace, int deliver_to_observers)
  937. {
  938. if (deliver_to_observers) {
  939. // We mark set the _when_last_matched to be the current
  940. // db key. See _Tt_s_message::change_state to see how
  941. // it is used.
  942. _when_last_matched = _tt_s_mp->now;
  943. }
  944. // Match the message against all relevant patterns, which
  945. // means, all the patterns that contain an op field that
  946. // matches the op field for this message or else patterns that
  947. // don't specify an op field. If most patterns do contain an
  948. // op field then we don't incur a linear scan of all the
  949. // patterns.
  950. _Tt_pattern_list_ptr pats2match;
  951. _Tt_s_pattern_ptr best_pattern;
  952. _Tt_procid_ptr handler_procid;
  953. _Tt_s_procid_ptr dummy;
  954. int found_observer = 0;
  955. int best_match = 0;
  956. _Tt_patlist_ptr opful_pats = _tt_s_mp->opful_pats->lookup(_op);
  957. if (opful_pats.is_null()) {
  958. pats2match = _tt_s_mp->opless_pats;
  959. } else {
  960. if (_tt_s_mp->opless_pats->count() > 0) {
  961. //
  962. // XXX The price you pay for opless patterns:
  963. // we create a new list and copy both lists into it.
  964. //
  965. pats2match =
  966. new _Tt_pattern_list( *_tt_s_mp->opless_pats );
  967. pats2match->append( opful_pats->patterns );
  968. } else {
  969. pats2match = opful_pats->patterns;
  970. }
  971. }
  972. if (! pats2match.is_null()) {
  973. found_observer = match_patterns( pats2match,
  974. trace, best_pattern,
  975. deliver_to_observers);
  976. }
  977. if (! best_pattern.is_null()) {
  978. handler_procid = best_pattern->procid();
  979. if (best_pattern->category() == TT_HANDLE_ROTATE) {
  980. best_pattern->set_timestamp( _tt_s_mp->now );
  981. }
  982. }
  983. // now we're done pattern matching so we try to deliver the
  984. // message to any handlers or deal with the case where nobody
  985. // handled the message (in the case of requests) or observed
  986. // the message (in the case of notifications).
  987. if (! is_handler_copy()) {
  988. // message represents an observer promise
  989. if (found_observer) {
  990. // promise will be fulfilled
  991. return(1);
  992. } else {
  993. handle_no_recipients( trace );
  994. return 0;
  995. }
  996. } else if (! handler_procid.is_null()) {
  997. // a handler was found for the message
  998. // deliver to handler
  999. set_handler_procid(handler_procid);
  1000. // always give requests to handlers in
  1001. // TT_SENT state.
  1002. set_state(TT_SENT);
  1003. if (! ((_Tt_s_procid *)handler_procid.c_pointer())->add_message(this)) {
  1004. // rematch because this
  1005. // procid can't receive messages
  1006. //
  1007. // XXX: rather than doing a recursive
  1008. // call, keep a list of the best matches
  1009. // in sorted order and just go down the list
  1010. // until one of them succeeds.
  1011. return(deliver(trace, 0));
  1012. } else {
  1013. return(1);
  1014. }
  1015. } else if ( (paradigm() == TT_HANDLER)
  1016. && (! _handler.is_null())
  1017. && (_tt_s_mp->find_proc(_handler, dummy, 0)))
  1018. {
  1019. //
  1020. // XXX Do nothing; the message was already delivered
  1021. // in handler_dispatch(). handler_dispatch() should
  1022. // probably set the state, or better yet, let the
  1023. // delivery happen here instead of there. This
  1024. // is really gross.
  1025. //
  1026. } else if ((_message_class == TT_REQUEST &&
  1027. (_state == TT_SENT ||
  1028. _state == TT_CREATED ||
  1029. _state == TT_STARTED ))
  1030. ||
  1031. ( ( _message_class == TT_NOTICE
  1032. || _message_class == TT_OFFER)
  1033. && (start() || queue()))
  1034. ||
  1035. (paradigm() == TT_HANDLER)) {
  1036. // Either this message is a request in a non-final
  1037. // state, or it is a notice that needs to be queued or
  1038. // started for a static handler, or it is a point-to-point
  1039. // message whose handler is not in this session
  1040. handle_no_recipients( trace );
  1041. return(0);
  1042. }
  1043. return(1);
  1044. }
  1045. //
  1046. // Matches the message against each pattern in "patterns". Uses the
  1047. // methods _Tt_s_message::match_handler and _Tt_s_message::match_observer
  1048. // to match handler and observer patterns respectively.
  1049. // best_pattern is set to the best handler pattern that matched.
  1050. //
  1051. // If "deliver_to_observers" is 1 then delivery is attempted for observer
  1052. // patterns.
  1053. //
  1054. int _Tt_s_message::
  1055. match_patterns(_Tt_pattern_list_ptr &patterns, const _Tt_msg_trace &trace,
  1056. _Tt_pattern_ptr &best_pattern, int deliver_to_observers)
  1057. {
  1058. int found_observer = 0;
  1059. unsigned int best_timestamp = 0;
  1060. Tt_category best_category = TT_CATEGORY_UNDEFINED;
  1061. int best_match = 0;
  1062. _Tt_pattern_list_cursor pcursor(patterns);
  1063. //
  1064. // Point-to-point messages aren't pattern-matched.
  1065. //
  1066. if (paradigm() == TT_HANDLER) {
  1067. return 0;
  1068. }
  1069. while (pcursor.next()) {
  1070. _Tt_s_procid_ptr registrant = (_Tt_s_procid *)
  1071. pcursor->procid().c_pointer();
  1072. if (registrant.is_null()) {
  1073. return(0);
  1074. }
  1075. if (! registrant->is_active()) {
  1076. return(0);
  1077. }
  1078. const _Tt_s_pattern *spat;
  1079. switch (pcursor->category()) {
  1080. case TT_HANDLE:
  1081. case TT_HANDLE_ROTATE:
  1082. case TT_HANDLE_PUSH:
  1083. if (! is_handler_copy()) {
  1084. // Can only handle original, not copies
  1085. continue;
  1086. }
  1087. if ( (_flags&(1<<_TT_MSG_OBSERVERS_ONLY))
  1088. || state() != TT_SENT)
  1089. {
  1090. // Not looking for a handler
  1091. continue;
  1092. }
  1093. if ( (! _tried.is_null()) && (_tried->count() > 0)
  1094. && already_tried(registrant))
  1095. {
  1096. // You had your chance, bub
  1097. continue;
  1098. }
  1099. // In slib, we know they are _Tt_s_patterns
  1100. spat = (const _Tt_s_pattern *)(*pcursor).c_pointer();
  1101. if (match_handler(*spat, trace, best_match,
  1102. best_category, best_timestamp))
  1103. {
  1104. best_pattern = *pcursor;
  1105. }
  1106. break;
  1107. case TT_OBSERVE:
  1108. // In slib, we know they are _Tt_s_patterns
  1109. spat = (const _Tt_s_pattern *)(*pcursor).c_pointer();
  1110. if (deliver_to_observers) {
  1111. // XXX: duplicates might get delivered in the
  1112. // case of file-scope messages. This needs to
  1113. // be fixed!
  1114. found_observer += match_observer(*spat,
  1115. registrant, trace);
  1116. }
  1117. break;
  1118. default:
  1119. continue;
  1120. }
  1121. }
  1122. if (! best_pattern.is_null()) {
  1123. set_pattern_id( best_pattern->id() );
  1124. _tt_s_mp->now++;
  1125. }
  1126. return found_observer;
  1127. }
  1128. static int
  1129. _tt_excludes(Tt_category best_category, Tt_category curr_category)
  1130. {
  1131. switch (curr_category) {
  1132. case TT_HANDLE:
  1133. if (best_category == TT_HANDLE_ROTATE) {
  1134. return 1;
  1135. }
  1136. // fall through
  1137. case TT_HANDLE_ROTATE:
  1138. if (best_category == TT_HANDLE_PUSH) {
  1139. return 1;
  1140. }
  1141. }
  1142. return 0;
  1143. }
  1144. static int
  1145. _tt_excludes(Tt_category best_category, int best_match,
  1146. unsigned int best_timestamp,
  1147. Tt_category category, int score, int timestamp)
  1148. {
  1149. switch (category) {
  1150. case TT_HANDLE_PUSH:
  1151. switch (best_category) {
  1152. case TT_HANDLE_PUSH:
  1153. if (best_match > score) {
  1154. return 0;
  1155. }
  1156. if ( (best_match == score)
  1157. && (best_timestamp >= timestamp))
  1158. {
  1159. // Newest PUSH pattern wins
  1160. return 1;
  1161. }
  1162. break;
  1163. case TT_HANDLE_ROTATE:
  1164. case TT_HANDLE:
  1165. default:
  1166. if (score <= 0) {
  1167. // Matching PUSH pattern trumps all
  1168. return 1;
  1169. }
  1170. break;
  1171. }
  1172. break;
  1173. case TT_HANDLE_ROTATE:
  1174. switch (best_category) {
  1175. case TT_HANDLE_ROTATE:
  1176. if (best_match > score) {
  1177. return 1;
  1178. }
  1179. if ( (best_match == score)
  1180. && (best_category == TT_HANDLE_ROTATE)
  1181. && (best_timestamp < timestamp))
  1182. {
  1183. // Coldest ROTATE pattern wins
  1184. return 1;
  1185. }
  1186. break;
  1187. case TT_HANDLE:
  1188. if (score <= 0) {
  1189. // Matching ROTATE trumps HANDLE
  1190. return 1;
  1191. }
  1192. break;
  1193. }
  1194. break;
  1195. case TT_HANDLE:
  1196. // best_category is either TT_HANDLE or unset
  1197. if (best_match >= score) {
  1198. return 1;
  1199. }
  1200. }
  1201. return 0;
  1202. }
  1203. //
  1204. // Match the message against the given handler pattern. "best_match"
  1205. // points to the current best matching score for this message. If "pat"
  1206. // gets a higher score when matching this message than "best_match" then
  1207. // this method returns 1 and sets "best_match" to the new best score.
  1208. // Otherwise, 0 is returned.
  1209. //
  1210. int _Tt_s_message::
  1211. match_handler(const _Tt_s_pattern &pat, const _Tt_msg_trace &trace,
  1212. int &best_match, Tt_category &best_category,
  1213. unsigned int &best_timestamp) const
  1214. {
  1215. if (_tt_excludes(best_category, pat.category())) {
  1216. return 0;
  1217. }
  1218. int score = pat.match(*this, trace);
  1219. if (score <= 0) {
  1220. return 0;
  1221. }
  1222. if (_tt_excludes(best_category, best_match, best_timestamp,
  1223. pat.category(), score, pat.timestamp()))
  1224. {
  1225. return 0;
  1226. }
  1227. best_match = score;
  1228. best_category = pat.category();
  1229. best_timestamp = pat.timestamp();
  1230. return 1;
  1231. }
  1232. int _Tt_s_message::
  1233. match_handler(const _Tt_signature &sig, const _Tt_msg_trace &trace,
  1234. int &best_match, Tt_category &best_category,
  1235. unsigned int &best_timestamp) const
  1236. {
  1237. if (_tt_excludes(best_category, sig.category())) {
  1238. return 0;
  1239. }
  1240. int was_exact;
  1241. int score = sig.match(scope(), _message_class, _op,
  1242. _args, _otype, _contexts, &trace, was_exact);
  1243. if (score <= 0) {
  1244. return 0;
  1245. }
  1246. if (_tt_excludes(best_category, best_match, best_timestamp,
  1247. sig.category(), score, sig.timestamp()))
  1248. {
  1249. return 0;
  1250. }
  1251. best_match = score;
  1252. best_category = sig.category();
  1253. best_timestamp = sig.timestamp();
  1254. return 1;
  1255. }
  1256. //
  1257. // Match the message against the given observer pattern. "proc" points
  1258. // to the procid that registered the pattern. If the pattern matches,
  1259. // then this message is immediately put on
  1260. // "proc"'s undelivered messages queue using the
  1261. // _Tt_s_procid::add_message method.
  1262. //
  1263. int _Tt_s_message::
  1264. match_observer(const _Tt_s_pattern &pat, const _Tt_s_procid_ptr &proc,
  1265. const _Tt_msg_trace &trace)
  1266. {
  1267. // match against observer patterns
  1268. if (pat.match(*this, trace) > 0) {
  1269. _Tt_s_message_ptr mcopy;
  1270. // if there is no observer field then we have to
  1271. // create a copy. Otherwise this already is a copy.
  1272. if (_observer.is_null()) {
  1273. mcopy = new _Tt_s_message(this, _observer);
  1274. } else {
  1275. mcopy = this;
  1276. }
  1277. mcopy->set_pattern_id(pat.id());
  1278. if (proc->add_message(mcopy)) {
  1279. _flags |= (1<<_TT_MSG_OBSERVERS_MATCH);
  1280. return(1);
  1281. }
  1282. }
  1283. return(0);
  1284. }
  1285. int _Tt_s_message::
  1286. match_observer(const _Tt_signature &sig, const _Tt_msg_trace &trace)
  1287. {
  1288. int was_exact;
  1289. return sig.match(scope(), _message_class, _op,
  1290. _args, _otype, _contexts, &trace, was_exact) >= 0;
  1291. }
  1292. //
  1293. // Delegate responsibility for finding a handler to the sessions in
  1294. // _rsessions. Returns:
  1295. // TT_OK successful delegation
  1296. // TT_ERR_SESSION no more sessions
  1297. //
  1298. Tt_status _Tt_s_message::
  1299. hdispatch()
  1300. {
  1301. _Tt_message_ptr m = this;
  1302. _Tt_string_list_cursor rc( _rsessions );
  1303. _Tt_string init_rc;
  1304. _Tt_session_ptr rs;
  1305. while (rc.next()) {
  1306. init_rc = *rc;
  1307. rc.remove();
  1308. if (_tt_s_mp->initial_session->address_string() == init_rc) {
  1309. continue;
  1310. }
  1311. if (TT_OK != _tt_s_mp->find_session(init_rc,rs,1)) {
  1312. continue;
  1313. }
  1314. Tt_status status = rs->call(TT_RPC_HDISPATCH,
  1315. (xdrproc_t)tt_xdr_message,
  1316. (char *)&m,
  1317. (xdrproc_t)xdr_void,
  1318. (char *)0);
  1319. if (status == TT_OK) {
  1320. //
  1321. // Flush the list of remote sessions, so that
  1322. // we will not retry these sessions if
  1323. // responsibility gets bucked back around to us.
  1324. // [See _tt_rpc_hupdate_msg().]
  1325. //
  1326. _rsessions->flush();
  1327. return TT_OK;
  1328. }
  1329. }
  1330. return TT_ERR_SESSION;
  1331. }
  1332. //
  1333. // This method is invoked when disposition options for the message need
  1334. // to be honored either because no handler was found for the message or
  1335. // there is a static observer that wants start or queue reliability for
  1336. // this message.
  1337. //
  1338. // The general mechanism is to use _Tt_s_message::change_state to change
  1339. // the state of the message to TT_STARTED or TT_QUEUED as appropiate. The
  1340. // exception is for file-scoped messages which are handled somewhat
  1341. // differently. If we are in the native session
  1342. // then we first attempt to forward the message to one
  1343. // of the remote sessions mentioned in the _rsessions field in the
  1344. // message (this field is set on the client side in the
  1345. // _Tt_c_message::dispatch method). If none of the remote sessions
  1346. // takes responsibility for the message, or ! try_rsessions, then we
  1347. // honor reliability options for the message as if were a
  1348. // non-file-scoped message.
  1349. //
  1350. void _Tt_s_message::
  1351. handle_no_recipients(const _Tt_msg_trace &trace)
  1352. {
  1353. if (_flags&(1<<_TT_MSG_OBSERVERS_ONLY)) {
  1354. //
  1355. // Disposition is not performed during inter-scope
  1356. // observation phase. Disposition is only performed
  1357. // by the native session, during handler-dispatch phase.
  1358. //
  1359. return;
  1360. }
  1361. if ( ((scope()==TT_FILE) || (scope()==TT_BOTH))
  1362. && is_handler_copy())
  1363. {
  1364. if (hdispatch() == TT_OK) {
  1365. // We have passed the buck.
  1366. return;
  1367. }
  1368. if (_flags&(1<<_TT_MSG_IS_REMOTE)) {
  1369. //
  1370. // We are the last session tried, so
  1371. // fail it, even if it is a notice.
  1372. // Native session will perform disposition.
  1373. //
  1374. set_status((int)TT_ERR_NO_MATCH);
  1375. change_state(0, TT_FAILED, trace);
  1376. return;
  1377. }
  1378. }
  1379. // We're here if the message is non-file-scoped or if no
  1380. // remote session would take responsibility for the message
  1381. if (start() || queue()) {
  1382. int reliability_attempted = 0;
  1383. // if the message has start disposition then change its state
  1384. // to TT_STARTED.
  1385. // rfm 28 Sept 1992: Used to bypass this if state had
  1386. // already been through TT_STARTED, apparently on
  1387. // the theory that we didn\'t need to do this again.
  1388. // But, there is a legitimate reason to be redelivering
  1389. // messages already in TT_STARTED state, if they were
  1390. // blocked on the ptype waiting for proc_replied
  1391. // to happen. In that case the extra check
  1392. // that caused the code at the end of this
  1393. // block to see reliablity_attempted as 0 and conclude
  1394. // that the message should be failed for lack of
  1395. // a handler.
  1396. if (start()) {
  1397. if (change_state(0, TT_STARTED, trace) != TT_OK) {
  1398. // now set reliability to TT_DISCARD
  1399. // because starting can't succeed
  1400. // for this message.
  1401. set_reliability(TT_DISCARD);
  1402. set_status((int)TT_ERR_PTYPE_START);
  1403. change_state(0, TT_FAILED, trace);
  1404. return;
  1405. } else {
  1406. reliability_attempted = 1;
  1407. }
  1408. }
  1409. // if the message has queue disposition and it hasn't
  1410. // gone to the TT_QUEUED state then change its state
  1411. // to TT_QUEUED.
  1412. // XXX: I don\'t think this has the same problem as above,
  1413. // since once a process declares a ptype it gets all the
  1414. // queued messages offered to it. If the process
  1415. // doesn\'t handle it, requeuing it is pointless \(while
  1416. // doing a start is meaningful, the process might be designed
  1417. // to start, do one message, and quit.\) \[ Queued
  1418. // requests are kind of silly anyway.\] rfm 28 Sept 1992
  1419. if (queue() && !(_state_reported&(1<<TT_QUEUED))) {
  1420. if (change_state(0, TT_QUEUED, trace) != TT_OK) {
  1421. change_state(0, TT_FAILED, trace);
  1422. return;
  1423. } else {
  1424. reliability_attempted = 1;
  1425. }
  1426. }
  1427. // if we didn't honor reliability options then we fail
  1428. // the message with the appropiate "no match found"
  1429. // status code.
  1430. if (! reliability_attempted) {
  1431. set_status((int)TT_ERR_NO_MATCH);
  1432. change_state(0, TT_FAILED, trace);
  1433. }
  1434. } else if (is_handler_copy()) {
  1435. set_status((int)TT_ERR_NO_MATCH);
  1436. change_state(0, TT_FAILED, trace);
  1437. }
  1438. }
  1439. //
  1440. // This method is invoked to determine if any of the static observers of
  1441. // this message require file-scope queueing. For each static observer
  1442. // that requires queueing we add the ptype that requires the message
  1443. // queued to the _Tt_qmsg_info data structure.
  1444. //
  1445. void _Tt_s_message::
  1446. qmsg_info(_Tt_qmsg_info_ptr &qm)
  1447. {
  1448. // XXX what about TT_BOTH? Do we queue them?
  1449. if (_scope == TT_FILE && queue() && _handler_ptype.len()) {
  1450. // XXX: return null list since file-scope queued
  1451. // requests are not implemented.
  1452. qm = (_Tt_qmsg_info *)0;
  1453. return;
  1454. }
  1455. if (!_observers.is_null() && _observers->count() > 0) {
  1456. _Tt_observer_list_cursor observers(_observers);
  1457. while (observers.next()) {
  1458. if (observers->scope() == TT_FILE &&
  1459. observers->reliability() & TT_QUEUE) {
  1460. if (qm.is_null()) {
  1461. qm = new _Tt_qmsg_info;
  1462. qm->m_id = _id;
  1463. qm->sender = _sender->id();
  1464. }
  1465. qm->categories->push(new _Tt_int_rec((int)TT_OBSERVE));
  1466. qm->ptypes->push(observers->ptid());
  1467. }
  1468. }
  1469. }
  1470. }
  1471. //
  1472. // Removes any reference to the given procid contained in this message.
  1473. // This is typically done when the procid has exited and we want to
  1474. // remove any reference to it in the system so its storage can be
  1475. // reclaimed.
  1476. //
  1477. void _Tt_s_message::
  1478. remove_procid(const _Tt_procid_ptr &p)
  1479. {
  1480. if (! _tried.is_null() && _tried->count()) {
  1481. _Tt_procid_list_cursor procs;
  1482. procs.reset(_tried);
  1483. while (procs.next()) {
  1484. if (procs->is_equal(p)) {
  1485. procs.remove();
  1486. break;
  1487. }
  1488. }
  1489. }
  1490. }
  1491. //
  1492. // Returns the scope of the message (returns observer's scope if
  1493. // present).
  1494. //
  1495. Tt_scope _Tt_s_message::
  1496. scope() const
  1497. {
  1498. if (_observer.is_null()) {
  1499. return(_scope);
  1500. } else {
  1501. return(_observer->scope());
  1502. }
  1503. }
  1504. //
  1505. // Returns the opnum of the message or the opnum of its static observer
  1506. // if present.
  1507. //
  1508. int _Tt_s_message::
  1509. opnum() const
  1510. {
  1511. if (_observer.is_null()) {
  1512. return(_opnum);
  1513. } else {
  1514. return(_observer->opnum());
  1515. }
  1516. }
  1517. //
  1518. // Returns the message's handler_ptype or the ptype of the static
  1519. // observer if present.
  1520. //
  1521. const _Tt_string & _Tt_s_message::
  1522. handler_ptype() const
  1523. {
  1524. if (_observer.is_null()) {
  1525. return(_handler_ptype);
  1526. } else {
  1527. return(_observer->ptid());
  1528. }
  1529. }
  1530. //
  1531. // Returns the message's reliability field (which represents the
  1532. // disposition of the message.). If this message has a static observer
  1533. // then the disposition of the observer is returned.
  1534. //
  1535. Tt_disposition _Tt_s_message::
  1536. reliability() const
  1537. {
  1538. if (_observer.is_null()) {
  1539. return(_reliability);
  1540. } else {
  1541. return(_observer->reliability());
  1542. }
  1543. }
  1544. //
  1545. // Sets the state of a message. If the value is not the default TT_SENT
  1546. // value then the appropiate field in _full_msg_guards is turned on. If
  1547. // the message has an attached static observer then we just set the state
  1548. // for the observer.
  1549. //
  1550. Tt_status _Tt_s_message::
  1551. set_state(Tt_state state)
  1552. {
  1553. if (_observer.is_null()) {
  1554. _state = state;
  1555. SET_GUARD(_full_msg_guards,_state != TT_SENT,_TT_MSK_STATE);
  1556. } else {
  1557. _observer->set_state(state);
  1558. }
  1559. return(TT_OK);
  1560. }
  1561. //
  1562. // Sets the scope of a message. If the value is not the default
  1563. // TT_SESSION value then we turn on the appropiate field in
  1564. // _full_msg_guards. If there is an attached static observer then we just
  1565. // set the scope for the observer.
  1566. //
  1567. Tt_status _Tt_s_message::
  1568. set_scope(Tt_scope s)
  1569. {
  1570. if (_observer.is_null()) {
  1571. _scope = s;
  1572. if (_tt_global->xdr_version() > 1) {
  1573. // version 1 tooltalk clients didn't set the
  1574. // default scope properly so always send them
  1575. // the scope value.
  1576. //
  1577. SET_GUARD(_full_msg_guards,
  1578. _scope != TT_SESSION,_TT_MSK_SCOPE);
  1579. }
  1580. } else {
  1581. _observer->set_scope(s);
  1582. }
  1583. return(TT_OK);
  1584. }
  1585. //
  1586. // Sets the reliability (disposition) of a message. If the value is
  1587. // not the default TT_DISCARD value then we turn on the appropiate
  1588. // field in _full_msg_guards. If there is an attached static observer
  1589. // then we just set the disposition for the observer.
  1590. //
  1591. Tt_status _Tt_s_message::
  1592. set_reliability(Tt_disposition r)
  1593. {
  1594. if (_observer.is_null()) {
  1595. _reliability = r;
  1596. SET_GUARD(_full_msg_guards,
  1597. _reliability != TT_DISCARD, _TT_MSK_RELIABILITY);
  1598. } else {
  1599. _observer->set_reliability(r);
  1600. }
  1601. return(TT_OK);
  1602. }
  1603. //
  1604. // Sets the state of the message or the state of the static observer if
  1605. // present.
  1606. //
  1607. Tt_state _Tt_s_message::
  1608. state() const
  1609. {
  1610. if (_observer.is_null()) {
  1611. return(_state);
  1612. } else {
  1613. return(_observer->state());
  1614. }
  1615. }
  1616. void _Tt_s_message::
  1617. add_eligible_voter(const _Tt_procid_ptr &)
  1618. {
  1619. if (_message_class != TT_OFFER) {
  1620. return;
  1621. }
  1622. _Tt_s_message_ptr orig = this;
  1623. while (! orig->_original.is_null()) {
  1624. orig = orig->_original;
  1625. }
  1626. orig->_num_recipients_yet_to_vote++;
  1627. }
  1628. Tt_status _Tt_s_message::
  1629. add_voter(const _Tt_procid_ptr &voter, Tt_state vote,
  1630. const _Tt_msg_trace &trace)
  1631. {
  1632. if (_message_class != TT_OFFER) {
  1633. return TT_OK;
  1634. }
  1635. switch (vote) {
  1636. case TT_ACCEPTED:
  1637. case TT_REJECTED:
  1638. case TT_ABSTAINED:
  1639. break;
  1640. default:
  1641. // Not a vote; bail out.
  1642. return TT_OK;
  1643. }
  1644. if (! voter->processing( *this )) {
  1645. return TT_OK;
  1646. }
  1647. //
  1648. // This is probably just a copy given to an observer.
  1649. // Backtrack to the sender's original copy, which we
  1650. // save on the sender's _delivered list.
  1651. //
  1652. _Tt_s_message_ptr orig = this;
  1653. while (! orig->_original.is_null()) {
  1654. orig = orig->_original;
  1655. }
  1656. Tt_status status = orig->_Tt_message::add_voter( voter, vote );
  1657. if (status != TT_OK) {
  1658. return status;
  1659. }
  1660. orig->_num_recipients_yet_to_vote--;
  1661. count_ballots( voter, trace );
  1662. return TT_OK;
  1663. }
  1664. Tt_status _Tt_s_message::
  1665. count_ballots(const _Tt_procid_ptr &last_voter, const _Tt_msg_trace &trace)
  1666. {
  1667. if (_message_class != TT_OFFER) {
  1668. return TT_OK;
  1669. }
  1670. //
  1671. // This is probably just a copy given to an observer.
  1672. // Backtrack to the sender's original copy, which we
  1673. // save on the sender's _delivered list.
  1674. //
  1675. _Tt_s_message_ptr orig = this;
  1676. while (! orig->_original.is_null()) {
  1677. orig = orig->_original;
  1678. }
  1679. if (orig->_num_recipients_yet_to_vote <= 0) {
  1680. orig->change_state( last_voter, TT_RETURNED, trace );
  1681. }
  1682. return TT_OK;
  1683. }