Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ public class JoinHandler extends OwnThreadDMLHandler {
protected List<FieldPacket> leftFieldPackets;
protected List<FieldPacket> rightFieldPackets;
private AtomicBoolean fieldSent = new AtomicBoolean(false);
// merge loop ended; set before terminateHandlerTree so late backend rows skip putLast on a full queue
private final AtomicBoolean joinMergeFinished = new AtomicBoolean(false);
private BufferPool pool;
private RowDataComparator leftComparator;
private RowDataComparator rightComparator;
Expand Down Expand Up @@ -122,20 +124,27 @@ private Item makeOtherJoinOnItem(List<FieldPacket> rowPackets, BackendConnection
@Override
public boolean rowResponse(byte[] rowNull, RowDataPacket rowPacket, boolean isLeft, BackendConnection conn) {
LOGGER.debug("rowresponse");
if (terminate.get()) {
// return true: interrupted; do not block on putLast after merge or during terminate
if (terminate.get() || joinMergeFinished.get()) {
return true;
}
try {
if (isLeft) {
leftLock.lock();
try {
if (terminate.get() || joinMergeFinished.get()) {
return true;
}
addRowToDeque(rowPacket, leftFieldPackets.size(), leftQueue, leftComparator);
} finally {
leftLock.unlock();
}
} else {
rightLock.lock();
try {
if (terminate.get() || joinMergeFinished.get()) {
return true;
}
addRowToDeque(rowPacket, rightFieldPackets.size(), rightQueue, rightComparator);
} finally {
rightLock.unlock();
Expand All @@ -151,7 +160,7 @@ public boolean rowResponse(byte[] rowNull, RowDataPacket rowPacket, boolean isLe
@Override
public void rowEofResponse(byte[] data, boolean isLeft, BackendConnection conn) {
LOGGER.debug("roweof");
if (terminate.get()) {
if (terminate.get() || joinMergeFinished.get()) {
return;
}
RowDataPacket eofRow = TERMINATED_ROW;
Expand Down Expand Up @@ -219,6 +228,9 @@ protected void ownThreadJob(Object... objects) {
rightLocal = takeFirst(rightQueue);
}
}
// stop accepting backend rows and drain queues before waiting on connections in terminateHandlerTree
joinMergeFinished.set(true);
clearJoinQueuesAfterMerge();

HandlerTool.terminateHandlerTree(this);
// for trace, when join end before all rows return ,the handler should mark as finished
Expand All @@ -243,6 +255,15 @@ protected void ownThreadJob(Object... objects) {
}
}

/**
* Clear join queues after merge. Unlocked poll first so producers blocked on a full
* deque can finish;
*/
private void clearJoinQueuesAfterMerge() {
clearDeque(leftQueue);
clearDeque(rightQueue);
}

private LocalResult takeFirst(FairLinkedBlockingDeque<LocalResult> deque) throws InterruptedException {
/**
* it must be in single thread
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock;

public class NotInHandler extends OwnThreadDMLHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(NotInHandler.class);
Expand All @@ -43,7 +44,12 @@ public class NotInHandler extends OwnThreadDMLHandler {
private RowDataComparator leftComparator;
private RowDataComparator rightComparator;
private AtomicBoolean fieldSent = new AtomicBoolean(false);
// merge loop ended; set before terminateHandlerTree so late backend rows skip putLast on a full queue
private final AtomicBoolean joinMergeFinished = new AtomicBoolean(false);
private String charset = "UTF-8";
// prevent multi thread rowresponse
protected ReentrantLock leftLock = new ReentrantLock();
protected ReentrantLock rightLock = new ReentrantLock();

public NotInHandler(long id, NonBlockingSession session, List<Order> leftOrder, List<Order> rightOrder) {
super(id, session);
Expand Down Expand Up @@ -88,14 +94,31 @@ public void fieldEofResponse(byte[] headerNull, List<byte[]> fieldsNull, final L
@Override
public boolean rowResponse(byte[] rowNull, RowDataPacket rowPacket, boolean isLeft, BackendConnection conn) {
LOGGER.debug("rowresponse");
if (terminate.get()) {
// return true: interrupted; do not block on putLast after merge or during terminate
if (terminate.get() || joinMergeFinished.get()) {
return true;
}
try {
if (isLeft) {
addRowToDeque(rowPacket, leftFieldPackets.size(), leftQueue, leftComparator);
leftLock.lock();
try {
if (terminate.get() || joinMergeFinished.get()) {
return true;
}
addRowToDeque(rowPacket, leftFieldPackets.size(), leftQueue, leftComparator);
} finally {
leftLock.unlock();
}
} else {
addRowToDeque(rowPacket, rightFieldPackets.size(), rightQueue, rightComparator);
rightLock.lock();
try {
if (terminate.get() || joinMergeFinished.get()) {
return true;
}
addRowToDeque(rowPacket, rightFieldPackets.size(), rightQueue, rightComparator);
} finally {
rightLock.unlock();
}
}
} catch (InterruptedException e) {
LOGGER.info("not in row exception", e);
Expand All @@ -107,7 +130,7 @@ public boolean rowResponse(byte[] rowNull, RowDataPacket rowPacket, boolean isLe
@Override
public void rowEofResponse(byte[] data, boolean isLeft, BackendConnection conn) {
LOGGER.info("roweof");
if (terminate.get()) {
if (terminate.get() || joinMergeFinished.get()) {
return;
}
RowDataPacket eofRow = TERMINATED_ROW;
Expand Down Expand Up @@ -164,6 +187,9 @@ protected void ownThreadJob(Object... objects) {
rightLocal = takeFirst(rightQueue);
}
}
// stop accepting backend rows and drain queues before waiting on connections in terminateHandlerTree
joinMergeFinished.set(true);
clearJoinQueuesAfterMerge();
session.setHandlerEnd(this);
nextHandler.rowEofResponse(null, isLeft, conn);
HandlerTool.terminateHandlerTree(this);
Expand All @@ -179,6 +205,15 @@ protected void ownThreadJob(Object... objects) {
}
}

/**
* Clear join queues after merge. Unlocked poll first so producers blocked on a full
* deque can finish;
*/
private void clearJoinQueuesAfterMerge() {
clearDeque(leftQueue);
clearDeque(rightQueue);
}

private LocalResult takeFirst(FairLinkedBlockingDeque<LocalResult> deque) throws InterruptedException {
deque.waitUtilCount(1);
LocalResult result = deque.peekFirst();
Expand Down
Loading