예제 #1
0
def _gen_queue_number(timestamp,
                      priority,
                      scale_factor_us=365 * 24 * 60 * 60 * 1000 * 1000):
    """Generates a 64 bit packed value used for TaskToRun.queue_number.

  The lower value the higher importance.

  Arguments:
  - timestamp: datetime.datetime when the TaskRequest was filed in. This value
        at 1µs is used for the FIFO ordering.
  - priority: priority of the TaskRequest. It's a 8 bit integer. Lower is higher
        priority.
  - scale_factor_us: multiplicative factor of the priority versus time. Higher
        values means that priority will become a strict stack of FIFO queues.
        Lower values means a blend between priority and time, where lower
        priority tasks (higher `priority` value) will slowly preempt higher
        priority tasks (lower `priority` value) when they waited long enough.
        Default is each priority increment is worth one year.

  Returns:
    queue_number is a 63 bit integer with timestamp at µs resolution plus
    priority scaled with scale_factor_us as a delay factor.
  """
    assert isinstance(timestamp, datetime.datetime), '%r' % timestamp
    assert isinstance(priority, int), '%r' % priority
    assert isinstance(scale_factor_us, (int, long)), '%r' % scale_factor_us
    task_request.validate_priority(priority)
    assert 0 <= priority <= 255, 'Just for clarity, validate_priority() checks it'
    if not 0 <= scale_factor_us <= 2**54:
        raise ValueError('Invalid scale_factor_us (%s)' % scale_factor_us)

    value = int(
        round((timestamp - utils.EPOCH).total_seconds() * 1000. * 1000.))
    assert 0 <= value < 2**58, hex(value)
    return value + priority * scale_factor_us
예제 #2
0
def _gen_queue_number(
    timestamp, priority, scale_factor_us=365*24*60*60*1000*1000):
  """Generates a 64 bit packed value used for TaskToRun.queue_number.

  The lower value the higher importance.

  Arguments:
  - timestamp: datetime.datetime when the TaskRequest was filed in. This value
        at 1µs is used for the FIFO ordering.
  - priority: priority of the TaskRequest. It's a 8 bit integer. Lower is higher
        priority.
  - scale_factor_us: multiplicative factor of the priority versus time. Higher
        values means that priority will become a strict stack of FIFO queues.
        Lower values means a blend between priority and time, where lower
        priority tasks (higher `priority` value) will slowly preempt higher
        priority tasks (lower `priority` value) when they waited long enough.
        Default is each priority increment is worth one year.

  Returns:
    queue_number is a 63 bit integer with timestamp at µs resolution plus
    priority scaled with scale_factor_us as a delay factor.
  """
  assert isinstance(timestamp, datetime.datetime), '%r' % timestamp
  assert isinstance(priority, int), '%r' % priority
  assert isinstance(scale_factor_us, (int, long)), '%r' % scale_factor_us
  task_request.validate_priority(priority)
  assert 0 <= priority <= 255, 'Just for clarity, validate_priority() checks it'
  if not 0 <= scale_factor_us <= 2**54:
    raise ValueError('Invalid scale_factor_us (%s)' % scale_factor_us)

  value = int(round((timestamp - utils.EPOCH).total_seconds() * 1000. * 1000.))
  assert 0 <= value < 2**58, hex(value)
  return value + priority * scale_factor_us
예제 #3
0
def _gen_queue_number(dimensions_hash, timestamp, priority):
    """Generates a 63 bit packed value used for TaskToRun.queue_number.

  Arguments:
  - dimensions_hash: 32 bit integer to classify in a queue.
  - timestamp: datetime.datetime when the TaskRequest was filed in. This value
        is used for FIFO or LIFO ordering (depending on configuration) with a
        100ms granularity; the year is ignored.
  - priority: priority of the TaskRequest. It's a 8 bit integer. Lower is higher
        priority.

  Returns:
    queue_number is a 63 bit integer with dimension_hash, timestamp at 100ms
    resolution plus priority.
  """
    # dimensions_hash should be 32 bits but on AppEngine, which is using 32 bits
    # python, it is silently upgraded to long.
    assert isinstance(dimensions_hash, (int, long)), repr(dimensions_hash)
    assert dimensions_hash > 0 and dimensions_hash <= 0xFFFFFFFF, hex(
        dimensions_hash)
    assert isinstance(timestamp, datetime.datetime), repr(timestamp)
    task_request.validate_priority(priority)

    # Ignore the year.

    if config.settings().use_lifo:
        next_year = datetime.datetime(timestamp.year + 1, 1, 1)
        # It is guaranteed to fit 32 bits but upgrade to long right away to ensure
        # assert works.
        t = long(round((next_year - timestamp).total_seconds() * 10.))
    else:
        year_start = datetime.datetime(timestamp.year, 1, 1)
        # It is guaranteed to fit 32 bits but upgrade to long right away to ensure
        # assert works.
        t = long(round((timestamp - year_start).total_seconds() * 10.))

    assert t >= 0 and t <= 0x7FFFFFFF, (hex(t), dimensions_hash, timestamp,
                                        priority)
    # 31-22 == 9, leaving room for overflow with the addition.
    # 0x3fc00000 is the priority mask.
    # It is important that priority mixed with time is an addition, not a bitwise
    # or.
    low_part = (long(priority) << 22) + t
    assert low_part >= 0 and low_part <= 0xFFFFFFFF, '0x%X is out of band' % (
        low_part)
    # int may be 32 bits, upgrade to long for consistency, albeit this is
    # significantly slower.
    high_part = long(dimensions_hash) << 31
    return high_part | low_part
예제 #4
0
 def test_validate_priority(self):
     with self.assertRaises(TypeError):
         task_request.validate_priority('1')
     with self.assertRaises(datastore_errors.BadValueError):
         task_request.validate_priority(-1)
     with self.assertRaises(datastore_errors.BadValueError):
         task_request.validate_priority(task_request.MAXIMUM_PRIORITY + 1)
     task_request.validate_priority(0)
     task_request.validate_priority(1)
     task_request.validate_priority(task_request.MAXIMUM_PRIORITY)
예제 #5
0
 def test_validate_priority(self):
   with self.assertRaises(TypeError):
     task_request.validate_priority('1')
   with self.assertRaises(datastore_errors.BadValueError):
     task_request.validate_priority(-1)
   with self.assertRaises(datastore_errors.BadValueError):
     task_request.validate_priority(task_request.MAXIMUM_PRIORITY+1)
   task_request.validate_priority(0)
   task_request.validate_priority(1)
   task_request.validate_priority(task_request.MAXIMUM_PRIORITY)