Skip to content

Commit 454b2d4

Browse files
committed
fixes igniterealtime#146: Add option to choose between database used for MUC archive
The archived MUC messages are persisted to the database more than once: Openfire stores them in ofMucConversationLog, the Monitoring plugin in ofMessageArchive. This commit introduces a configuration option to switch between the two: conversation.database.use-openfire-tables The default for this new option is to use the database table provided by the Monitoring plugin, which is a change from the behavior prior to this commit.
1 parent 77f639d commit 454b2d4

File tree

3 files changed

+63
-19
lines changed

3 files changed

+63
-19
lines changed

changelog.html

+3
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ <h1>
5252
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/138'>Issue #138</a>] - Stanzas not always stored for one-to-one messages whilst clustered</li>
5353
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/139'>Issue #139</a>] - Reduce code complexity</li>
5454
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/141'>Issue #141</a>] - Make Archiver configuration configurable</li>
55+
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/142'>Issue #142</a>] - Do not require plugin restart after config change</li>
56+
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/145'>Issue #145</a>] - Replace deprecated API usage</li>
57+
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/146'>Issue #146</a>] - Allow database used for MUC MAM to be configurable</li>
5558
</ul>
5659

5760
<p><b>2.1.0</b> -- September 10, 2020</p>

src/java/com/reucon/openfire/plugin/archive/impl/MucMamPersistenceManager.java

+25-11
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.jivesoftware.openfire.muc.MUCRoom;
1414
import org.jivesoftware.openfire.muc.MultiUserChatManager;
1515
import org.jivesoftware.openfire.muc.MultiUserChatService;
16+
import org.jivesoftware.util.JiveGlobals;
1617
import org.jivesoftware.util.NotFoundException;
1718
import org.slf4j.Logger;
1819
import org.slf4j.LoggerFactory;
@@ -32,9 +33,6 @@
3233
/**
3334
* A persistence provider that facilitates the implementation of Message Archive Management (XEP-0313) for MUC rooms.
3435
*
35-
* Note that this implementation primarily makes use of the database tables that are provided by Openfire (core), and
36-
* not of the database tables that are provided by the Monitoring plugin.
37-
*
3836
* Created by dwd on 25/07/16.
3937
*/
4038
public class MucMamPersistenceManager implements PersistenceManager {
@@ -85,13 +83,24 @@ public Collection<ArchivedMessage> findMessages(Date startDate, Date endDate, JI
8583
msgs = paginatedMucMessageLuceneQuery.getPage(after, before, maxResults, isPagingBackwards);
8684
}
8785
} else {
88-
final PaginatedMucMessageDatabaseQuery paginatedMucMessageDatabaseQuery = new PaginatedMucMessageDatabaseQuery(startDate, endDate, room, with );
89-
Log.debug("Request for message archive of room '{}' resulted in the following query data: {}", room.getJID(), paginatedMucMessageDatabaseQuery);
90-
totalCount = paginatedMucMessageDatabaseQuery.getTotalCount();
91-
if ( totalCount == 0 ) {
92-
msgs = Collections.emptyList();
86+
if (JiveGlobals.getBooleanProperty("conversation.database.use-openfire-tables", false ) ) {
87+
final PaginatedMucMessageDatabaseQuery paginatedMucMessageDatabaseQuery = new PaginatedMucMessageDatabaseQuery(startDate, endDate, room, with);
88+
Log.debug("Request for message archive of room '{}' resulted in the following query data: {}", room.getJID(), paginatedMucMessageDatabaseQuery);
89+
totalCount = paginatedMucMessageDatabaseQuery.getTotalCount();
90+
if (totalCount == 0) {
91+
msgs = Collections.emptyList();
92+
} else {
93+
msgs = paginatedMucMessageDatabaseQuery.getPage(after, before, maxResults, isPagingBackwards);
94+
}
9395
} else {
94-
msgs = paginatedMucMessageDatabaseQuery.getPage(after, before, maxResults, isPagingBackwards);
96+
final PaginatedMessageDatabaseQuery paginatedMessageDatabaseQuery = new PaginatedMessageDatabaseQuery(startDate, endDate, room.getJID(), with);
97+
Log.debug("Request for message archive of room '{}' resulted in the following query data: {}", room.getJID(), paginatedMessageDatabaseQuery);
98+
totalCount = paginatedMessageDatabaseQuery.getTotalCount();
99+
if (totalCount == 0) {
100+
msgs = Collections.emptyList();
101+
} else {
102+
msgs = paginatedMessageDatabaseQuery.getPage(after, before, maxResults, isPagingBackwards);
103+
}
95104
}
96105
}
97106

@@ -138,8 +147,13 @@ public Collection<ArchivedMessage> findMessages(Date startDate, Date endDate, JI
138147
}
139148
else
140149
{
141-
final PaginatedMucMessageDatabaseQuery paginatedMucMessageDatabaseQuery = new PaginatedMucMessageDatabaseQuery(startDate, endDate, room, with);
142-
nextPage = paginatedMucMessageDatabaseQuery.getPage(afterForNextPage, beforeForNextPage, 1, isPagingBackwards);
150+
if (JiveGlobals.getBooleanProperty("conversation.database.use-openfire-tables", false ) ) {
151+
final PaginatedMucMessageDatabaseQuery paginatedMucMessageDatabaseQuery = new PaginatedMucMessageDatabaseQuery(startDate, endDate, room, with);
152+
nextPage = paginatedMucMessageDatabaseQuery.getPage(afterForNextPage, beforeForNextPage, 1, isPagingBackwards);
153+
} else {
154+
final PaginatedMessageDatabaseQuery paginatedMessageDatabaseQuery = new PaginatedMessageDatabaseQuery(startDate, endDate, room.getJID(), with);
155+
nextPage = paginatedMessageDatabaseQuery.getPage(afterForNextPage, beforeForNextPage, 1, isPagingBackwards);
156+
}
143157
}
144158
Log.debug("Found results for 'next page': {} (based on after: {} before: {} isPagingBackwards: {})", !nextPage.isEmpty(), afterForNextPage, beforeForNextPage, isPagingBackwards);
145159
xmppResultSet.setComplete(nextPage.isEmpty());

src/java/com/reucon/openfire/plugin/archive/impl/PaginatedMessageDatabaseQuery.java

+35-8
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.slf4j.LoggerFactory;
2222
import org.xmpp.packet.JID;
2323

24+
import javax.annotation.Nonnull;
2425
import javax.annotation.Nullable;
2526
import java.sql.Connection;
2627
import java.sql.PreparedStatement;
@@ -32,42 +33,69 @@
3233

3334
/**
3435
* Encapsulates responsibility of creating a database query that retrieves a specific subset (page) of archived messages
35-
* from a specific owner
36+
* from a specific owner.
37+
*
38+
* Note that an 'owner' can be an end-user entity (when the archive that's queried is considered to be a
39+
* 'personal archive') or a chatroom (in which case the archive that's queried is considered to be a group chat archive).
3640
*
3741
* @author Guus der Kinderen, [email protected]
3842
*/
3943
public class PaginatedMessageDatabaseQuery
4044
{
4145
private static final Logger Log = LoggerFactory.getLogger(PaginatedMessageDatabaseQuery.class );
4246

47+
@Nonnull
4348
private final Date startDate;
49+
50+
@Nonnull
4451
private final Date endDate;
52+
53+
@Nonnull
4554
private final JID owner;
55+
56+
@Nullable
4657
private final JID with;
4758

48-
public PaginatedMessageDatabaseQuery( Date startDate, Date endDate, JID owner, JID with )
59+
/**
60+
* Creates a query for messages from a message archive.
61+
*
62+
* The semantics of the 'with' arguments are slightly different, depending on the nature of the owner of the
63+
* archive. When the archive owner is an end-user ('personal archive'), then all messages sent 'to' or 'from' the
64+
* 'with' entity are returned. When the archive is a group chat archive and the 'with' argument is provided, then
65+
* the results will be limited to messages sent by the 'with' entity.
66+
*
67+
* @param startDate Start (inclusive) of period for which to return messages. EPOCH will be used if no value is provided.
68+
* @param endDate End (inclusive) of period for which to return messages. 'now' will be used if no value is provided.
69+
* @param owner The message archive owner.
70+
* @param with An optional converstation partner (or message author, in case of MUC).
71+
*/
72+
public PaginatedMessageDatabaseQuery(@Nullable final Date startDate, @Nullable final Date endDate, @Nonnull final JID owner, @Nullable final JID with)
4973
{
5074
this.startDate = startDate == null ? new Date( 0L ) : startDate ;
5175
this.endDate = endDate == null ? new Date() : endDate;
5276
this.owner = owner;
5377
this.with = with;
5478
}
5579

80+
@Nonnull
5681
public Date getStartDate()
5782
{
5883
return startDate;
5984
}
6085

86+
@Nonnull
6187
public Date getEndDate()
6288
{
6389
return endDate;
6490
}
6591

92+
@Nonnull
6693
public JID getOwner()
6794
{
6895
return owner;
6996
}
7097

98+
@Nullable
7199
public JID getWith()
72100
{
73101
return with;
@@ -84,7 +112,7 @@ public String toString()
84112
'}';
85113
}
86114

87-
protected List<ArchivedMessage> getPage( final Long after, final Long before, final int maxResults, final boolean isPagingBackwards )
115+
protected List<ArchivedMessage> getPage( @Nullable final Long after, @Nullable final Long before, final int maxResults, final boolean isPagingBackwards )
88116
{
89117
Log.trace( "Getting page of archived messages. After: {}, Before: {}, Max results: {}, Paging backwards: {}", after, before, maxResults, isPagingBackwards );
90118

@@ -106,11 +134,14 @@ protected List<ArchivedMessage> getPage( final Long after, final Long before, fi
106134
pstmt = connection.prepareStatement( query );
107135
pstmt.setLong( 1, dateToMillis( startDate ) );
108136
pstmt.setLong( 2, dateToMillis( endDate ) );
137+
138+
// TODO Optimize this for the MUC use-case. Unlike personal archives, the owner of the MUC archive is guaranteed to be in the 'tojid' column. For MUC, there's no need to look in both columns.
109139
pstmt.setString( 3, owner.toBareJID() );
110140
pstmt.setString( 4, owner.toBareJID() );
111141
int pos = 4;
112142

113143
if ( with != null ) {
144+
// TODO Optimize this for the MUC use-case. Unlike personal archives, the relevant 'with' value (sender of the message) of the MUC archive is guaranteed to be in the 'fromJid' columns. For MUC, there's no need to look in both columns.
114145
if (with.getResource() == null) {
115146
pstmt.setString( ++pos, with.toString() );
116147
pstmt.setString( ++pos, with.toString() );
@@ -147,11 +178,7 @@ protected List<ArchivedMessage> getPage( final Long after, final Long before, fi
147178
return archivedMessages;
148179
}
149180

150-
private Date millisToDate(Long millis) {
151-
return millis == null ? null : new Date(millis);
152-
}
153-
154-
private Long dateToMillis(Date date) {
181+
private Long dateToMillis(@Nullable final Date date) {
155182
return date == null ? null : date.getTime();
156183
}
157184

0 commit comments

Comments
 (0)