Skip to content

Fix the connection and manager lifecycle (#126, #94, #95, #98) - #148

Open
bertysentry wants to merge 8 commits into
mainfrom
fix/connection-lifecycle
Open

bertysentry wants to merge 8 commits into
mainfrom
fix/connection-lifecycle

Conversation

@bertysentry

Copy link
Copy Markdown
Contributor

Fixes #126, fixes #94, fixes #95, fixes #98.

Keep-alive (#126, #94)

  • ConnectionManager(int, long) assigned the ping period after initialize() had resolved -1 to the connection.properties value, so every IpmiClient call with the default configuration ran without keep-alive. The field is now assigned before initialize(), and getPingPeriod() exposes the result (unit test for IpmiConnector(0), (0, -1), (0, 12345) and (0, 0)).
  • The keep-alive task sent its Get Channel Authentication Capabilities in a while loop that hot-spun when sendMessage threw (after disconnect(), StateMachine.stop() left current as SessionValid, so every iteration threw the State machine not started NPE). The task now sends the message one-way and returns: no loop, no sleep, and StateMachine.stop() resets the state to Uninitialized, so a disconnected connection reports no valid session.
  • As the keep-alive reply is no longer queued, IpmiMessageHandler no longer drops every reply whose coder class is GetChannelAuthenticationCapabilities: an application sending that command in a session gets its reply (ConnectionManager / SessionManager lifecycle bugs: static reservedTags reassigned, inconsistent handles, connections never removed, establishSession tears down the whole connector, keep-alive responses filtered by class #95.5).

Manager lifecycle (#95)

  • reservedTags is static final: it was replaced by every new ConnectionManager, which discarded the reservations of the other managers of the JVM and made synchronized (reservedTags) lock different objects over time.
  • The four createConnection() overloads share one private connect(): the two overloads taking an int pingPeriod returned handle 0 for every connection.
  • closeConnection(index) releases the connection (getConnection(index) then throws IllegalStateException; closing twice is a no-op; handles are not reused). getConnection(InetAddress, int) compares the addresses with equals().
  • SessionManager.establishSession() closes the failed connection instead of calling tearDown() on the caller's connector (which closed its UDP socket and every other connection, e.g. the SerialOverLan main session).

PropertiesManager (#98)

Guarded lazy initialization (private lock, SpotBugs rejects static synchronized), a missing resource is logged and skipped instead of failing with NullPointerException, ConcurrentHashMap for the map, lookups logged at DEBUG; the never-read cleaningFrequency property and the unused Constants.TIMEOUT are removed. The file was already LF with a trailing newline in git (the CRLF of the issue is the Windows checkout).

Verification

  • mvn formatter:format verify green on JDK 17 (checkstyle, PMD, CPD, SpotBugs gated); 12 new or updated unit tests, the 3 behavioral ones fail on main.
  • Live getFrusAndSensorsAsStringResult on Dell iDRAC 8 (106 s, 3 keep-alives fired), Lenovo IMM, HP iLO 4 (79 s), Supermicro and Fujitsu iRMC (99 s): identical to main apart from reading drift. The keep-alive now actually runs during the collections that exceed 30 s.

Documentation

upgrading.md lists the user-visible changes; low-level-api.md describes closeConnection() as releasing the connection.

🤖 Generated with Claude Code

ConnectionManager(int, long) assigns the ping period before initialize()
resolves -1, so the default IpmiClient configuration gets the 30 s
keep-alive of connection.properties instead of none (#126).

The keep-alive task sends its Get Channel Authentication Capabilities
one-way and returns: no retry loop that hot-spins when sendMessage
throws, and StateMachine.stop() leaves the session state so a stopped
connection reports no valid session (#94). As the keep-alive reply is
no longer queued, IpmiMessageHandler delivers every reply, including the
replies of that command sent by the application.

The sessionless tag pool is final instead of being replaced by each new
manager, every createConnection() overload returns the handle of the
connection it created, closeConnection() releases the connection
(getConnection() then throws IllegalStateException), getConnection(
InetAddress, int) compares the addresses with equals(), and
SessionManager.establishSession() closes the failed connection instead
of tearing down the whole connector (#95).

PropertiesManager guards its lazy initialization, skips a missing
resource instead of failing with NullPointerException, keeps its map in
a ConcurrentHashMap and logs lookups at DEBUG; the unused
cleaningFrequency property and Constants.TIMEOUT are removed (#98).

Co-Authored-By: Claude Fable 5.1 <[email protected]>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-09T16:05:23.615698Z c52b0ca New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ef8c6ed393

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/main/java/org/metricshub/ipmi/core/connection/Connection.java Outdated
Comment thread src/main/java/org/metricshub/ipmi/core/connection/ConnectionManager.java Outdated
Comment thread src/main/java/org/metricshub/ipmi/core/connection/ConnectionManager.java Outdated
Comment thread src/main/java/org/metricshub/ipmi/core/common/Constants.java
A one-way message skips the tags of the queued requests, so the
keep-alive can never take the tag of a pending request; every operation
of ConnectionManager on a released handle throws IllegalStateException;
getPingPeriod() is package-private; Constants.TIMEOUT is deprecated
instead of removed; the documentation of the property lookups says
DEBUG and thread-safe.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8246818381

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/main/java/org/metricshub/ipmi/core/connection/ConnectionManager.java Outdated
IpmiMessageHandler drops a reply whose command is not the command of
the queued request with that tag: a late reply to the one-way
keep-alive can no longer be decoded as the reply of a request that was
given its sequence number since.

ConnectionManager keeps its connections in a copy-on-write list looked
up without a lock: the receiving thread, which holds the UDP listener
lock, no longer waits for a lock that connect() and close() hold while
registering or unregistering UDP listeners.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b786faa358

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/main/java/org/metricshub/ipmi/core/connection/IpmiMessageHandler.java Outdated
The keep-alive is a Connection.KeepAlive request, queued like any
request so that its tag stays reserved until its reply arrives or it
times out; IpmiMessageHandler discards the reply of a KeepAlive and
delivers every other reply, including the application's own Get
Channel Authentication Capabilities. The command-code check is gone.

ConnectionManager.close() disconnects the connections under the same
lock as connect() and marks the manager closed; connect() then throws
IllegalStateException instead of creating a connection on a closed
messenger.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7312ecf74b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/main/java/org/metricshub/ipmi/core/connection/ConnectionManager.java Outdated
Comment thread src/main/java/org/metricshub/ipmi/core/connection/Connection.java
Comment thread src/site/markdown/upgrading.md
…eouts stay silent

ConnectionManager.connect() reserves the slot under connectionsLock
and registers with the messenger outside it, then disconnects and
throws if close() ran meanwhile; close() flags the manager closed under
the lock and disconnects outside it. A listener callback on the
receiving thread, which holds the messenger lock, may therefore create
or close connections without deadlocking.

MessageQueue does not report the timeout of a Connection.KeepAlive,
which nobody waits for; the class is public so the queue package can
recognize it. The README upgrade summary lists the public changes.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bd5715a133

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/main/java/org/metricshub/ipmi/core/connection/Connection.java
IpmiMessageHandler drops a reply whose command is not the command of
the queued request with that tag and leaves the request queued: a late
reply to a one-way message, whose tag is not reserved, can carry the
tag of a newer request. The low-level API page and the README describe
the Connection.KeepAlive request.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2c68ad9390

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/main/java/org/metricshub/ipmi/core/connection/IpmiMessageHandler.java Outdated
Command codes are scoped by network function: the reply must carry the
command code of the queued request under the response network function
of that request (the request one plus one, IPMI 2.0 section 5.1), and a
reply whose network function the library does not know answers nothing.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c52b0ca5a2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/site/markdown/low-level-api.md
The paragraph ended the Markdown table before its last rows.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment