示例#1
0
    /*!
     * Request a new ID that is not currently in use.
     *
     * @return  Returns an ID in the range [1, MaxID] or 0 if there are no
     *           unused IDs.
     */
    FUND::UINT32 GetID()
    {
        EXPONENTIAL_BACKOFF<STATS> backoff(1, _stats);

        for (FUND::UINT32 i = 0;  i < _numElements;  i++)
        {
            FUND::UINT32 val = OPS::Load(&_bits[i]);

            while (val != 0xffffffff)
            {
                FUND::UINT32 bit = 0;
                for (FUND::UINT32 tval = val;  tval & 1;  tval >>= 1)
                    bit++;

                FUND::UINT32 newval = val | (1 << bit);
                if (OPS::CompareAndDidSwap(&_bits[i], val, newval))
                    return i*sizeof(FUND::UINT32) + bit + 1;

                backoff.Delay();
                val = OPS::Load(&_bits[i]);
            }
        }

        return 0;
    }
示例#2
0
bool SessionImpl::nextReceiver(qpid::messaging::Receiver& receiver, qpid::messaging::Duration timeout)
{
    while (true) {
        txError.raise();
        try {
            std::string destination;
            if (incoming.getNextDestination(destination, adjust(timeout))) {
                qpid::sys::Mutex::ScopedLock l(lock);
                Receivers::const_iterator i = receivers.find(destination);
                if (i == receivers.end()) {
                    throw qpid::messaging::ReceiverError(QPID_MSG("Received message for unknown destination " << destination));
                } else {
                    receiver = i->second;
                }
                return true;
            } else {
                return false;
            }
        } catch (TransportFailure&) {
            reconnect();
        } catch (const qpid::framing::ResourceLimitExceededException& e) {
            if (backoff()) return false;
            else throw qpid::messaging::TargetCapacityExceeded(e.what());
        } catch (const qpid::SessionException& e) {
            rethrow(e);
        } catch (const qpid::ClosedException&) {
            throw qpid::messaging::SessionClosed();
        } catch (const qpid::ConnectionException& e) {
            throw qpid::messaging::ConnectionError(e.what());
        } catch (const qpid::ChannelException& e) {
            throw qpid::messaging::MessagingException(e.what());
        }
    }
}
示例#3
0
    /*!
     * Pop an element off the head of the lifo queue.
     *
     *  @param[out] isEmpty     If Pop() returns NULL and \a isEmpty is not NULL, the
     *                           \a isEmpty parameter is set to TRUE.  This parameter
     *                           is not particularly useful, but it is provided for
     *                           symetry with LIFO_PTR::Pop().
     *  @param[in] maxRetries   This parameter is ignored, but it is provided for
     *                           symetry with LIFO_PTR::Pop().
     *
     * @return  Returns the popped element on success, or NULL if the queue is empty.
     */
    ELEMENT *Pop(bool *isEmpty=0, unsigned maxRetries=0)
    {
        HEAD oldHead;
        HEAD newHead;
        ELEMENT *element;
        EXPONENTIAL_BACKOFF<STATS> backoff(1, _stats);

        do
        {
            backoff.Delay();

            oldHead._word = OPS::Load(&_head._word);
            if (oldHead._fields._iElement == 0)
            {
                if (isEmpty)
                    *isEmpty = true;
                return 0;
            }

            element = _heap->Pointer(oldHead._fields._iElement);
            newHead._fields._iElement = _heap->Index(element->_next);
            newHead._fields._counter = oldHead._fields._counter+1;
        }
        while (!OPS::CompareAndDidSwap(&_head._word, oldHead._word, newHead._word, BARRIER_CS_NEXT));

        // BARRIER_CS_NEXT above ensures that all processors see that the element is removed from
        // the queue before the consumer uses the element.

        return element;
    }
示例#4
0
EndPoint::EndPoint(const char *const name, const char *const location, const Parameters /*params*/) :
  mName(name),
  mLocation(location),
  mContext(0),
  mNameMap(),
  mMessageFactory(),
  mNetworkThread(),
  mRunning(false),
  mStarted(false),
  mNetworkLock(),
  mConnectQueue(),
  mSendQueue()
{
    THERON_ASSERT_MSG(!mName.IsNull(), "Must supply a unique, non-null name for each endpoint");
    THERON_ASSERT_MSG(!mLocation.IsNull(), "Must supply a valid port address for each endpoint");

    // Initialize the per-process context.
    mContext = InitializeContext();

    // Don't start the network thread if networking isn't enabled.
    if (mContext->Enabled())
    {
        // Start the network thread.
        mRunning = true;
        mNetworkThread.Start(NetworkThreadEntryPoint, this);

        // Wait for the network thread to start.
        uint32_t backoff(0);
        while (!mStarted)
        {
            Detail::Utils::Backoff(backoff);
        }
    }
}
示例#5
0
SCORE LanguageModel::BackoffScore(
  const std::vector<const Factor*> &context) const
{
  //cerr << "backoff=";
  //DebugContext(context);

  SCORE ret;
  size_t stoppedAtInd;
  const Node<const Factor*, LMScores> &node = m_root.getNode(context,
      stoppedAtInd);

  if (stoppedAtInd == context.size()) {
    // found entire ngram
    ret = node.getValue().backoff;
  } else {
    if (stoppedAtInd == 0) {
      ret = m_oov;
      stoppedAtInd = 1;
    } else {
      ret = node.getValue().backoff;
    }

    // recursive
    std::vector<const Factor*> backoff(context.begin() + stoppedAtInd,
                                       context.end());
    ret += BackoffScore(backoff);
  }

  return ret;
}
示例#6
0
文件: locks.hpp 项目: jaingaurav/rstm
/***  Slowpath TATAS acquire.  This performs exponential backoff */
inline int tatas_acquire_slowpath(tatas_lock_t* lock)
{
    int b = 64;
    do {
        backoff(&b);
    } while (tas(lock));
    return b;
}
示例#7
0
	inline void write_lock() {
		// set WRITE flag
		BaseType oldV = value.load();
		
		for (;;) {
			if ((oldV & FLAG_WRITE) != 0) {
				backoff(BackoffWrite);
				oldV = value.load();
			}
			else if (value.compare_exchange_weak(oldV, oldV | FLAG_WRITE))
				break;
		}
		
		// wait until there are no more readers
		while (value.load() != FLAG_WRITE)
			backoff(BackoffRead);
		assert(value.load() == FLAG_WRITE);
	}
示例#8
0
void stpcDeferredDelete(stpcProxy *proxy, void (*freeData)(void *), void *data, void (*backoff)(int)) {
    stpcNode *node;
	int n = 0;
    
	while ((node = _newNode(proxy, true)) == NULL) {
		backoff(n++);
	}
    
    node->freeData = freeData;
    node->data = data;
    
    _queueNode(proxy, node);        
}
示例#9
0
	inline void read_lock() {
		BaseType oldV = value.load();
		
		for (;;) {
			if ((oldV & FLAG_WRITE) != 0) {
				backoff(BackoffWrite);
				oldV = value.load();
			}
			else if (value.compare_exchange_weak(oldV, oldV+1))
				break;
		}
		BaseType v = value.load();
		if (v == 0) fail(v, "Must be positive");
		if (v == FLAG_WRITE) fail(v, "Write Flag must not be set");
	}
示例#10
0
/* static */ int DicNodeUtils::getBigramNodeProbability(const uint8_t *const dicRoot,
        const DicNode *const node, MultiBigramMap *multiBigramMap) {
    const int unigramProbability = node->getProbability();
    const int wordPos = node->getPos();
    const int prevWordPos = node->getPrevWordPos();
    if (NOT_VALID_WORD == wordPos || NOT_VALID_WORD == prevWordPos) {
        // Note: Normally wordPos comes from the dictionary and should never equal NOT_VALID_WORD.
        return backoff(unigramProbability);
    }
    if (multiBigramMap) {
        return multiBigramMap->getBigramProbability(
                   dicRoot, prevWordPos, wordPos, unigramProbability);
    }
    return BinaryFormat::getBigramProbability(dicRoot, prevWordPos, wordPos, unigramProbability);
}
示例#11
0
    /*
     * Attempt to add a new element at the given location.  Return TRUE if it could
     * be added there, FALSE if not.
     */
    bool AddAt(FUND::UINT32 index, KEY key, const OBJECT &userObj)
    {
        // If this location is available, mark it as reserved.
        //
        // The BARRIER_CS_NEXT here works in conjunction with the other barrier marked (B).
        // This ensures that the read of _map[index] is made before the read of
        // _highWaterMark below.  Otherwise, we might read a stale version of _highWaterMark
        // and not realize that _highWaterMark needs to be updated for this new element.
        // (See reference mark (C) below.)
        //
        if (!OPS::CompareAndDidSwap(&_map[index], KeyAvailable, KeyReserved, BARRIER_CS_NEXT))
            return false;

        // Now that the position is reserved, we can safely write to it without
        // anyone else using it.
        //
        // The BARRIER_ST_PREV here works in conjunction with the other barrier marked (A).
        // They ensure that the write of _object[index] is visible on other processors
        // by the time the _map[index] is made valid.
        //
        _objects[index] = userObj;
        OPS::Store(&_map[index], key, BARRIER_ST_PREV);

        // Make sure the high water mark stays above all the valid entries.
        // If we're storing at the free location hint, we just bump the hint,
        // assuming that the next location is more likely to be free than this
        // one.
        //
        FUND::UINT32 highWater;
        EXPONENTIAL_BACKOFF<STATS> backoff(1, _stats);
        do
        {
            backoff.Delay();

            // Reference mark (C).  This is the read of _highWaterMark that is synchronized
            // with barrier (B).  If this read were to happen before the CompareAndDidSwap on
            // _map[index] above, we might get a stale value of _highWaterMark.  This is
            // prevented by barrier (B).
            //
            highWater = OPS::Load(&_highWaterMark);
            if (index < highWater)
                break;
        }
        while (!OPS::CompareAndDidSwap(&_highWaterMark, highWater, index+1));

        OPS::CompareAndSwap(&_freeLocationHint, index, index+1);
        return true;
    }
示例#12
0
    /*!
     * Release an ID, making it available for reuse.
     *
     *  @param[in] id   The ID, which must be in the range [1,MaxID].
     */
    void ReleaseID(FUND::UINT32 id)
    {
        id--;
        FUND::UINT32 i = id >> 5;
        FUND::UINT32 bit = 1 << (id & 0x1f);

        FUND::UINT32 val;
        FUND::UINT32 newval;
        EXPONENTIAL_BACKOFF<STATS> backoff(1, _stats);

        do {
            backoff.Delay();
            val = OPS::Load(&_bits[i]);
            newval = val & ~bit;
        } while (!OPS::CompareAndDidSwap(&_bits[i], val, newval));
    }
示例#13
0
static void
check_connected( void *user_data ) {
  UNUSED( user_data );

  debug( "Checking a connection ( fd = %d, ip = %#x, port = %u ).", connection.fd, connection.ip, connection.port );

  assert( secure_channel_initialized );
  assert( connection.fd >= 0 );

  set_writable( connection.fd, false );
  delete_fd_handler( connection.fd );

  int err = 0;
  socklen_t length = sizeof( error );
  int ret = getsockopt( connection.fd, SOL_SOCKET, SO_ERROR, &err, &length );
  if ( ret < 0 ) {
    error( "Failed to retrieve error code ( fd = %d, ret = %d, errno = %s [%d] ).",
           connection.fd, ret, strerror( errno ), errno );
    return;
  }

  switch ( err ) {
    case 0:
      connected();
      break;

    case EINTR:
    case EAGAIN:
    case ECONNREFUSED:
    case ENETUNREACH:
    case ETIMEDOUT:
      warn( "Failed to connect ( fd = %d, errno = %s [%d] ).", connection.fd, strerror( err ), err );
      backoff();
      return;

    case EINPROGRESS:
      set_fd_handler( connection.fd, NULL, NULL, ( event_fd_callback ) check_connected, NULL );
      set_writable( connection.fd, true );
      break;

    default:
      error( "Failed to connect ( fd = %d, errno = %s [%d] ).", connection.fd, strerror( err ), err );
      clear_connection();
      return;
  }
}
示例#14
0
    /*!
     * Push a list of elements onto the head of the lifo queue.
     *
     *  @param[in] listHead     A list of ELEMENTs linked through their _next pointers.  The
     *                           last element's _next pointer must be NULL.
     *  @param[in] listTail     The last element in the list.
     */
    void PushList(ELEMENT *listHead, ELEMENT *listTail)
    {
        HEAD oldHead;
        HEAD newHead;
        EXPONENTIAL_BACKOFF<STATS> backoff(1, _stats);
        do
        {
            backoff.Delay();

            oldHead._word = OPS::Load(&_head._word);
            listTail->_next = _heap->Pointer(oldHead._fields._iElement);
            newHead._fields._iElement = _heap->Index(listHead);
            newHead._fields._counter = oldHead._fields._counter+1;

            // BARRIER_CS_PREV below ensures that all processors will see the write to _next
            // before the element is inserted into the queue.
        }
        while (!OPS::CompareAndDidSwap(&_head._word, oldHead._word, newHead._word, BARRIER_CS_PREV));
    }
示例#15
0
 // request permission to abort enemy tx.  For now, policies are totally
 // local, so we don't need a parameter to this method
 ConflictResolutions onConflict()
 {
     if (policy == POLITE) {
         if (tries > MAX_BACKOFF_RETRIES)
             return AbortOther;
         backoff();
         return Wait;
     }
     else if (policy == PATIENT) {
         return Wait;
     }
     else if (policy == AGGRESSIVE) {
         return AbortOther;
     }
     else if (policy == TIMID) {
         return AbortSelf;
     }
     return Wait;
 }
示例#16
0
    /*!
     * Atomically clears the lifo queue and returns a pointer to the previous contents.
     *
     * @return  Returns a pointer to a linked list with the previous elements in
     *           in the queue, or NULL if the queue was already empty.
     */
    ELEMENT *Clear()
    {
        HEAD oldHead;
        HEAD newHead;
        EXPONENTIAL_BACKOFF<STATS> backoff(1, _stats);

        newHead._fields._iElement = 0;
        do
        {
            backoff.Delay();
            oldHead._word = OPS::Load(&_head._word);
            newHead._fields._counter = oldHead._fields._counter+1;
        }
        while (!OPS::CompareAndDidSwap(&_head._word, oldHead._word, newHead._word, BARRIER_CS_NEXT));

        // BARRIER_CS_NEXT above ensures that all processors see that the elements are
        // removed from the list before the caller starts changing them.

        return _heap->Pointer(oldHead._fields._iElement);
    }
示例#17
0
        void run() {

            int maxSleepTimeMillis = 1000;

            Backoff backoff( maxSleepTimeMillis, maxSleepTimeMillis * 2 );

            // Double previous sleep duration
            ASSERT_EQUALS( backoff.getNextSleepMillis( 0,   0, 0 ), 1 );
            ASSERT_EQUALS( backoff.getNextSleepMillis( 2,   0, 0 ), 4 );
            ASSERT_EQUALS( backoff.getNextSleepMillis( 256, 0, 0 ), 512 );

            // Make sure our backoff increases to the maximum value
            ASSERT_EQUALS( backoff.getNextSleepMillis( maxSleepTimeMillis - 200, 0, 0 ), maxSleepTimeMillis );
            ASSERT_EQUALS( backoff.getNextSleepMillis( maxSleepTimeMillis * 2, 0, 0 ), maxSleepTimeMillis );

            // Make sure that our backoff gets reset if we wait much longer than the maximum wait
            unsigned long long resetAfterMillis = maxSleepTimeMillis + maxSleepTimeMillis * 2;
            ASSERT_EQUALS( backoff.getNextSleepMillis( 20, resetAfterMillis, 0), 40 ); // no reset here
            ASSERT_EQUALS( backoff.getNextSleepMillis( 20, resetAfterMillis + 1, 0), 1 ); // reset expected

        }
示例#18
0
int lumberjack_ensure_connected(struct lumberjack *lumberjack) {
  int rc;
  struct backoff sleeper;
  backoff_init(&sleeper, &MIN_SLEEP, &MAX_SLEEP);

  while (!lumberjack_connected(lumberjack)) {
    backoff(&sleeper);
    rc = lumberjack_connect(lumberjack);
    if (rc != 0) {
      flog(stdout, "Connection attempt to %s:%hd failed: %s",
           lumberjack->host, lumberjack->port, strerror(errno));
    } else {
      /* we're connected! */
      backoff_clear(&sleeper);
    }
  }
  insist(lumberjack->fd > 0,
         "lumberjack->fd must be > 0 after a connect, was %d", lumberjack->fd);
  insist(lumberjack->ssl != NULL,
         "lumberjack->ssl must not be NULL after a connect");
  return 0;
} /* lumberjack_connect_block */
int main(int argc, char *argv[])
{
	int retc = 0;
	int ret;

	char *hostfile = NULL;
	char *cachefile = NULL;
	char *xml = NULL;
	char *xmlfile = NULL;

	int cachefd = -1;

	char value[64];
	char units[64];

	int retry_count = 0, ret2;

	if (get_config(argc, argv) < 0) {
		retc = 2;
		goto cleanup;
	}

	if (config.heartbeat > 0) {
		debug("Checking heartbeat for %s with threshold %d\n",
		      config.host, config.heartbeat);
	} else {
		debug("Checking %s for %s metric\n",
		      config.host, config.metric);
	}

	hostfile = get_full_cache_path(config.cachepath, config.host);
	cachefile = get_full_cache_path(config.cachepath, config.cachename);

retry:
	debug("Checking cache at %s\n", cachefile);
	ret = check_cache_age(cachefile);
	if (ret < 0) {
		printf("ERROR: Unable to check cache age.\n");
		retc = 2;
		goto cleanup;
	}

	if (ret < config.max_age) {
		debug("Cache age is %d\n", ret);
	} else {
		debug("Cache age greater than configured max (%d >= %d)\n", ret, config.max_age);
		debug("Connecting to %s on port %d\n", config.gmetad_host, config.gmetad_port);
		ret = fetch_xml(config.gmetad_host, config.gmetad_port, &xml);
		if (ret < 0) {
			printf("ERROR: Unable to get XML data: %d.\n", ret);
			retc = 2;
			goto cleanup;
		}

		debug("Read %d bytes from %s\n", ret, config.gmetad_host);
		if (config.dump) {
			xmlfile = calloc((strlen(config.cachepath) + 9), sizeof(char));
			sprintf(xmlfile, "%s/dump.xml", config.cachepath);

			debug("Dumping XML to %s\n", xmlfile);
			if (write_xml(xml, ret, xmlfile) < 0) {
				printf("ERROR: Unable to dump XML.\n");
				retc = 2;
				goto cleanup;
			}
		}

		ret2 = get_cache_lock(cachefile, &cachefd);
		if (ret2 < 0) {
			if (retry_count == MAX_RETRY) {
				printf("ERROR: Unable to get cache lock after retrying %d times. Stale lock?", retry_count);
				retc = 2;
				goto cleanup;
			} else {
				backoff(retry_count / 2.0);
			}

			retry_count++;
			goto retry;
		}

		debug("Parsing XML into %s\n", config.cachepath);
		ret = parse_xml_to_cache(xml, ret, config.cachepath, cachefile);
		if (ret < 0) {
			printf("ERROR: Unable to parse XML.\n");
			retc = 2;
			goto cleanup;
		}

		touch_cache_lock(cachefile);
		release_cache_lock(cachefile, &cachefd);
	}

	if (config.heartbeat > 0) {
		strcpy(config.metric, "#REPORTED");
	}

	if (locate_hostfile(hostfile) < 0) {
		printf("CRITICAL - Unable to locate cache file for %s\n", config.host);
		retc = 2;
		goto cleanup;
	}

	debug("Fetching %s metric from cache at %s\n", config.metric, hostfile);

	ret = fetch_value_from_cache(hostfile, config.metric, value, units);
	if (ret < 0) {
		printf("CRITICAL - Unable to read cache at %s\n", hostfile);
		retc = 2;
		goto cleanup;
	} else if (ret == 0) {
		printf("CRITICAL - Metric %s not found\n", config.metric);
		retc = 2;
		goto cleanup;
	}

	debug("Checking...\n");

	if (config.heartbeat > 0) {
		int diff = time(NULL) - strtol(value, NULL, 10);
		if (diff > config.heartbeat) {
			printf("CRITICAL - %d over threshold %d\n", diff, config.heartbeat);
			retc = 2;
			goto cleanup;
		} else {
			printf("OK - %d\n", diff);
			goto cleanup;
		}
	}

	if (threshold_check(config.critical, value)) {
		printf("CRITICAL - %s %s\n", value, units);
		retc = 2;
	} else {
		if (threshold_check(config.warning, value)) {
			printf("WARNING - %s %s\n", value, units);
			retc = 1;
		} else {
			printf("OK - %s %s\n", value, units);
		}
	}

cleanup:
	if (cachefd >= 0) {
		release_cache_lock(cachefile, &cachefd);
	}

	if (xml != NULL)
		free(xml);

	if (xmlfile != NULL)
		free(xmlfile);

	if (hostfile != NULL)
		free(hostfile);

	if (cachefile != NULL)
		free(cachefile);

	exit(retc);
}
示例#20
0
void *emitter(void *arg) {
  int rc;
  struct emitter_config *config = arg;
  insist(config->zmq != NULL, "zmq is NULL");
  insist(config->zmq_endpoint != NULL, "zmq_endpoint is NULL");
  insist(config->ssl_ca_path != NULL, "ssl_ca_path is NULL");
  insist(config->window_size > 0, "window_size (%d) must be positive",
         (int)config->window_size);
  insist(config->host != NULL, "host is NULL");
  insist(config->port > 0, "port (%hd) must be positive", config->port);

  void *socket = zmq_socket(config->zmq, ZMQ_PULL);
  insist(socket != NULL, "zmq_socket() failed: %s", strerror(errno));
  int64_t hwm = 100;
  //zmq_setsockopt(socket, ZMQ_HWM, &hwm, sizeof(hwm));
  zmq_compat_set_recvhwm(socket, hwm);
  rc = zmq_bind(socket, config->zmq_endpoint);
  insist(rc != -1, "zmq_bind(%s) failed: %s", config->zmq_endpoint,
         zmq_strerror(errno));

  struct timespec start;
  clock_gettime(CLOCK_MONOTONIC, &start);
  //long count = 0;

  struct backoff sleeper;
  backoff_init(&sleeper, &MIN_SLEEP, &MAX_SLEEP);

  struct lumberjack *lumberjack;
  lumberjack = lumberjack_new(config->host, config->port, config->window_size);
  insist(lumberjack != NULL, "lumberjack_new failed");
  lumberjack->ring_size = config->window_size;

  if (config->ssl_ca_path != NULL) {
    rc = lumberjack_set_ssl_ca(lumberjack, config->ssl_ca_path);
    insist(rc == 0, "lumberjack_set_ssl_ca failed, is '%s' a valid ssl cert?",
           config->ssl_ca_path);
  }

  long count = 0;
  long bytes = 0;

  zmq_pollitem_t items[1];

  items[0].socket = socket;
  items[0].events = ZMQ_POLLIN;

  int can_flush = 0;
  for (;;) {
    /* Receive an event from a harvester and put it in the queue */
    zmq_msg_t message;

    rc = zmq_msg_init(&message);
    insist(rc == 0, "zmq_msg_init failed");
    rc = zmq_poll(items, 1, 1000000 /* microseconds */);

    if (rc == 0) {
      /* poll timeout. We're idle, so let's flush and back-off. */
      if (can_flush) {
        /* only flush if there's something to flush... */
        flog(stdout, "flushing since nothing came in over zmq");
        /* We flush here to keep slow feeders closer to real-time */
        rc = lumberjack_flush(lumberjack);
        can_flush = 0;
        if (rc != 0) {
          /* write failure, reconnect (which will resend) and such */
          lumberjack_disconnect(lumberjack);
          lumberjack_ensure_connected(lumberjack);
        }
      }
      backoff(&sleeper);

      /* Restart the loop - checking to see if there's any messages */
      continue;
    } 

    /* poll successful, read a message */
    //rc = zmq_recv(socket, &message, 0);
    rc = zmq_compat_recvmsg(socket, &message, 0);
    insist(rc == 0 /*|| errno == EAGAIN */,
           "zmq_recv(%s) failed (returned %d): %s",
           config->zmq_endpoint, rc, zmq_strerror(errno));

    /* Clear the backoff timer since we received a message successfully */
    backoff_clear(&sleeper);

    /* Write the data over lumberjack. This will handle any
     * connection/reconnection/ack issues */
    lumberjack_send_data(lumberjack, zmq_msg_data(&message),
                         zmq_msg_size(&message));
    /* Since we sent data, let it be known that we can flush if idle */
    can_flush = 1;
    /* Stats for debugging */
    count++;
    bytes += zmq_msg_size(&message);

    zmq_msg_close(&message);

    if (count == 10000) {
      struct timespec now;
      clock_gettime(CLOCK_MONOTONIC, &now);
      double s = (start.tv_sec + 0.0) + (start.tv_nsec / 1000000000.0);
      double n = (now.tv_sec + 0.0) + (now.tv_nsec / 1000000000.0);
      flog(stdout, "Rate: %f (bytes: %f)\n", (count + 0.0) / (n - s), (bytes + 0.0) / (n - s));
      struct rusage rusage;
      rc = getrusage(RUSAGE_SELF, &rusage);
      insist(rc == 0, "getrusage failed: %s\n", strerror(errno));
      flog(stdout, "cpu user/system: %d.%06d / %d.%06d\n",
           (int)rusage.ru_utime.tv_sec, (int)rusage.ru_utime.tv_usec,
           (int)rusage.ru_stime.tv_sec, (int)rusage.ru_stime.tv_usec);
      clock_gettime(CLOCK_MONOTONIC, &start);
      bytes = 0;
      count = 0;
    }
  } /* forever */
} /* emitter */
示例#21
0
文件: pusher.c 项目: jdee/dubsar
int
main(int argc, char** argv)
{
    signal(SIGINT, signalHandler);
    signal(SIGTERM, signalHandler);

    int s = -1;
    int success = 0;
    SSL* tls = NULL;

    /*
     * Parse and validate args
     */
    if (parseArgs(argc, argv))
    {
        usage(argv[0]);
        return 1;
    }

    // make logs a little easier to read/more useful
    setvbuf(stderr, NULL, _IOLBF, 0);

    if (broadcast)
    {
        timestamp_f(stderr);
        fprintf(stderr, "broadcast environment: %s\n", (production ? "prod" : "dev"));
    }
    else if (noSend == 0)
    {
        timestamp_f(stderr);
        fprintf(stderr, "device token: %s\n", deviceToken);
    }
    else
    {
        timestamp_f(stderr);
        fprintf(stderr, "build and report only; no send\n");
    }

    timestamp_f(stderr);
    fprintf(stderr, "cert. file: %s. passphrase loaded\n", certPath);
    timestamp_f(stderr);
    fprintf(stderr, "database path: %s\n", databasePath);
    timestamp_f(stderr);
    fprintf(stderr, "message: \"%s\"\n", message);
    timestamp_f(stderr);
    fprintf(stderr, "host: %s, port: %d\n", host, port);
    timestamp_f(stderr);
    fprintf(stderr, "url: %s\n", url);
    timestamp_f(stderr);
    fprintf(stderr, "wotd: %d\n", wotd);

    time_t expiration = time(NULL) + 43200;
    
    void* notificationPayload = NULL;
    size_t notificationPayloadSize = 0;
    if (buildNotificationPayload(wotd, broadcast, production, deviceToken,
        databasePath, message, url, wotdExpiration, expiration,
        &notificationPayload, &notificationPayloadSize))
    {
        timestamp_f(stderr);
        fprintf(stderr, "failed to build notification payload\n");
        return -1;
    }
    timestamp_f(stderr);
    fprintf(stderr, "notification length is %ld\n", notificationPayloadSize);

    if (noSend)
    {
        free(notificationPayload);
        return 0;
    }

    /*
     * Connect to server
     */

    int nb = 0;
    int b = 0;
    while (!success && !_shutdown && time(NULL) < expiration)
    {
        while (!_shutdown && time(NULL) < expiration && s < 0)
        {
            timestamp_f(stderr);
            fprintf(stderr, "attempting connection to %s:%d\n", host, port);
            s = socketConnect(host, port);
            if (s < 0)
            {
                timestamp_f(stderr);
                fprintf(stderr, "connection to %s:%d failed\n", host, port);
                b = backoff();

                if (_shutdown || time(NULL) + b >= expiration)
                {
                    free(notificationPayload);
                    return 1;
                }

                timestamp_f(stderr);
                fprintf(stderr, "will try again in %d s\n", b);
                sleep(b);
                continue;
            }
        
            timestamp_f(stderr);
            fprintf(stderr, "successfully connected to %s:%d\n", host, port);
        }
    
        if (_shutdown || time(NULL) >= expiration)
        {
            free(notificationPayload);
            if (s >= 0) close(s);
            return 1;
        }

        tls = makeTlsConnection(s, certPath, passphrase, cacertPath);
        if (!tls)
        {
            timestamp_f(stderr);
            fprintf(stderr, "TLS handshake failed\n");
            close(s);
            s = -1;
            b = backoff();

            if (_shutdown || time(NULL) + b >= expiration)
            {
                free(notificationPayload);
                return 1;
            }

            timestamp_f(stderr);
            fprintf(stderr, "will reconnect in %d s\n", b);
            sleep(b);
            continue;
        }

        if (_shutdown)
        {
            free(notificationPayload);
            stopTlsConnection(tls);
            return 1;
        }
    
        nb = SSL_write(tls, notificationPayload, notificationPayloadSize);
        if (nb != notificationPayloadSize)
        {
            timestamp_f(stderr);
            fprintf(stderr, "SSL_write: %s", ERR_error_string(nb, NULL));
            stopTlsConnection(tls);
            s = -1;
            tls = NULL;
            b = backoff();

            if (_shutdown || time(NULL) + b >= expiration)
            {
                free(notificationPayload);
                return 1;
            }

            timestamp_f(stderr);
            fprintf(stderr, "will reconnect in %d s\n", b);
            sleep(b);
            continue;
        }
    
        timestamp_f(stderr);
        fprintf(stderr, "successfully wrote %d bytes\n", nb);
        free(notificationPayload);
        success = 1;
    }

    if (_shutdown || time(NULL) >= expiration)
    {
        if (tls) stopTlsConnection(tls);
        else if (s >= 0) close(s);
        return 1;
    }

    /*
     * Check for error response packet(s)
     */
    timestamp_f(stderr);
    fprintf(stderr, "checking for error responses (10 s)\n");
    char errorResponse[6];
    
    int numErrors;
    for (numErrors=0;
        (nb=SSL_read(tls, errorResponse, sizeof(errorResponse))) == sizeof(errorResponse);
        ++numErrors)
    {
        uint32_t identifier;
        memcpy(&identifier, errorResponse+2, sizeof(identifier));

        timestamp_f(stderr);
        fprintf(stderr, "APNS error response: command %d, status %d, identifier %u (network order)\n", errorResponse[0], errorResponse[1], identifier);
    }

    if (nb == 0 || (nb == -1 && errno == EAGAIN))
    {
        if (numErrors == 0)
        {
            timestamp_f(stderr);
            fprintf(stderr, "APNS push successfully sent\n");
        }
    }
    else if (nb == -1)
    {
        timestamp_f(stderr);
        perror("SSL_read");
    }
    else {
        timestamp_f(stderr);
        fprintf(stderr, "SSL_read error %d: %s", nb, ERR_error_string(nb, NULL));
    }

    stopTlsConnection(tls);
    
    return 0;
}
示例#22
0
static bool
try_connect() {
  assert( connection.state != CONNECTED );

  int fd = socket( PF_INET, SOCK_STREAM, 0 );
  if ( fd < 0 ) {
    error( "Failed to create a socket ( ret = %d, errno = %s [%d] ).",
           fd, strerror( errno ), errno );
    return false;
  }

  int flag = 1;
  int ret = setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof( flag ) );
  if ( ret < 0 ) {
    error( "Failed to set socket options ( fd = %d, ret = %d, errno = %s [%d] ).",
           fd, ret, strerror( errno ), errno );
    return false;
  }

  ret = fcntl( fd, F_SETFL, O_NONBLOCK );
  if ( ret < 0 ) {
    error( "Failed to enable non-blocking mode ( fd = %d, ret = %d, errno = %s [%d] ).",
           fd, ret, strerror( errno ), errno );

    close( fd );
    return false;
  }

  connection.fd = fd;

  struct sockaddr_in addr;
  memset( &addr, 0, sizeof( struct sockaddr_in ) );
  addr.sin_family = AF_INET;
  addr.sin_port = htons( connection.port );
  addr.sin_addr.s_addr = htonl( connection.ip );

  transit_state( CONNECTING );

  ret = connect( connection.fd, ( struct sockaddr * ) &addr, sizeof( struct sockaddr_in ) );
  if ( ret < 0 ) {
    switch ( errno ) {
      case EINTR:
      case EAGAIN:
      case ECONNREFUSED:
      case ENETUNREACH:
      case ETIMEDOUT:
        warn( "Failed to connect ( fd = %d, ret = %d, errno = %s [%d] ).",
              connection.fd, ret, strerror( errno ), errno );
        backoff();
        return true;

      case EINPROGRESS:
        break;

      default:
        error( "Failed to connect ( fd = %d, ret = %d, errno = %s [%d] ).",
               connection.fd, ret, strerror( errno ), errno );
        clear_connection();
        return false;
    }
  }

  set_fd_handler( connection.fd, NULL, NULL, ( event_fd_callback ) check_connected, NULL );
  set_writable( connection.fd, true );

  return true;
}