Skip to content

Commit

Permalink
fixes igniterealtime#373: Separate stanza parsing from database loading
Browse files Browse the repository at this point in the history
By not parsing database content immediately, this parsing can be done after the database connection has been released. This should reduce resource contention.
  • Loading branch information
guusdk committed Nov 22, 2024
1 parent 1dc8c64 commit c0f0fe6
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 25 deletions.
1 change: 1 addition & 0 deletions changelog.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ <h1>
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/401'>Issue #401</a>] - Fixes: Update Jersey from 2.35 to 2.45</li>
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/398'>Issue #398</a>] - Fixes: Missing translation for system property</li>
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/392'>Issue #392</a>] - Fixes: Compatibility issue with Openfire 5.0.0</li>
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/373'>Issue #373</a>] - Separate stanza parsing from database loading</li>
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/363'>Issue #363</a>] - Fixes SQL Server error: An expression of non-boolean type specified in a context where a condition is expected, near 'RowNum'</li>
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/357'>Issue #357</a>] - Fixes: Error on admin console after user session expired.</li>
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/354'>Issue #354</a>] - Allow full-text search / indexing to be disabled</li>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,13 @@ public static Direction getDirection(@Nonnull final JID owner, @Nonnull final JI
@Nonnull
private final JID with;

// Issue #373: Lazily populated with the value of #rawStanza
@Nullable
private final Message stanza;
private Message stanza;

@Nullable
// Issue #373: Lazily populates #stanza
private String rawStanza;

public ArchivedMessage(@Nullable final Long id, @Nonnull final Date time, @Nonnull final Direction direction, @Nonnull final JID with, @Nullable final String body, @Nullable final String stanza) throws DocumentException {
this.id = id;
Expand All @@ -85,27 +90,9 @@ public ArchivedMessage(@Nullable final Long id, @Nonnull final Date time, @Nonnu
this.with = with;
this.body = body;

if ( stanza != null && stanza.length() > 0 ) {
Message stanzaResult;
try {
final Document doc = DocumentHelper.parseText( stanza );
stanzaResult = new Message( doc.getRootElement() );
} catch (DocumentException de) {
Log.debug("Unable to parse (non-empty) stanza (id: {})", id, de);
stanzaResult = null;
}
this.stanza = stanzaResult;
} else {
this.stanza = null;
}

if ( this.stanza != null && !OF1804_DISABLE.getValue() )
{
// Prior to OF-1804 (Openfire 4.4.0), the stanza was logged with a formatter applied.
// This causes message formatting to be modified (notably, new lines could be altered).
// This workaround restores the original body text, that was stored in a different column.
this.stanza.setBody( body );
}
// Issue #373: Do not parse the stanza now, as this incurs quite a bit of resource usage. This constructor is
// often called when a database resource is held. It is desirable to release that database resource as soon as possible.
this.rawStanza = stanza;
}

/**
Expand Down Expand Up @@ -159,7 +146,41 @@ public String getBody() {
*/
@Nullable
public Message getStanza() {
return stanza;
if (this.stanza != null) {
// Return lazily-loaded stanza
return this.stanza;
}

if (rawStanza == null || rawStanza.isEmpty()) {
// There is no data to lazily load.
return null;
}

synchronized (this) {
// Issue #373: Lazily load stanza from rawStanza. This can be resource intensive. Guarded with mutex to prevent duplicate execution.
Message stanzaResult;
try {
final Document doc = DocumentHelper.parseText(rawStanza);
stanzaResult = new Message(doc.getRootElement());
} catch (DocumentException de) {
Log.debug("Unable to parse (non-empty) stanza (id: {})", id, de);
stanzaResult = null;
}
this.stanza = stanzaResult;

if (this.stanza != null && !OF1804_DISABLE.getValue())
{
// Prior to OF-1804 (Openfire 4.4.0), the stanza was logged with a formatter applied.
// This causes message formatting to be modified (notably, new lines could be altered).
// This workaround restores the original body text, that was stored in a different column.
this.stanza.setBody( body );
}

// Prevent data duplication: Remove the now-processed raw data.
this.rawStanza = null;
}

return this.stanza;
}

/**
Expand All @@ -185,12 +206,13 @@ public JID getWith() {
@Nullable
public String getStableId(final JID owner)
{
if (this.stanza == null) {
final Message stanza = getStanza();
if (stanza == null) {
return null;
}

try {
return StanzaIDUtil.findFirstUniqueAndStableStanzaID(this.stanza, owner.toBareJID());
return StanzaIDUtil.findFirstUniqueAndStableStanzaID(stanza, owner.toBareJID());
} catch (Exception e) {
Log.warn("An exception occurred while parsing message with ID {}", id, e);
return null;
Expand Down

0 comments on commit c0f0fe6

Please sign in to comment.