def read_many(self, start_sequence, min_count, max_count): """ Reads a batch of items from the Ringbuffer. If the number of available items after the first read item is smaller than the max_count, these items are returned. So it could be the number of items read is smaller than the max_count. If there are less items available than min_count, then this call blocks. Reading a batch of items is likely to perform better because less overhead is involved. :param start_sequence: (long), the start_sequence of the first item to read. :param min_count: (int), the minimum number of items to read. :param max_count: (int), the maximum number of items to read. :return: (Sequence), the list of read items. """ check_not_negative(start_sequence, "sequence can't be smaller than 0") check_true(max_count >= min_count, "max count should be greater or equal to min count") check_true(min_count <= self.capacity().result(), "min count should be smaller or equal to capacity") check_true(max_count < MAX_BATCH_SIZE, "max count can't be greater than %d" % MAX_BATCH_SIZE) return self._encode_invoke( ringbuffer_read_many_codec, response_handler=self._read_many_response_handler, start_sequence=start_sequence, min_count=min_count, max_count=max_count, filter=None)
def init(self, permits): """ Try to initialize this Semaphore instance with the given permit count. :param permits: (int), the given permit count. :return: (bool), ``true`` if initialization success. """ check_not_negative(permits, "Permits cannot be negative!") return self._encode_invoke(semaphore_init_codec, permits=permits)
def try_set_count(self, count): """ Sets the count to the given value if the current count is zero. If count is not zero, this method does nothing and returns ``false``. :param count: (int), the number of times count_down() must be invoked before threads can pass through await(). :return: (bool), ``true`` if the new count was set, ``false`` if the current count is not zero. """ check_not_negative(count, "count can't be negative") return self._encode_invoke(count_down_latch_try_set_count_codec, count=count)
def reduce_permits(self, reduction): """ Shrinks the number of available permits by the indicated reduction. This method differs from acquire in that it does not block waiting for permits to become available. :param reduction: (int), the number of permits to remove. """ check_not_negative(reduction, "Reduction cannot be negative!") return self._encode_invoke(semaphore_reduce_permits_codec, reduction=reduction)
def read_one(self, sequence): """ Reads one item from the Ringbuffer. If the sequence is one beyond the current tail, this call blocks until an item is added. Currently it isn't possible to control how long this call is going to block. :param sequence: (long), the sequence of the item to read. :return: (object), the read item. """ check_not_negative(sequence, "sequence can't be smaller than 0") return self._encode_invoke(ringbuffer_read_one_codec, sequence=sequence)
def release(self, permits=1): """ Releases one or given number of permits, increasing the number of available permits by one or that amount. There is no requirement that a thread that releases a permit must have acquired that permit by calling one of the acquire methods. Correct usage of a semaphore is established by programming convention in the application. :param permits: (int), the number of permits to release (optional). """ check_not_negative(permits, "Permits cannot be negative!") return self._encode_invoke(semaphore_release_codec, permits=permits)
def read_many(self, start_sequence, min_count, max_count): """Reads a batch of items from the Ringbuffer. If the number of available items after the first read item is smaller than the max_count, these items are returned. So it could be the number of items read is smaller than the max_count. If there are less items available than min_count, then this call blocks. Reading a batch of items is likely to perform better because less overhead is involved. Args: start_sequence (int): The start_sequence of the first item to read. min_count (int): The minimum number of items to read. max_count (int): The maximum number of items to read. Returns: hazelcast.future.Future[list]: The list of read items. """ check_not_negative(start_sequence, "sequence can't be smaller than 0") check_true(max_count >= min_count, "max count should be greater or equal to min count") check_true(max_count < MAX_BATCH_SIZE, "max count can't be greater than %d" % MAX_BATCH_SIZE) future = Future() request = ringbuffer_read_many_codec.encode_request( self.name, start_sequence, min_count, max_count, None) def handler(message): return ImmutableLazyDataList( ringbuffer_read_many_codec.decode_response(message)["items"], self._to_object) def check_capacity(capacity): try: capacity = capacity.result() check_true( min_count <= capacity, "min count: %d should be smaller or equal to capacity: %d" % (min_count, capacity), ) f = self._invoke(request, handler) f.add_done_callback(set_result) except Exception as e: future.set_exception(e) def set_result(f): try: future.set_result(f.result()) except Exception as e: future.set_exception(e) self.capacity().add_done_callback(check_capacity) return future
def read_many(self, start_sequence, min_count, max_count): check_not_negative(start_sequence, "sequence can't be smaller than 0") check_true(max_count >= min_count, "max count should be greater or equal to min count") check_true(min_count <= self.capacity().result(), "min count should be smaller or equal to capacity") check_true(max_count < MAX_BATCH_SIZE, "max count can't be greater than %d" % MAX_BATCH_SIZE) return self._encode_invoke( ringbuffer_read_many_codec, response_handler=self._read_many_response_handler, start_sequence=start_sequence, min_count=min_count, max_count=max_count, filter=None, )
def read_one(self, sequence): """ Reads one item from the Ringbuffer. If the sequence is one beyond the current tail, this call blocks until an item is added. Currently it isn't possible to control how long this call is going to block. :param sequence: (long), the sequence of the item to read. :return: (object), the read item. """ check_not_negative(sequence, "sequence can't be smaller than 0") def handler(message): return self._to_object( ringbuffer_read_one_codec.decode_response(message)) request = ringbuffer_read_one_codec.encode_request(self.name, sequence) return self._invoke(request, handler)
def read_many(self, start_sequence, min_count, max_count): check_not_negative(start_sequence, "sequence can't be smaller than 0") check_true(max_count >= min_count, "max count should be greater or equal to min count") check_true(min_count <= self.capacity().result(), "min count should be smaller or equal to capacity") check_true(max_count < MAX_BATCH_SIZE, "max count can't be greater than %d" % MAX_BATCH_SIZE) return self._encode_invoke( ringbuffer_read_many_codec, response_handler=self._read_many_response_handler, start_sequence=start_sequence, min_count=min_count, max_count=max_count, filter=None)
def acquire(self, permits=1): """ Acquires one or specified amount of permits if available, and returns immediately, reducing the number of available permits by one or given amount. If insufficient permits are available then the current thread becomes disabled for thread scheduling purposes and lies dormant until one of following happens: * some other thread invokes one of the release methods for this semaphore, the current thread is next to be assigned permits and the number of available permits satisfies this request, * this Semaphore instance is destroyed, or * some other thread interrupts the current thread. :param permits: (int), the number of permits to acquire (optional). """ check_not_negative(permits, "Permits cannot be negative!") return self._encode_invoke(semaphore_acquire_codec, permits=permits)
def init(self, permits): """Tries to initialize this Semaphore instance with the given permit count. Args: permits (int): The given permit count. Returns: hazelcast.future.Future[bool]: ``True`` if the initialization succeeds, ``False`` if already initialized. Raises: AssertionError: If the ``permits`` is negative. """ check_not_negative(permits, "Permits must be non-negative") codec = semaphore_init_codec request = codec.encode_request(self._group_id, self._object_name, permits) return self._invoke(request, codec.decode_response)
def increase_permits(self, increase: int) -> Future[None]: """Increases the number of available permits by the indicated amount. If there are some callers waiting for permits to become available, they will be notified. Moreover, if the caller has acquired some permits, they are not released with this call. Args: increase: The number of permits to increase. Raises: AssertionError: If ``increase`` is negative. """ check_not_negative(increase, "Increase must be non-negative") if increase == 0: return ImmediateFuture(None) return self._do_change_permits(increase)
def reduce_permits(self, reduction: int) -> Future[None]: """Reduces the number of available permits by the indicated amount. This method differs from ``acquire`` as it does not block until permits become available. Similarly, if the caller has acquired some permits, they are not released with this call. Args: reduction: The number of permits to reduce. Raises: AssertionError: If the ``reduction`` is negative. """ check_not_negative(reduction, "Reduction must be non-negative") if reduction == 0: return ImmediateFuture(None) return self._do_change_permits(-reduction)
def try_acquire(self, permits=1, timeout=0): """ Tries to acquire one or the given number of permits, if they are available, and returns immediately, with the value ``true``, reducing the number of available permits by the given amount. If there are insufficient permits and a timeout is provided, the current thread becomes disabled for thread scheduling purposes and lies dormant until one of following happens: * some other thread invokes the release() method for this semaphore and the current thread is next to be assigned a permit, or * some other thread interrupts the current thread, or * the specified waiting time elapses. If there are insufficient permits and no timeout is provided, this method will return immediately with the value ``false`` and the number of available permits is unchanged. :param permits: (int), the number of permits to acquire (optional). :param timeout: (long), the maximum time in seconds to wait for the permit(s) (optional). :return: (bool), ``true`` if desired amount of permits was acquired, ``false`` otherwise. """ check_not_negative(permits, "Permits cannot be negative!") return self._encode_invoke(semaphore_try_acquire_codec, permits=permits, timeout=to_millis(timeout))
def init(self, permits): check_not_negative(permits, "Permits cannot be negative!") return self._encode_invoke(semaphore_init_codec, permits=permits)
def try_set_count(self, count): check_not_negative(count, "count can't be negative") return self._encode_invoke(count_down_latch_try_set_count_codec, count=count)
def read_one(self, sequence): check_not_negative(sequence, "sequence can't be smaller than 0") return self._encode_invoke(ringbuffer_read_one_codec, sequence=sequence)
def read_many( self, start_sequence: int, min_count: int, max_count: int, filter: typing.Any = None ) -> Future[ReadResult]: """Reads a batch of items from the Ringbuffer. If the number of available items after the first read item is smaller than the ``max_count``, these items are returned. So it could be the number of items read is smaller than the ``max_count``. If there are less items available than ``min_count``, then this call blocks. Warnings: These blocking calls consume server memory and if there are many calls, it can be possible to see leaking memory or ``OutOfMemoryError`` s on the server. Reading a batch of items is likely to perform better because less overhead is involved. A filter can be provided to only select items that need to be read. If the filter is ``None``, all items are read. If the filter is not ``None``, only items where the filter function returns true are returned. Using filters is a good way to prevent getting items that are of no value to the receiver. This reduces the amount of IO and the number of operations being executed, and can result in a significant performance improvement. Note that, filtering logic must be defined on the server-side. If the ``start_sequence`` is smaller than the smallest sequence still available in the Ringbuffer (:func:`head_sequence`), then the smallest available sequence will be used as the start sequence and the minimum/maximum number of items will be attempted to be read from there on. If the ``start_sequence`` is bigger than the last available sequence in the Ringbuffer (:func:`tail_sequence`), then the last available sequence plus one will be used as the start sequence and the call will block until further items become available and it can read at least the minimum number of items. Args: start_sequence: The start sequence of the first item to read. min_count: The minimum number of items to read. max_count: The maximum number of items to read. filter: Filter to select returned elements. Returns: The list of read items. """ check_not_negative(start_sequence, "sequence can't be smaller than 0") check_not_negative(min_count, "min count can't be smaller than 0") check_true(max_count >= min_count, "max count should be greater or equal to min count") check_true( max_count < MAX_BATCH_SIZE, "max count can't be greater than %d" % MAX_BATCH_SIZE ) try: filter_data = self._to_data(filter) except SchemaNotReplicatedError as e: return self._send_schema_and_retry( e, self.read_many, start_sequence, min_count, max_count, filter ) request = ringbuffer_read_many_codec.encode_request( self.name, start_sequence, min_count, max_count, filter_data ) def handler(message): response = ringbuffer_read_many_codec.decode_response(message) read_count = response["read_count"] next_seq = response["next_seq"] items = response["items"] item_seqs = response["item_seqs"] return ReadResult(read_count, next_seq, items, item_seqs, self._to_object) def continuation(future): # Since the first call to capacity # is cached on the client-side, doing # a capacity check each time should not # be a problem capacity = future.result() check_true( max_count <= capacity, "max count: %d should be smaller or equal to capacity: %d" % (max_count, capacity), ) return self._invoke(request, handler) return self.capacity().continue_with(continuation)
def reduce_permits(self, reduction): check_not_negative(reduction, "Reduction cannot be negative!") return self._encode_invoke(semaphore_reduce_permits_codec, reduction=reduction)
def try_acquire(self, permits=1, timeout=0): check_not_negative(permits, "Permits cannot be negative!") return self._encode_invoke(semaphore_try_acquire_codec, permits=permits, timeout=to_millis(timeout))
def release(self, permits=1): check_not_negative(permits, "Permits cannot be negative!") return self._encode_invoke(semaphore_release_codec, permits=permits)