123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- //%% (c) Copyright 1993, 1994 Hewlett-Packard Company
- //%% (c) Copyright 1993, 1994 International Business Machines Corp.
- //%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
- //%% (c) Copyright 1993, 1994 Novell, Inc.
- //%% $XConsortium: mp_s_pattern.C /main/3 1995/10/23 11:57:37 rswiston $
- /*
- * @(#)mp_s_pattern.C 1.27 93/09/07
- *
- * mp_s_pattern.cc
- *
- * Copyright (c) 1990, 1992 by Sun Microsystems, Inc.
- */
- #include "mp_s_global.h"
- #include "mp/mp_arg.h"
- #include "mp_s_pat_context.h"
- #include "mp/mp_mp.h"
- #include "mp_s_mp.h"
- #include "mp_s_pattern.h"
- #include "mp_s_message.h"
- #include "mp_signature.h"
- #include "mp_observer.h"
- #include "mp_ptype.h"
- #include "mp_rpc_implement.h"
- #include "mp_s_session.h"
- #include "mp/mp_xdr_functions.h"
- #include "util/tt_enumname.h"
- #include "mp/mp_trace.h"
- #include "util/tt_global_env.h"
- #include "util/tt_assert.h"
- //
- // Creates a pattern from a signature object by extracting the relevant
- // fields from the signature.
- //
- _Tt_s_pattern::
- _Tt_s_pattern(const _Tt_signature_ptr &sig)
- {
- _timestamp = 0;
- set_id(_tt_s_mp->initial_session->address_string());
- set_category(sig->category());
- add_scope(sig->scope());
- add_op(sig->op());
- if (sig->opnum() != -1) {
- add_opnum(sig->opnum());
- }
- if (sig->category()!=TT_OBSERVE) {
- add_handler_ptype(sig->ptid());
- }
- if (sig->otid().len() > 0) {
- add_otype(sig->otid());
- add_paradigm(TT_OTYPE);
- add_paradigm(TT_OBJECT);
- } else {
- add_paradigm(TT_PROCEDURE);
- }
- add_reliability(sig->reliability());
- add_message_class(sig->message_class());
- // We share the arg list from the signature
- // by just assigning the pointer and letting the ref-counting
- // system do its thing. Conceivably, this might cause
- // consternation if we ever let clients update patterns created
- // from signatures, since updating the arg list would change
- // the in-memory copy of the signature and every other pattern
- // generated from the signature! However, the most likely
- // way such updates would be generated would be to send a whole
- // new pattern over from the client, so sharing the arg list
- // wouldn\'t cause trouble.
- _args = sig->args();
- // We *cannot* share the context list from the signature as
- // the signature contains plain _Tt_context entries, while
- // the pattern should contain _Tt_pat_context entries.
- _Tt_context_list_cursor c(sig->contexts());
- while (c.next()) {
- _Tt_pat_context_ptr nc = new _Tt_pat_context(**c);
- add_context(nc);
- }
- }
- _Tt_s_pattern::_Tt_s_pattern ()
- {
- _timestamp = 0;
- }
- _Tt_s_pattern::~_Tt_s_pattern ()
- {
- }
- //
- // Matches a pattern with a message and returns a number indicating how
- // well the pattern matches the message. 0 indicates no match whereas a
- // positive number indicates some level of matching. The greater the
- // level, the "better" the pattern matches the message. A level of 1
- // indicates all the pattern fields are wildcards so this is the minimum
- // level of matching. Any level greater than 1 is controlled by the
- // number returned from each field match. Thus twiddling these numbers
- // gives some control as to what field matches are to be considered more
- // important than others. Presently, the algorithm for selecting match
- // numbers is that wildcard matches count as 0 whereas any specific match
- // counts as 1. The total is added up for each field and returned as the
- // value of the match. The variable tm below holds the total count of
- // matches. It is initially 1 because wildcard matches don't increment
- // it. In any submethod called to do matching the variable tm is passed
- // to the method to be incremented.
- //
- int _Tt_s_pattern::
- match(const _Tt_s_message &msg, const _Tt_msg_trace &trace) const
- {
- int tm = 1;
- if (msg.is_handler_copy()) {
- // message is the original
- if ( (! _generating_ptype.is_null())
- && (category() == TT_OBSERVE))
- {
- //
- // A static observer pattern can only match
- // the message copy promised to it,
- // and cannot match the original.
- //
- return 0;
- }
- } else {
- // message is a copy promised to observer ptype
- if ( (_generating_ptype.is_null())
- || ( msg.observer()->ptid()
- != _generating_ptype->ptid()))
- {
- //
- // If this pattern is not owned by the
- // promised ptype, or is owned by no
- // ptype, then this pattern cannot
- // fulfill the promise.
- //
- return 0;
- }
- }
- trace << "Tt_message & Tt_pattern {\n";
- trace.incr_indent();
- trace << "timestamp:\t" << _timestamp << "\n";
- trace << *this;
- trace.decr_indent();
- trace << "} ";
- // The code for this method is quite repetitive. For each
- // field, the list is checked to see if there are any values. If
- // there are and the appropiate match method returns 0 then the
- // pattern fails to match. The only exception is match_scopes
- // which defaults to not matching if there are no values specified.
- // This function used to not match the op field of the
- // message, because in the usual code path it is
- // hashed on the basis of the op field so it would be
- // redundant to check the op field here. However, when
- // matching TT_HANDLER messages just to get callbacks run,
- // this is not the case. To save a little time, we skip
- // the op check if the message paradigm is not TT_HANDLER,
- // even though that looks really funny here!
- if (0 != _ops->count()) {
- if (msg.paradigm() == TT_HANDLER &&
- ! match_field(msg.op(), _ops,
- tm, trace, "op" ))
- {
- return(0);
- }
- tm++;
- }
- if (_reliabilities != 0) {
- if (!(_reliabilities&(1<<msg.reliability()))) {
- trace << "== 0; /* Tt_disposition */\n";
- return(0);
- }
- tm++;
- }
- if (_states != 0) {
- if (!(_states&(1<<msg.state()))) {
- trace << "== 0; /* Tt_state */\n";
- return(0);
- }
- tm++;
- }
- if (_classes != 0) {
- if (!(_classes&(1<<TT_CLASS_UNDEFINED))
- && !(_classes&(1<< msg.message_class()))) {
- trace << "== 0; /* Tt_class */\n";
- return(0);
- }
- tm++;
- }
- if (_paradigms != 0) {
- if (!(_paradigms&(1<<msg.paradigm()))) {
- trace << "== 0; /* Tt_address */\n";
- return(0);
- }
- tm++;
- }
- if (_handlers->count()) {
- _Tt_string h;
- if (! msg.handler().is_null()) {
- h = msg.handler()->id();
- }
- if (! match_field(h, _handlers, tm, trace, "handler")) {
- return(0);
- }
- }
- if (_handler_ptypes->count() &&
- ! match_field(msg.handler_ptype(), _handler_ptypes,
- tm, trace, "handler_ptype" ))
- {
- return(0);
- }
- if (! match_scopes(msg, tm, trace)) {
- return(0);
- }
- if (msg.scope() == TT_SESSION) {
- if (_files->count() &&
- ! match_field(msg.file(), _files,
- tm, trace, "file"))
- {
- return(0);
- }
- }
- if (_objects->count() &&
- ! match_field(msg.object(), _objects,
- tm, trace, "object"))
- {
- return(0);
- }
- if (_otypes->count() &&
- ! match_field(msg.otype(), _otypes,
- tm, trace, "otype"))
- {
- return(0);
- }
- if (_senders->count() &&
- ! match_field(msg.sender()->id(), _senders,
- tm, trace, "sender"))
- {
- return(0);
- }
- if (_sender_ptypes->count() &&
- ! match_field(msg.sender_ptype(), _sender_ptypes,
- tm, trace, "sender_ptype"))
- {
- return(0);
- }
- if (_args->count() && ! match_args(msg, tm, trace)) {
- return(0);
- }
- if (! match_contexts(msg, tm, trace)) {
- return(0);
- }
- trace << "== " << tm << ";\n";
- return(tm);
- }
- //
- // Generic matching function for lists of integers. If the given pattern
- // values, pvals, is empty then 0 is returned indicating a mismatch.
- // Otherwise, 1 is returned if "val" is in the list and the variable tm
- // is incremented to update the matching score in _Tt_pattern::match.
- //
- int _Tt_s_pattern::
- match_field(int val, const _Tt_int_rec_list_ptr &pvals, int &tm,
- const _Tt_msg_trace &trace, const char *failure_note) const
- {
- _Tt_int_rec_list_cursor c(pvals);
- while (c.next()) {
- if (val == c->val) {
- tm++;
- return(1);
- }
- }
- if (failure_note != 0) {
- trace << "== 0; /* " << failure_note << " */\n";
- }
- return(0);
- }
- //
- // Generic matching function for lists of strings. If the given pattern
- // values, pvals, is empty then 0 is returned indicating a mismatch.
- // Otherwise, 1 is returned if "val" is in the list and the variable tm
- // is incremented to update the matching score in _Tt_pattern::match.
- //
- int _Tt_s_pattern::
- match_field(const _Tt_string &val, const _Tt_string_list_ptr &pvals,
- int &tm, const _Tt_msg_trace &trace,
- const char *failure_note) const
- {
- _Tt_string_list_cursor c(pvals);
- if (val.len() != 0) {
- while (c.next()) {
- if (val == *c) {
- tm++;
- return(1);
- }
- }
- }
- if (failure_note != 0) {
- trace << "== 0; /* " << failure_note << " */\n";
- }
- return(0);
- }
- //
- // Matches the scope of the message with the pattern scopes. For the
- // different scopes, matching is defined differently as specified below.
- //
- int _Tt_s_pattern::
- match_scopes(const _Tt_message &msg, int &tm,
- const _Tt_msg_trace &trace) const
- {
- Tt_scope s = msg.scope();
- int valid_scope_mask = 0;
- int rval;
- ASSERT(TT_SCOPE_NONE==0 && TT_SESSION==1 && TT_FILE==2 &&
- TT_BOTH==3 && TT_FILE_IN_SESSION==4,
- "Tt_scope enum values changed. This breaks the following "
- "code, and also breaks binary compatibility for libtt users. "
- "You probably don't want to do that, do you?")
- static int valid_scope_masks[] = {
- 0, // TT_SCOPE_NONE
- (1<<TT_SESSION) | (1<<TT_BOTH), // TT_SESSION
- (1<<TT_FILE) | (1<<TT_BOTH), // TT_FILE
- (1<<TT_SESSION) | (1<<TT_FILE) | (1<<TT_BOTH), // TT_BOTH
- (1<<TT_FILE_IN_SESSION)}; // TT_FILE_IN_SESSION
- if (! (_scopes & valid_scope_masks[s])) {
- trace << "== 0; /* " << _tt_enumname(s) << " != Tt_scopes */\n";
- return 0;
- }
- // if this is not a file-scoped message and the pattern
- // doesn't contain a value for the _sessions list then we
- // immediately fail the match.
- if (s != TT_FILE &&
- (msg.session().is_null() || _sessions->count() == 0)) {
- trace << "== 0; /* pattern not joined to "
- "tt_message_session() */\n";
- return 0;
- }
- switch (s) {
- case TT_FILE:
- return match_field(msg.file(), _files,
- tm, trace, "file" );
- case TT_FILE_IN_SESSION:
- if (msg.session()->has_id(_sessions)) {
- return((_files->count() == 0)
- || match_field(msg.file(), _files,
- tm, trace, "file"));
- } else {
- trace << "== 0; /* file in session */\n";
- return(0);
- }
- case TT_SESSION:
- // The session-scope case is so common that we avoid
- // matching the session id by setting a flag on a
- // pattern that we know is in the session (see
- // _Tt_s_procid::add_pattern and
- // _Tt_session::mod_session_id_in_patterns to see how
- // the flag is set). This flag is turned on if this
- // pattern is joined to the current session or not.
-
- if (in_session()) {
- return(1);
- } else {
- trace << "== 0; /* session */\n";
- }
- return(0);
- case TT_BOTH:
- rval = (msg.session()->has_id(_sessions) +
- match_field(msg.file(), _files, tm, trace, 0));
- if (rval == 0) {
- trace << "== 0; /* file and session */\n";
- }
- return(rval);
- case TT_SCOPE_NONE:
- default:
- trace << "== 0; /* Tt_scope */\n";
- return(0);
- }
- }
- //
- // Returns 1 if the message's args match the pattern args. The
- // _Tt_arg::is_match method is used to do the bulk of the work.
- //
- int _Tt_s_pattern::
- match_args(const _Tt_message &msg, int &tm,
- const _Tt_msg_trace &trace) const
- {
- if (msg.args()->count() == 0) {
- // arg matching was specified but the
- // message doesn't contain any args.
- trace << "== 0; /* args */\n";
- return(0);
- }
- _Tt_arg_list_cursor p_args(_args);
- _Tt_arg_list_cursor m_args(msg.args());
- int cumulative_args_score = 0;
- while (p_args.next()) {
- if (!m_args.next()) {
- trace << "== 0; /* args */\n";
- return(0);
- }
- int used_wildcard;
- int score = p_args->match_score(*m_args, used_wildcard);
- if (score <= 0) {
- trace << "== 0; /* args */\n";
- return(0);
- }
- cumulative_args_score += score;
- }
- tm += cumulative_args_score;
- return(1);
- }
- //
- // Returns 1 if the message's contexts match pattern's contexts.
- //
- int _Tt_s_pattern::
- match_contexts(const _Tt_message &msg, int &tm,
- const _Tt_msg_trace &trace) const
- {
- _Tt_pat_context_list_cursor cntxtC( _contexts );
- while (cntxtC.next()) {
- if (((_Tt_s_pat_context &)**cntxtC).matchVal( msg ) == 0) {
- trace << "== 0; /* contexts */\n";
- return 0;
- }
- }
- tm++;
- return 1;
- }
- // Routines to set and get the ptype that this pattern was generated
- // from, and to test if it was so generate.
- _Tt_ptype_ptr &_Tt_s_pattern::
- generating_ptype(_Tt_ptype_ptr &pt)
- {
- _generating_ptype = pt;
- return pt;
- }
- _Tt_ptype_ptr &_Tt_s_pattern::
- generating_ptype()
- {
- return _generating_ptype;
- }
- int _Tt_s_pattern::
- is_from_ptype()
- {
- return !_generating_ptype.is_null();
- }
- Tt_status _Tt_s_pattern::
- join_context(const _Tt_msg_context &msgCntxt)
- {
- _Tt_pat_context_list_cursor contextC( _contexts );
- while (contextC.next()) {
- if (contextC->slotName() == msgCntxt.slotName()) {
- return contextC->addValue( msgCntxt );
- }
- }
- return TT_WRN_NOTFOUND;
- }
- Tt_status _Tt_s_pattern::
- quit_context(const _Tt_msg_context &msgCntxt)
- {
- _Tt_pat_context_list_cursor contextC( _contexts );
- while (contextC.next()) {
- if (contextC->slotName() == msgCntxt.slotName()) {
- return contextC->deleteValue( msgCntxt );
- }
- }
- return TT_WRN_NOTFOUND;
- }
|