Пример #1
0
bool LeakyBucket::ratelimit(int tokens) {
	// First remove tokens we leaked over time
	time_point tnow = now();
	long ms = millisecondsBetween(lastUpdate, tnow);

	long drainTokens = (ms * tokensPerSec) / 1000;

	// Prevent constant starvation due to too many updates
	if (drainTokens > 0) {
		this->lastUpdate = tnow;

		this->currentTokens -= drainTokens;
		if (this->currentTokens < 0) {
			this->currentTokens = 0;
		}
	}

	// Then try to add tokens
	bool limit = this->currentTokens > ((static_cast<long>(maxTokens)) - tokens);

	// If the bucket is not overflowed, allow message and add tokens
	if (!limit) {
		this->currentTokens += tokens;
	}

	return limit;
}
Пример #2
0
int
asyncExecuteAlarmCallback (AsyncAlarmData *ad, long int *timeout) {
  if (ad) {
    Queue *alarms = ad->alarmQueue;

    if (alarms) {
      Element *element = processQueue(alarms, testInactiveAlarm, NULL);

      if (element) {
        AlarmEntry *alarm = getElementItem(element);
        TimeValue now;
        long int milliseconds;

        getMonotonicTime(&now);
        milliseconds = millisecondsBetween(&now, &alarm->time);

        if (milliseconds <= 0) {
          AsyncAlarmCallback *callback = alarm->callback;
          const AsyncAlarmCallbackParameters parameters = {
            .now = &now,
            .data = alarm->data
          };

          logSymbol(LOG_CATEGORY(ASYNC_EVENTS), callback, "alarm starting");
          alarm->active = 1;
          if (callback) callback(&parameters);
          alarm->active = 0;

          if (alarm->reschedule) {
            adjustTimeValue(&alarm->time, alarm->interval);
            getMonotonicTime(&now);
            if (compareTimeValues(&alarm->time, &now) < 0) alarm->time = now;
            requeueElement(element);
          } else {
            alarm->cancel = 1;
          }

          if (alarm->cancel) deleteElement(element);
          return 1;
        }

        if (milliseconds < *timeout) {
          *timeout = milliseconds;
          logSymbol(LOG_CATEGORY(ASYNC_EVENTS), alarm->callback, "next alarm: %ld", *timeout);
        }
      }
    }
  }

  return 0;
}
Пример #3
0
bool HTTPTransaction::maybeDelayForRateLimit() {
  if (egressLimitBytesPerMs_ <= 0) {
    // No rate limiting
    return false;
  }

  if (numLimitedBytesEgressed_ == 0) {
    // If we haven't egressed any bytes yet, don't delay.
    return false;
  }

  int64_t limitedDurationMs = (int64_t) millisecondsBetween(
    getCurrentTime(),
    startRateLimit_
  ).count();

  // Algebra!  Try to figure out the next time send where we'll
  // be allowed to send at least 1 full packet's worth.  The
  // formula we're using is:
  //   (bytesSoFar + packetSize) / (timeSoFar + delay) == targetRateLimit
  std::chrono::milliseconds requiredDelay(
    (
     ((int64_t)numLimitedBytesEgressed_ + kApproximateMTU) -
     ((int64_t)egressLimitBytesPerMs_ * limitedDurationMs)
    ) / (int64_t)egressLimitBytesPerMs_
  );

  if (requiredDelay.count() <= 0) {
    // No delay required
    return false;
  }

  if (requiredDelay > kRateLimitMaxDelay) {
    // The delay should never be this long
    VLOG(4) << "ratelim: Required delay too long (" << requiredDelay.count()
      << "ms), ignoring";
    return false;
  }

  // Delay required

  egressRateLimited_ = true;

  timeout_.scheduleTimeout(&rateLimitCallback_, requiredDelay);

  notifyTransportPendingEgress();
  return true;
}
Пример #4
0
static int
awaitCursorMotion (RoutingData *routing, int direction, const CursorAxisEntry *axis) {
  int moved = 0;
  long int timeout = routing->timeSum / routing->timeCount;
  TimeValue start;

  int trgy = routing->cury;
  int trgx = routing->curx;

  routing->oldy = routing->cury;
  routing->oldx = routing->curx;

  axis->adjustCoordinate(&trgy, &trgx, direction);
  getMonotonicTime(&start);

  while (1) {
    long int time;
    TimeValue now;

    int oldy;
    int oldx;

    approximateDelay(ROUTING_INTERVAL);
    getMonotonicTime(&now);
    time = millisecondsBetween(&start, &now) + 1;

    {
      int row = routing->cury + routing->verticalDelta;
      int bestRow = row;
      int bestLength = 0;

      do {
        ScreenCharacter buffer[routing->screenColumns];
        if (!readScreenRow(routing, buffer, row)) break;

        {
          int before = routing->curx;
          int after = before;

          while (buffer[before].text == routing->rowBuffer[before].text)
            if (--before < 0)
              break;

          while (buffer[after].text == routing->rowBuffer[after].text)
            if (++after >= routing->screenColumns)
              break;

          {
            int length = after - before - 1;
            if (length > bestLength) {
              bestRow = row;
              if ((bestLength = length) == routing->screenColumns) break;
            }
          }
        }

        row -= direction;
      } while ((row >= 0) && (row < routing->screenRows));

      routing->verticalDelta = bestRow - routing->cury;
    }

    oldy = routing->cury;
    oldx = routing->curx;
    if (!getCurrentPosition(routing)) return 0;

    if ((routing->cury != oldy) || (routing->curx != oldx)) {
      logRouting("moved: [%d,%d] -> [%d,%d] (%dms)",
                 oldx, oldy, routing->curx, routing->cury, time);

      if (!moved) {
        moved = 1;
        timeout = (time * 2) + 1;

        routing->timeSum += time * 8;
        routing->timeCount += 1;
      }

      if ((routing->cury == trgy) && (routing->curx == trgx)) break;

      if (ROUTING_INTERVAL) {
        start = now;
      } else {
        approximateDelay(1);
        getMonotonicTime(&start);
      }
    } else if (time > timeout) {
      if (!moved) logRouting("timed out: %ldms", timeout);
      break;
    }
  }

  return 1;
}
Пример #5
0
long int millisecondsSince(const struct timeval *from)
{
	struct timeval now;
	gettimeofday(&now, NULL);
	return millisecondsBetween(from, &now);
}