def test_transfered_ongoing_overlapping_ops(): ticket = Ticket(testutil.create_ticket(ops=["read"])) # Start 2 ongoing operations. # ongoing: 0-0, 80-80 # completed: op1 = Operation(0, 120) op2 = Operation(80, 120) ticket._add_operation(op1) ticket._add_operation(op2) assert ticket.transferred() == 0 assert ticket.active() # Consume op1 data: # ongoing: 0-120, 80-80 # completed: op1.run() ticket._remove_operation(op1) assert ticket.transferred() == 120 assert ticket.active() # Consume op2 data: # ongoing: 0-120, 80-200 # completed: op2.run() ticket._remove_operation(op2) assert ticket.transferred() == 200 assert not ticket.active()
def test_transfered_ongoing_non_continues_ops(): ticket = Ticket(testutil.create_ticket(ops=["read"])) # Start 2 ongoing operations. # ongoing: 0-0, 200-200 # completed: op1 = Operation(0, 100) op2 = Operation(200, 100) ticket._add_operation(op1) ticket._add_operation(op2) assert ticket.transferred() == 0 assert ticket.active() # Consume op1 data: # ongoing: 0-100, 200-200 # completed: op1.run() ticket._remove_operation(op1) assert ticket.transferred() == 100 # Consume op2 data: # ongoing: 0-100, 200-300 # completed: op2.run() ticket._remove_operation(op2) assert ticket.transferred() == 200
def test_cancel_timeout(cfg): ticket = Ticket(testutil.create_ticket(ops=["read"]), cfg) # Add conection - having connections does not block cancelation, but we # cannot have ongoing operations without a connection. ctx = Context() ticket.add_context(1, ctx) # Ongoing operation blocks cancel. ticket._add_operation(Operation(0, 100)) # Canceling will time out. with pytest.raises(errors.TransferCancelTimeout): ticket.cancel(timeout=0.001) # Ticket is marked as canceled, but the context was not closed. assert ticket.canceled assert not ctx.closed # Caller can poll ticket "active" property and remove the ticket when the # ticket is inactive. info = ticket.info() assert info["canceled"] assert info["active"] assert info["connections"] == 1
def test_transfered_ongoing_concurrent_ops(cfg): ticket = Ticket(testutil.create_ticket(ops=["read"]), cfg) # Start 2 ongoing operations: # ongoing: 0-0, 100-100 # completed: op1 = Operation(0, 100) ticket._add_operation(op1) assert ticket.transferred() == 0 assert ticket.active() op2 = Operation(100, 100) ticket._add_operation(op2) assert ticket.transferred() == 0 assert ticket.active() # Consume op1 data: # ongoing: 0-100, 100-100 # completed: op1.run() ticket._remove_operation(op1) assert ticket.transferred() == 100 assert ticket.active() # Consume op2 data: # ongoing: 0-100, 100-200 # completed: op2.run() ticket._remove_operation(op2) assert ticket.transferred() == 200 assert not ticket.active()
def test_cancel_async(cfg): ticket = Ticket(testutil.create_ticket(ops=["read"]), cfg) ctx = Context() ticket.add_context(1, ctx) ticket._add_operation(Operation(0, 100)) ticket.cancel(timeout=0) # Ticket is marked as canceled, but the context was not closed. assert ticket.canceled assert not ctx.closed info = ticket.info() assert info["canceled"] assert info["active"] assert info["connections"] == 1
def test_cancel_ongoing_operations(): ticket = Ticket(testutil.create_ticket(ops=["read"])) # Few connections are using this ticket. Each running an operation. ops = [] for i in range(4): ctx = Context() op = Operation() ticket.add_context(i, ctx) ticket._add_operation(op) ops.append(op) ticket.cancel(timeout=0) # All ongoing operations are canceled. assert all(op.canceled for op in ops)
def test_cancel_wait(cfg): ticket = Ticket(testutil.create_ticket(ops=["read"]), cfg) # Add connections using this ticket. users = [] for cid in range(4): ctx = Context() op = Operation(cid * 1024**2, 1024**2) ticket.add_context(cid, ctx) ticket._add_operation(op) users.append((cid, ctx, op)) # Add idle connection. idle_ctx = Context() ticket.add_context(4, idle_ctx) def finish_operations(): time.sleep(0.1) for cid, ctx, op in users: # Removing operation from a canceled ticket raises, send and error # and close the connection. try: ticket._remove_operation(op) except errors.AuthorizationError: ticket.remove_context(cid) info = ticket.info() assert not info["canceled"] assert info["connections"] == 5 assert info["active"] t = util.start_thread(finish_operations) try: ticket.cancel(timeout=10) finally: t.join() info = ticket.info() # After the ticket was canceled, ticket is inactive, and all ongoging # connnections removed from ticket. The idle connection is left, but its # context is closed. assert not info["active"] assert info["connections"] == 1 assert all(ctx.closed for cid, ctx, op in users) assert idle_ctx.closed
def test_transferred_benchmark(concurrent): # Time trransferred call with multiple ongoing and completed operations. ticket = Ticket(testutil.create_ticket(ops=["read"])) calls = 10000 # Add some completed ranges - assume worst case when ranges are not # continues. for i in range(concurrent): ticket.run(Operation(i * 1000, 100)) # Add some ongoing operations - assume worst case when ranges are not # continues. for i in range(concurrent): ticket._add_operation(Operation(i * 1000 + 200, 100)) # Time transferred call - merging ongoing and completed ranges. start = time.monotonic() for i in range(calls): ticket.transferred() elapsed = time.monotonic() - start print("%d concurrent operations, %d calls in %.3f seconds (%d nsec/op)" % (concurrent, calls, elapsed, elapsed * 10**9 // calls))
def test_transferred_benchmark(cfg, workers): # Time trransferred call with multiple ongoing and completed operations. ticket = Ticket(testutil.create_ticket(ops=["read"]), cfg) ops = 10000 # Add some completed ranges - assume worst case when ranges are not # continues. for i in range(workers): ticket.run(Operation(i * 1000, 100)) # Add some ongoing operations - assume worst case when ranges are not # continues. for i in range(workers): ticket._add_operation(Operation(i * 1000 + 200, 100)) # Time transferred call - merging ongoing and completed ranges. start = time.monotonic() for i in range(ops): ticket.transferred() elapsed = time.monotonic() - start print("%d workers, %d ops, %.3f s, %.2f ops/s" % (workers, ops, elapsed, ops / elapsed))