Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make Session.shutdown()/close, Transaction.close(), and PreparedState… #501

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

t-horikawa
Copy link
Contributor

@t-horikawa t-horikawa requested a review from hishidama December 4, 2024 06:10
@@ -39,32 +39,55 @@ public class Disposer extends Thread {

private AtomicBoolean started = new AtomicBoolean();

private AtomicBoolean sessionClosed = new AtomicBoolean();
private Queue<ForegroundFutureResponse<?>> futureResponseQueue = new ArrayDeque<>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

キューを使う箇所でsynchronizedしていますが、ConcurrentLinkedQueueを使えばいいのではないでしょうか。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ConcurrentLinkedQueueを使いました。

private AtomicBoolean sessionClosed = new AtomicBoolean();
private Queue<ForegroundFutureResponse<?>> futureResponseQueue = new ArrayDeque<>();

private Queue<DelayedClose> serverResourceQueue = new ArrayDeque<>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここも同様(ConcurrentLinkedQueue)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここも同様

} catch (TimeoutException e) {
// Let's try again
queue.add(futureResponse);
futureResponseQueue.add(futureResponse);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

futureResponseQueueを(他の個所ではsynchronizedしているのに)synchronizedせずに使ってますね

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ConcurrentLinkedQueueを使いました。

synchronized (queue) {
sessionClosed.set(true);
return queue.isEmpty();
public synchronized void registerDelayedShutdown(DelayedShutdown c) throws IOException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

このメソッドの中のc.shutdown()に長時間かかる可能性があるので、
このメソッドでsynchronizedすると、他スレッドから同時に呼び出された場合に待ちが発生しますが、大丈夫でしょうか?
’(呼び出し元は FutureResponse<Void> shutdown(@Nonnull ShutdownType type) であり、Futureを返すメソッドはなるべく早く戻るべきな気がします(future.get()で時間がかかるのは普通のことなので気にならない))
(それとも、shutodwnメソッドは時間がかかっても構わないという仕様?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c.shutdown()はsynchronized(this)の外に出しました。

}
shutdown.set(c);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

複数スレッドから同時に呼ばれた場合や複数回呼ばれた場合、shutdownにセットされるのはひとつだけになりますが、問題ないでしょうか?
(呼び出し元はSessionImpl#shutdown()なので、ユーザーが異なる引数で複数呼ぶことは可能)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

複数のshutdownをセット可能にしました。

}

@Override
public void setCloseTimeout(long t, TimeUnit u) {
timeout = t;
unit = u;
synchronized (this) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

synchronized(this) しか無いメソッドなら、メソッドをsynchronizedにした方がいいと思いますが、
たぶんここで排他したいのはthisではなくタイムアウトフィールドですよね?

thisで排他するとcommitやcloseと競合しますが、setCloseTimeoutを複数スレッドから呼ぶことは考えにくいので、実際的には問題にならないような気もしますが。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

メソッドをsynchronizedにしました。synchronizedは不要と思ったのですが、spotBugsでエラーになるので入れています。

return sendAndGetSqlServiceException();
}
}
return sendAndGetSqlServiceException();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

synchronized(this)の終わりがここですが、この排他は実質的にstateの排他だと考えられるので、
var cr = commitResult の前まで排他すれば良いように思われます。
そして、state自身がAtomicなので、CLOSEDかどうかをチェックするだけなら、synchronized自体不要かも?

(もしstateの排他という意味なら、synchronized(this)よりsynchronized(state)の方が分かりやすいですが(他のメソッドも含めて))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commitResultも排他の対象になっています。また、synchronized(state)としたかったのですが、SpotBugsがエラーだと誤検出してしまいます。

@@ -279,11 +326,79 @@ public String getTransactionId() {
return transaction.getTransactionId().getId();
}

private State toBeClosed(State s) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

呼ばれるメソッドは、呼ぶメソッドの下にある方が分かりやすいです。
(Javaにおける、ソースコードの慣例)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

入れ替えました。

}

private void doClose() throws IOException, ServerException, InterruptedException {
synchronized (this) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doClose()はclose()からしか呼ばれないので(closeの中でsynchronized(this)されているので)、ここでの排他は不要です。
(不要である旨はソースコード上にコメントとして残した方がいいかもしれませんが)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doClose()はDisposerのスレッドからcallされる可能性があります。

// need session.close() followed by SessionImpl.waitForDisposerEmpty()
session.close();
if (session instanceof SessionImpl) {
((SessionImpl) session).waitForDisposerEmpty();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iceaxe-dbtestでもDisposerが終了したことを確認した方がいいと思われるので、Sessionから呼べると嬉しいです。
(IceaxeでSessionImplを使うのはいまいちなので)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これは議論が必要そう。waitForDisposerEmpty()はtestだけで使うAPI(Arch meetingの決定事項)なので、Sessionが持つAPIとするのは不適切という気がしました。testのみのAPIもSessionが持つAPIに持たせてよいのであれば、そのように変更します。

@t-horikawa t-horikawa requested a review from hishidama December 9, 2024 06:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants