libtrigger.c

来自「SRI international 发布的OAA框架软件」· C语言 代码 · 共 652 行 · 第 1/2 页

C
652
字号
  oaa_Id(&me);
  from_me_list =
    icl_NewList(
     icl_NewCons(
      icl_NewStruct("from", 1,
		    icl_CopyTerm(me)),
      NULL));
  res = oaa_Interpret(term, from_me_list, NULL);
  icl_Free(from_me_list);
  icl_Free(me);
  return res;
}

/*****************************************************************************
 * name:    oaa_update_trigger
 * purpose: NOT IMPLEMENTED YET
 ****************************************************************************/
int oaa_update_trigger(char *mode, char* type, ICLTerm* condition, ICLTerm* action,
		       ICLTerm* in_params, ICLTerm** out_params){
  ICLTerm *t1 = NULL, *local_condition = NULL;
  ICLTerm *params = NULL, *params1 = NULL, *params2 = NULL;
  ICLTerm *new_addr = NULL, *addr = NULL;
  ICLTerm *me = NULL;
  ICLTerm *updaters1 = NULL, *requestees1 = NULL;
  ICLTerm *updaters2 = NULL, *requestees2 = NULL;
  ICLTerm *reflexive_true = icl_NewTermFromData("reflexive(true)", 15);
  ICLTerm *updaters = (ICLTerm *)NULL;
  ICLTerm *requestees = (ICLTerm *)NULL;
  ICLTerm* solvables = NULL;

  int res = FALSE, self = FALSE;

  /* If type is "comm" and InCondition does not unify with event(_,_) */
  if (STREQ(mode, "comm") && !icl_Unify(condition, t1 = icl_NewTermFromData("event(A,B)", 10), NULL)) {
    local_condition = icl_NewStruct("event", 2, condition, icl_NewVar("X"));
  }
  else {
    local_condition = icl_CopyTerm(condition);
  }
  icl_Free(t1);

  /* in_params might be a variable */
  if (icl_IsList(in_params)) {
    icl_standardize_params(in_params, 0, &params);
  }
  else {
    params = icl_NewList(NULL);
  }

  /* is there a specific address ? */
  if (!icl_param_arg("address", NULL, params, &addr)) {
    addr = icl_NewList(NULL);
  }

  /* decide whether or not to update locally: */
  if (oaa_PrimaryAddress(&me) &&
      icl_Member(me, addr, NULL)) {

    icl_ListDelete(addr, me, &new_addr);
    t1 = icl_NewStruct("address", 1, icl_CopyTerm(addr));
    replace_element(t1, params,
		    icl_NewStruct("address", 1, new_addr), &params1);
    icl_Free(t1);
    self = TRUE;
  } else {
    new_addr = icl_CopyTerm(addr);
    params1 = icl_CopyTerm(params);
  }

  if ((!addr->p) &&
      icl_GetParamValue(reflexive_true, params1, NULL)) {
    ICLTerm *write = icl_NewStr("write");
    ICLTerm *real_clause, *real_matched;
    /* do NOT use remove_element here: */
    icl_ListDelete(params1, reflexive_true, &params2);
    solvables = valid_oaa_solvables();
    if (oaa_data_matches_solvables(local_condition, solvables, write, &real_clause,
				   &real_matched))
      self = TRUE;
    icl_Free(write);
  } else {
    params2 = params1;
  }
  icl_Free(reflexive_true);

  /* update locally if appropriate */
  if (self) {
    requestees1 = icl_NewList(icl_NewCons(icl_CopyTerm(me), NULL));
    if (STREQ(mode, "add"))
      res = oaa_add_trigger_local(type, local_condition, action, params2);
    else if (STREQ(mode, "remove"))
      res = oaa_remove_trigger_local(type, local_condition, action, params2);
    if(res) {
      updaters1 = icl_NewList(icl_NewCons(icl_CopyTerm(me), NULL));
    } else {
      updaters1 = icl_NewList(NULL);
    }
  } else {
    requestees1 = icl_NewList(NULL);
    updaters1 = icl_NewList(NULL);
  }
  icl_Free(me);

  /* Update remotely if appropriate:
   */
  if (oaa_class("leaf") && ((!addr->p) || (new_addr->p))) {
    ICLTerm *reply;
    char *goalIdStr = new_goal_id();

    /* Send the ev_update_data event to the Facilitator
     */
    ICLTerm* toBeSent = icl_NewStruct("ev_update_trigger", 6,
				      icl_NewStr(goalIdStr), icl_NewStr(mode),
				      icl_NewStr(type), icl_CopyTerm(local_condition),
				      icl_CopyTerm(action), params2);
    oaa_PostEvent(toBeSent, ICL_EMPTY);

    /* In the return event, Requestees2 lists all agents to whom
     * the update request wassent; Updaters2 lists those who succeeded
     */
    requestees2 = icl_NewList(NULL);
    updaters2 = icl_NewList(NULL);

    if (!(icl_param_arg("reply", NULL, params, &reply) &&
          (STREQ("asynchronous", icl_Str(reply)) ||
           STREQ("none", icl_Str(reply)))) ) {
      ICLTerm *ev_reply_updated =
        icl_NewStruct("ev_trigger_updated", 8, icl_NewVar("G"),
                      icl_NewStr(mode), icl_NewStr(type),
                      icl_CopyTerm(local_condition), icl_CopyTerm(action), icl_CopyTerm(params2),
                      icl_NewVar("Requestees"), icl_NewVar("Updaters"));
      oaa_poll_until_event(ev_reply_updated, NULL);
      icl_Free(ev_reply_updated);
    }
    icl_Free(toBeSent);
  }
  icl_Free(addr);
  icl_Free(new_addr);

  /*
   * The following section replaces a variable parameter value in the
   * parameter list for return to the calling function
   */
  icl_append_to_list(updaters1, updaters2, &updaters);
  icl_Free(updaters1);
  icl_Free(updaters2);

  /* Return Updaters if requested:
   */
  t1 = icl_NewStruct("get_satisfiers", 1,
		     updaters);
  icl_replace_param_value(t1, params);
  icl_Free(t1);		/* frees updaters too */

  /*  Return Requestees if requested:
   */
  icl_append_to_list(requestees1, requestees2, &requestees);
  icl_replace_param_value((t1 = icl_NewStruct("get_address", 1,
					      requestees)),
			  params);
  icl_Free(requestees1);
  icl_Free(requestees2);
  icl_Free(t1);

  if (out_params) {
    *out_params = params;
  }

  if(params2 == params1) {
    icl_Free(params2);
  }
  else {
    icl_Free(params2);
    icl_Free(params1);
  }

  icl_Free(local_condition);
  icl_Free(params);
  return TRUE;

};

/**
 * Adds a trigger according to parameters.
 * <p>Type     = comm, data, task, time</p>
 * <p>Condition= comm:event to match,  data:data to match, task:solvable to call
 *            time:@@</p>
 * <p>Action   = Can be any of these:</p>
 * <ul>
 *              <li>oaa_Solve(Goal, Params)</li>
 *              <li>oaa_Interpret(Goal, Params)</li>
 *              <li>Goal [passed to oaa_Interpret with default params]</li>
 * </ul>
 * <p>Params   =</p>
 * <ul>
 *   <li>address(X): a list including 'self', 'parent', and/or the
 *   addresses of other client agents.  Default: see below.</li>
 *   <li>test(T): additional tests before trigger will fire [@@needs work?]</li>
 *   <li>on(OP) : operation check: on(add), on(remove), on(receive), etc.</li>
 *   <li>recurrence(R): when, whenever, or integer (# of times to execute)</li>
 *   <li>reply({true,none}): When a trigger is being added on</li>
 *     a remote agent or agents, this tells whether reply message(s) are
 *     desired.</li>
 *   <li>block(Mode) : true: Block until the reply arrives.
 *               : false: Don't block.  In
 *                        this case, the reply events
 *                         can be handled by the user's app_do_event callback</li>
 *               Default: true.  Note that reply(none) overrides
 *                        block(true).</li>
 *   <li>get_address(X): Returns a list of addresses (ids) of agents that
 *     were sent the request.</li>
 *   <li>get_satisfiers(X): Returns a list of addresses (ids) of agents that
 *     successfully completed the request.</p>
 * </ul>
 *
 * <p>Default destination for triggers:</p>
 * <ul>
 *    <li>Data triggers: all agents with solvables matching the Condition
 *        field.</li>
 *    <li>All other types: the local agent</li>
 * </ul>
 */
int oaa_AddTrigger(char *type, ICLTerm *condition, ICLTerm *action,
                   ICLTerm *initial_params, ICLTerm **out_params) {
  return oaa_update_trigger("add", type, condition, action,
                            initial_params, out_params);
}

/**
 * Removes a trigger from a local or remote agent.
 */
int oaa_RemoveTrigger(char *type, ICLTerm *condition,
                      ICLTerm *action, ICLTerm *initial_params,
                      ICLTerm **out_params) {
  return oaa_update_trigger("remove", type, condition, action,
                            initial_params, out_params);
}

int oaa_add_trigger_local(char *type, ICLTerm *condition, ICLTerm *action,
                          ICLTerm *params)
{
  static int cntr = 0;
  char trigger_id[32];
  int res;
  ICLTerm *t1;
  ICLTerm *trigger;

  sprintf(trigger_id, "trg%d", cntr++);

  t1 = icl_NewList(NULL);
  trigger = icl_NewStruct("oaa_trigger", 5,
                          icl_NewStr(trigger_id),
                          icl_NewStr(type),
                          icl_CopyTerm(condition),
                          icl_CopyTerm(action),
                          icl_CopyTerm(params));
  res = oaa_add_data_local(trigger, t1);
  icl_Free(t1);
  icl_Free(trigger);
  return res;
}

int oaa_remove_trigger_local(char *type, ICLTerm *condition, ICLTerm *action,
                             ICLTerm *params)
{
  int res;
  ICLTerm *tid_var = icl_NewVar("_trigger_id");
  ICLTerm *trigger_term = icl_NewStruct("oaa_trigger", 5, tid_var,
                                        icl_NewStr(type),
                                        icl_CopyTerm(condition),
                                        icl_CopyTerm(action),
                                        icl_CopyTerm(params));
  ICLTerm *t1;

  t1 = icl_NewList(NULL);
  res = oaa_remove_data_local(trigger_term, t1);
  icl_Free(trigger_term);
  icl_Free(tid_var);
  icl_Free(t1);

  return res;
}

/**
 * Removes a local trigger given its unique identifier.
 */
int oaa_remove_local_trigger_by_id(ICLTerm *trigger_id)
{
  ICLTerm *dummyvar = icl_NewVar("_");
  ICLTerm *trigger_term = icl_NewStruct("oaa_trigger", 5,
                                        icl_CopyTerm(trigger_id),
                                        icl_CopyTerm(dummyvar),
                                        icl_CopyTerm(dummyvar),
                                        icl_CopyTerm(dummyvar),
                                        icl_CopyTerm(dummyvar));
  ICLTerm *t1;

  t1 = icl_NewList(NULL);
  oaa_remove_data_local(trigger_term, t1);
  icl_Free(trigger_term);
  icl_Free(dummyvar);
  icl_Free(t1);
  return TRUE;
}

/**
 * @defgroup Triggers Triggers
 *
 * Contains C versions of the trigger functions for the Open Agent
 * Architecture.
 *
 * @{
 */

/**
 * @file libtrigger.h
 * Contains C versions of the trigger functions for the Open Agent
 * Architecture.
 */

/**
 * @file libtrigger.c
 */

/** @} */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?