/*      Get number of events made by attachment       */
int et_attach_geteventsmake(et_sys_id id, et_att_id att_id,
                            uint64_t *events)
{
  et_id *etid = (et_id *) id;
  
  if (etid->locality == ET_REMOTE) {
      return etr_attach_geteventsmake(id, att_id, events);
  }
  
  if (!et_alive(id)) {
      return ET_ERROR_DEAD;
  }
  
  /* Protection from (local) et_close() unmapping shared memory */
  et_memRead_lock(etid);

  /* Has caller already called et_close()? */
  if (etid->closed) {
      et_mem_unlock(etid);
      if (etid->debug >= ET_DEBUG_ERROR) {
          et_logmsg("ERROR", "et_attach_geteventsmake, et id is closed\n");
      }
      return ET_ERROR_CLOSED;
  }
  
  if ((att_id < 0) || (att_id >= etid->sys->config.nattachments)) {
      et_mem_unlock(etid);
      if (etid->debug >= ET_DEBUG_ERROR) {
          et_logmsg("ERROR", "et_attach_geteventsmake, bad attachment id\n");
      }
      return ET_ERROR;
  }
  
  if (events != NULL) {
      *events = etid->sys->attach[att_id].events_make;
  }
  
  et_mem_unlock(etid);
  return ET_OK;
}
/* Wake up a specific attachment waiting to read events.*/
int et_wakeup_attachment(et_sys_id id, et_att_id att)
{
  int status;
  et_id      *etid = (et_id *) id;
  et_stat_id  stat_id;
  et_station *ps;
  et_list    *pl, *pl_gc;

  if (att < 0) {
    if (etid->debug >= ET_DEBUG_ERROR) {
      et_logmsg("ERROR", "et_wakeup_attachment, bad argument\n");
    }
    return ET_ERROR;
  }
  
  if (etid->locality != ET_LOCAL) {
    return etr_wakeup_attachment(id, att);
  }
  
  /* Protection from (local) et_close() unmapping shared memory */
  et_memRead_lock(etid);

  /* Has caller already called et_close()? */
  if (etid->closed) {
      et_mem_unlock(etid);
      if (etid->debug >= ET_DEBUG_ERROR) {
          et_logmsg("ERROR", "et_wakeup_attachment, et id is closed\n");
      }
      return ET_ERROR_CLOSED;
  }
  
  stat_id = etid->sys->attach[att].stat;
  ps = etid->grandcentral + stat_id;
  pl = &ps->list_in;
  pl_gc = &etid->grandcentral->list_in;

  if (att >= etid->sys->config.nattachments) {
      et_mem_unlock(etid);
      if (etid->debug >= ET_DEBUG_ERROR) {
          et_logmsg("ERROR", "et_wakeup_attachment, bad argument\n");
      }
      return ET_ERROR;
  }
  
  /* Only tell things to wake up if they are sleeping, otherwise
   * after the NEXT read, it will quit as if being woken up! */
  if ((etid->sys->attach[att].blocked == ET_ATT_UNBLOCKED) &&
      (etid->sys->attach[att].sleep   == ET_ATT_NOSLEEP)) {

      et_mem_unlock(etid);
      if (etid->debug >= ET_DEBUG_WARN) {
          et_logmsg("WARN", "et_wakeup_attachment, attachment is NOT blocked so not sending wakeup signal\n");
      }
      return ET_OK;
  }
  
  if (etid->debug >= ET_DEBUG_INFO) {
    et_logmsg("INFO", "et_wakeup_attachment, waking up attachment %d\n", att);
  }
  /* attachment may be waiting on a "get", so wake own station in list */
  etid->sys->attach[att].quit = ET_ATT_QUIT;
  status = pthread_cond_broadcast(&pl->cread);
  if (status != 0) {
    err_abort(status, "Wakeup readers");
  }
  /* attachment may be waiting on a "new", so wake GrandCentral's in list */
  status = pthread_cond_broadcast(&pl_gc->cread);
  if (status != 0) {
    err_abort(status, "Wakeup readers");
  }
  
  et_mem_unlock(etid);
  return ET_OK;
}
/*   Wake up all attachments waiting to read events   */
int et_wakeup_all(et_sys_id id, et_stat_id stat_id)
{
  int i, status;
  et_att_id att;
  et_id *etid = (et_id *) id;
  et_station *ps;
  et_list    *pl, *pl_gc;

  if (stat_id < 0) {
    if (etid->debug >= ET_DEBUG_ERROR) {
      et_logmsg("ERROR", "et_wakeup_all, bad argument\n");
    }
    return ET_ERROR;
  }
  
  if (etid->locality != ET_LOCAL) {
    return etr_wakeup_all(id, stat_id);
  }
  
  /* Protection from (local) et_close() unmapping shared memory */
  et_memRead_lock(etid);

  /* Has caller already called et_close()? */
  if (etid->closed) {
      et_mem_unlock(etid);
      if (etid->debug >= ET_DEBUG_ERROR) {
          et_logmsg("ERROR", "et_wakeup_all, et id is closed\n");
      }
      return ET_ERROR_CLOSED;
  }
  
  ps = etid->grandcentral + stat_id;
  pl = &ps->list_in;
  pl_gc = &etid->grandcentral->list_in;

  if (stat_id >= etid->sys->config.nstations) {
      et_mem_unlock(etid);
      if (etid->debug >= ET_DEBUG_ERROR) {
          et_logmsg("ERROR", "et_wakeup_all, bad argument\n");
      }
      return ET_ERROR;
  }
  
  for (i=0; i < etid->sys->config.nattachments ; i++) {
    att = ps->data.att[i];
    if (att > -1) {
      if ((etid->sys->attach[att].blocked == ET_ATT_BLOCKED) ||
	      (etid->sys->attach[att].sleep == ET_ATT_SLEEP)) {
        etid->sys->attach[att].quit = ET_ATT_QUIT;
        if (etid->debug >= ET_DEBUG_INFO) {
          et_logmsg("INFO", "et_wakeup_all, waking up attachment %d\n", att);
        }
      } 
    }
  }
  /* attachment may be waiting on a "get", so wake own station in list */
  status = pthread_cond_broadcast(&pl->cread);
  if (status != 0) {
    err_abort(status, "Wakeup all readers");
  }
  /* attachment may be waiting on a "new", so wake GrandCentral's in list */
  status = pthread_cond_broadcast(&pl_gc->cread);
  if (status != 0) {
    err_abort(status, "Wakeup all readers");
  }
  
  et_mem_unlock(etid);
  return ET_OK;
}
Exemple #4
0
/**
 * This routine determines whether we are looking for the ET system locally,
 * locally on some non-pthread-mutex-sharing operating system, or remotely.
 *
 * @param filename    name of ET system file.
 * @param openconfig  ET system open configuration.
 *
 * @returns @ref ET_REMOTE         if looking for a remote ET system.
 * @returns @ref ET_LOCAL          if looking for a local ET system.
 * @returns @ref ET_LOCAL_NOSHARE  if looking for a local ET system without pthread mutex sharing.
 */
int et_findlocality(const char *filename, et_openconfig openconfig) {

    char ethost[ET_IPADDRSTRLEN];
    et_open_config *config = (et_open_config *) openconfig;

    /* if local client opens ET system as remote (thru server) ...
     * This option is for those applications (such as system
     * monitoring) that only want to communication through
     * an ET system's server and not map its shared mem.
     */
    if (config->mode == ET_HOST_AS_REMOTE) {
        return ET_REMOTE;
    }
    /* else if ET system host name is unknown and remote ... */
    else if (strcmp(config->host, ET_HOST_REMOTE) == 0) {
        return ET_REMOTE;
    }
    /* else if ET system is on local host */
    else if ((strcmp(config->host, ET_HOST_LOCAL) == 0) ||
             (strcmp(config->host, "localhost")   == 0))  {
        /* if local operating system can share pthread mutexes ... */
        if (et_sharedmutex() == ET_MUTEX_SHARE) {
            return ET_LOCAL;
        }
        else {
            return ET_LOCAL_NOSHARE;
        }
    }
    /* else if ET system host name is unknown and maybe anywhere ... */
    else if (strcmp(config->host, ET_HOST_ANYWHERE) == 0) {
        int err, port, isLocal;
        uint32_t inetaddr;
        struct timeval waittime;

        waittime.tv_sec  = 0;
        waittime.tv_usec = 10000; /* 0.1 sec */

        /* send only 1 broad/multicast with a 0.1 sec wait */
        err = et_findserver2(filename, ethost, &port, &inetaddr, NULL, config, 1, &waittime, ET_DEBUG_NONE);
        if ((err == ET_ERROR) || (err == ET_ERROR_TIMEOUT)) {
            et_logmsg("ERROR", "et_findlocality, cannot find ET system\n");
            return err;
        }
        else if (err == ET_ERROR_TOOMANY) {
            /* many systems responded */
            et_logmsg("ERROR", "et_findlocality, multiple ET systems responded\n");
            return err;
        }

        etNetNodeIsLocal(ethost, &isLocal);
        if (isLocal) {
            if (et_sharedmutex() == ET_MUTEX_SHARE) {
                return ET_LOCAL;
            }
            else {
                return ET_LOCAL_NOSHARE;
            }
        }

        return ET_REMOTE;
    }
    /* else ET system host name is given ... */
    else {
        int isLocal;
        etNetNodeIsLocal(config->host, &isLocal);
        if (isLocal) {
            if (et_sharedmutex() == ET_MUTEX_SHARE) {
                return ET_LOCAL;
            }
            else {
                return ET_LOCAL_NOSHARE;
            }
        }

        return ET_REMOTE;
    }

    return ET_REMOTE;
}
Exemple #5
0
/**
 * This routine opens an ET system for client use.
 *
 * Given an ET system on the same host, this routine will map the system's shared memory into the
 * user's space. It also starts up a thread to produce a heartbeat and a second thread to monitor
 * the ET system's heartbeat. If the ET system is remote, a network connection is made to it.<p>
 *
 * The ET system is implemented as a single memory mapped file of the name, filename.
 * This routine should only be called once, before all other ET routines are used, or after a
 * system has been closed with a call to @ref et_close or @ref et_forcedclose. A successful return
 * from this routine assures connection to an ET system which is up and running.
 * <b><i>IT IS CRUCIAL THAT THE USER GET A RETURN VALUE OF "ET_OK" IF THE USER WANTS AN ET SYSTEM
 * GUARANTEED TO FUNCTION.</i></b><p>
 *
 * The user may open an ET system on a remote host. ET decides whether the user is on the same
 * as or a different machine than the system. If the determination is made that the user is on
 * another computer, then network connections are made to that system.<p>
 *
 * @param id          pointer to ET system id which gets filled in if ET system successfully opened.
 * @param filename    name of ET system file.
 * @param openconfig  ET system open configuration.
 *
 * @returns @ref ET_OK             if successful
 * @returns @ref ET_ERROR          if bad arg, ET name too long, cannot initialize id,
 *                                 creating/using shared memory, incompatible values for @ref ET_STATION_SELECT_INTS,
 *                                 or ET system is 32 bit and this program is 64 bit,
 * @returns @ref ET_ERROR_TIMEOUT if the ET system is still not active before the routine returns.
 * @returns @ref ET_ERROR_TOOMANY  if broad/multicasting and too many responses
 * @returns @ref ET_ERROR_REMOTE   if broad/multicasting and cannot find/connect to ET system or
 *                                 cannot allocate memory or ET system & user use different versions of ET, or
 *                                 the host has a strange byte order.
 * @returns @ref ET_ERROR_READ     if network read error.
 * @returns @ref ET_ERROR_WRITE    if network write error.
 */
int et_open(et_sys_id *id, const char *filename, et_openconfig openconfig) {

    int             status, auto_open=0, err, locality;
    et_open_config *config;
    et_openconfig   auto_config = NULL;
    int             def_debug;

    if (openconfig == NULL) {
        auto_open = 1;
        if (et_open_config_init(&auto_config) == ET_ERROR) {
            et_logmsg("ERROR", "et_open, null arg for openconfig, cannot use default\n");
            return ET_ERROR;
        }
        openconfig = auto_config;
    }

    config = (et_open_config *) openconfig;

    err = ET_OK;
    /* argument checking */
    if ((filename == NULL) || (config->init != ET_STRUCT_OK)) {
        et_logmsg("ERROR", "et_open, bad argument\n");
        err = ET_ERROR;
    }
    else if (strlen(filename) > ET_FILENAME_LENGTH - 1) {
        et_logmsg("ERROR", "et_open, ET name too long\n");
        err = ET_ERROR;
    }

    if (err != ET_OK) {
        if (auto_open == 1) {
            et_open_config_destroy(auto_config);
        }
        return err;
    }

    /* initialize id */
    if (et_id_init(id) != ET_OK) {
        et_logmsg("ERROR", "et_open, cannot initialize id\n");
        return ET_ERROR;
    }

    if (et_open_config_getdebugdefault(openconfig, &def_debug) != ET_OK) {
        def_debug = ET_DEBUG_ERROR;
    }
    et_system_setdebug(*id, def_debug);


    /* Decide whether we are looking for the ET system locally,
     * locally on some non-mutex-sharing operating
     * system, remotely, or anywhere.
     */
    locality = et_findlocality(filename, openconfig);
    /* if host is local ... */
    if (locality == ET_LOCAL) {
        status = etl_open(id, filename, openconfig);
        /* If this is a Java-based ET sys, try opening it as remote client. */
        if (status == ET_ERROR_JAVASYS) {
            et_logmsg("ERROR", "et_open: cannot open Java ET file, try as remote client\n");
            status = etr_open(id, filename, openconfig);
        }
    }
        /* else if host is remote ... */
    else if (locality == ET_REMOTE) {
        status = etr_open(id, filename, openconfig);
    }
        /* else if host is local on Linux ... */
    else if (locality == ET_LOCAL_NOSHARE) {
        status = etn_open(id, filename, openconfig);
    }
        /* else if too many systems responded and we have return error policy ... */
    else if ((locality == ET_ERROR_TOOMANY) && (config->policy == ET_POLICY_ERROR)) {
        if (auto_open == 1) {
            et_open_config_destroy(auto_config);
        }
        et_logmsg("ERROR", "et_open: too many ET systems of that name responded\n");
        return ET_ERROR;
    }
        /* else did not find ET system by broad/multicasting. In
         * this case, try to open a local system first then remote.
         */
    else {
        int shared = et_sharedmutex();
        /* if local operating system can share pthread mutexes ... */
        if (shared == ET_MUTEX_SHARE) {
            status = etl_open(id, filename, openconfig);
        }
        else {
            status = etn_open(id, filename, openconfig);
        }

        if (status != ET_OK) {
            status = etr_open(id, filename, openconfig);
        }
    }

    if (status != ET_OK) {
        et_id_destroy(*id);
    }

    if (auto_open == 1) {
        et_open_config_destroy(auto_config);
    }

    return status;
}
Exemple #6
0
int et_open(et_sys_id *id, const char *filename, et_openconfig openconfig)
{     
  int             status, auto_open=0, err;
  et_open_config *config;
  et_openconfig   auto_config = NULL;
  int             def_debug;

  if (openconfig == NULL) {
    auto_open = 1;
    if (et_open_config_init(&auto_config) == ET_ERROR) {
      et_logmsg("ERROR", "et_open, null arg for openconfig, cannot use default\n");
      return ET_ERROR;
    }
    openconfig = auto_config;
  }

  config = (et_open_config *) openconfig;

  err = ET_OK;
  /* argument checking */
  if ((filename == NULL) || (config->init != ET_STRUCT_OK)) {
    et_logmsg("ERROR", "et_open, bad argument\n");
    err = ET_ERROR;
  }
  else if (strlen(filename) > ET_FILENAME_LENGTH - 1) {
    et_logmsg("ERROR", "et_open, ET name too long\n");
    err = ET_ERROR;
  }

  if (err != ET_OK) {
    if (auto_open == 1) {
      et_open_config_destroy(auto_config);
    }
    return err;
  }
  
  /* initialize id */
  if (et_id_init(id) != ET_OK) {
    et_logmsg("ERROR", "et_open, cannot initialize id\n");
    return ET_ERROR;
  }

  if (et_open_config_getdebugdefault(openconfig, &def_debug) != ET_OK) {
    def_debug = ET_DEBUG_ERROR;
  }
  et_system_setdebug(*id, def_debug);
  
  /* We depart from the original version of et_open since
   * this ET client will attach to an ET system remotely by definition.
   * Force the configuration to make a tcp connection to the ET system,
   * even if it's not remote.
   */
  config->mode = ET_HOST_AS_REMOTE;
  status = etr_open(id, filename, openconfig);
 
  if (status != ET_OK) {
    et_id_destroy(*id);
  }
  
  if (auto_open == 1) {
    et_open_config_destroy(auto_config);
  }

  return status;
}