From 37e9ffb2527455b8ebe1a2d0a085de5b8ec15c0e Mon Sep 17 00:00:00 2001 From: Damian Minkov Date: Fri, 26 Oct 2007 18:09:29 +0000 Subject: [PATCH] generate more precise events during history search (Issue #270) --- .../impl/history/HistoryReaderImpl.java | 39 ++++++ .../msghistory/MessageHistoryServiceImpl.java | 112 +++++++++++++----- .../service/history/HistoryReader.java | 11 ++ 3 files changed, 132 insertions(+), 30 deletions(-) diff --git a/src/net/java/sip/communicator/impl/history/HistoryReaderImpl.java b/src/net/java/sip/communicator/impl/history/HistoryReaderImpl.java index 4d99f4ca3..02def73a9 100644 --- a/src/net/java/sip/communicator/impl/history/HistoryReaderImpl.java +++ b/src/net/java/sip/communicator/impl/history/HistoryReaderImpl.java @@ -840,6 +840,45 @@ public void removeSearchProgressListener(HistorySearchProgressListener progressListeners.remove(listener); } } + + /** + * Count the number of messages that a search will return + * Actually only the last file is parsed and its nodes are counted. + * We accept that the other files are full with max records, + * this way we escape parsing all files which will significantly + * slow the process and for one search will parse the files twice. + * + * @return the number of searched messages + * @throws UnsupportedOperationException + * Thrown if an exception occurs during the execution of the + * query, such as internal IO error. + */ + public int countRecords() + throws UnsupportedOperationException + { + int result = 0; + String lastFile = null; + Iterator filelistIter = this.historyImpl.getFileList(); + while (filelistIter.hasNext()) + { + lastFile = (String)filelistIter.next(); + result += HistoryWriterImpl.MAX_RECORDS_PER_FILE; + } + + if(lastFile == null) + return result; + + Document doc = this.historyImpl.getDocumentForFile(lastFile); + + if(doc == null) + return result; + + NodeList nodes = doc.getElementsByTagName("record"); + + result += nodes.getLength(); + + return result; + } /** * Used to compare HistoryRecords diff --git a/src/net/java/sip/communicator/impl/msghistory/MessageHistoryServiceImpl.java b/src/net/java/sip/communicator/impl/msghistory/MessageHistoryServiceImpl.java index e9bfccb30..c179300bc 100644 --- a/src/net/java/sip/communicator/impl/msghistory/MessageHistoryServiceImpl.java +++ b/src/net/java/sip/communicator/impl/msghistory/MessageHistoryServiceImpl.java @@ -84,6 +84,8 @@ public Collection findByStartDate(MetaContact contact, Date startDate) // get the readers for this contact Hashtable readers = getHistoryReaders(contact); + int recordsCount = countRecords(readers); + Iterator iter = readers.keySet().iterator(); while (iter.hasNext()) { @@ -91,7 +93,7 @@ public Collection findByStartDate(MetaContact contact, Date startDate) HistoryReader reader = (HistoryReader)readers.get(item); // add the progress listeners - addHistorySearchProgressListeners(reader, readers.size()); + addHistorySearchProgressListeners(reader, recordsCount); Iterator recs = reader.findByStartDate(startDate); while (recs.hasNext()) { @@ -127,6 +129,8 @@ public Collection findByEndDate(MetaContact contact, Date endDate) // get the readers for this contact Hashtable readers = getHistoryReaders(contact); + int recordsCount = countRecords(readers); + Iterator iter = readers.keySet().iterator(); while (iter.hasNext()) { @@ -134,7 +138,7 @@ public Collection findByEndDate(MetaContact contact, Date endDate) HistoryReader reader = (HistoryReader)readers.get(item); // add the progress listeners - addHistorySearchProgressListeners(reader, readers.size()); + addHistorySearchProgressListeners(reader, recordsCount); Iterator recs = reader.findByEndDate(endDate); while (recs.hasNext()) { @@ -170,6 +174,8 @@ public Collection findByPeriod(MetaContact contact, Date startDate, Date endDate // get the readers for this contact Hashtable readers = getHistoryReaders(contact); + int recordsCount = countRecords(readers); + Iterator iter = readers.keySet().iterator(); while (iter.hasNext()) { @@ -177,7 +183,7 @@ public Collection findByPeriod(MetaContact contact, Date startDate, Date endDate HistoryReader reader = (HistoryReader)readers.get(item); // add the progress listeners - addHistorySearchProgressListeners(reader, readers.size()); + addHistorySearchProgressListeners(reader, recordsCount); Iterator recs = reader.findByPeriod(startDate, endDate); while (recs.hasNext()) @@ -1011,10 +1017,10 @@ public void removeSearchProgressListener( * to the given HistoryReader * * @param reader HistoryReader - * @param countContacts number of contacts will search + * @param countRecords number of records will search */ private void addHistorySearchProgressListeners( - HistoryReader reader, int countContacts) + HistoryReader reader, int countRecords) { synchronized(progressListeners) { @@ -1023,7 +1029,7 @@ private void addHistorySearchProgressListeners( { SearchProgressWrapper l = (SearchProgressWrapper) iter.next(); - l.contactCount = countContacts; + l.setCurrentValues(reader, countRecords); reader.addSearchProgressListener(l); } } @@ -1072,6 +1078,8 @@ public Collection findByPeriod(MetaContact contact, Date startDate, // get the readers for this contact Hashtable readers = getHistoryReaders(contact); + int recordsCount = countRecords(readers); + Iterator iter = readers.keySet().iterator(); while (iter.hasNext()) { @@ -1079,7 +1087,7 @@ public Collection findByPeriod(MetaContact contact, Date startDate, HistoryReader reader = (HistoryReader) readers.get(item); // add the progress listeners - addHistorySearchProgressListeners(reader, readers.size()); + addHistorySearchProgressListeners(reader, recordsCount); Iterator recs = reader.findByPeriod(startDate, endDate, keywords, SEARCH_FIELD, caseSensitive); while (recs.hasNext()) @@ -1118,6 +1126,8 @@ public Collection findByKeyword(MetaContact contact, String keyword, // get the readers for this contact Hashtable readers = getHistoryReaders(contact); + int recordsCount = countRecords(readers); + Iterator iter = readers.keySet().iterator(); while (iter.hasNext()) { @@ -1125,7 +1135,7 @@ public Collection findByKeyword(MetaContact contact, String keyword, HistoryReader reader = (HistoryReader) readers.get(item); // add the progress listeners - addHistorySearchProgressListeners(reader, readers.size()); + addHistorySearchProgressListeners(reader, recordsCount); Iterator recs = reader. findByKeyword(keyword, SEARCH_FIELD, caseSensitive); while (recs.hasNext()) @@ -1164,6 +1174,8 @@ public Collection findByKeywords(MetaContact contact, String[] keywords, // get the readers for this contact Hashtable readers = getHistoryReaders(contact); + int recordsCount = countRecords(readers); + Iterator iter = readers.keySet().iterator(); while (iter.hasNext()) { @@ -1171,7 +1183,7 @@ public Collection findByKeywords(MetaContact contact, String[] keywords, HistoryReader reader = (HistoryReader) readers.get(item); // add the progress listeners - addHistorySearchProgressListeners(reader, readers.size()); + addHistorySearchProgressListeners(reader, recordsCount); Iterator recs = reader. findByKeywords(keywords, SEARCH_FIELD, caseSensitive); while (recs.hasNext()) @@ -1218,6 +1230,30 @@ private Hashtable getHistoryReaders(MetaContact contact) return readers; } + /** + * Total count of records for supplied history readers will read through + * + * @param readers hashtable with pairs contact <-> history reader + * @return the number of searched messages + * @throws UnsupportedOperationException + * Thrown if an exception occurs during the execution of the + * query, such as internal IO error. + */ + public int countRecords(Hashtable readers) + { + int result = 0; + + Enumeration readersEnum = readers.elements(); + + while (readersEnum.hasMoreElements()) + { + HistoryReader r = (HistoryReader)readersEnum.nextElement(); + result += r.countRecords(); + } + + return result; + } + /** * Returns all the messages exchanged in the supplied * chat room after the given date @@ -1642,62 +1678,78 @@ private class SearchProgressWrapper implements HistorySearchProgressListener { private MessageHistorySearchProgressListener listener = null; - int contactCount = 0; - int currentContactCount = 0; - int currentProgress = 0; - int lastHistoryProgress = 0; + int allRecords = 0; + HistoryReader reader = null; + double currentReaderProgressRatio = 0; + double accumulatedRatio = 0; + double currentProgress = 0; + double lastHistoryProgress = 0; + + // used for more precise calculations with double values + int raiser = 1000; SearchProgressWrapper(MessageHistorySearchProgressListener listener) { this.listener = listener; } + + private void setCurrentValues(HistoryReader currentReader, int allRecords) + { + this.allRecords = allRecords; + this.reader = currentReader; + currentReaderProgressRatio = + (double)currentReader.countRecords()/allRecords * raiser; + accumulatedRatio += currentReaderProgressRatio; + } public void progressChanged(ProgressEvent evt) { - int progress = getProgressMapping(evt.getProgress()); + int progress = getProgressMapping(evt); + currentProgress = progress; listener.progressChanged( new net.java.sip.communicator.service.msghistory.event. ProgressEvent(MessageHistoryServiceImpl.this, - evt, progress)); + evt, progress/raiser)); } /** - * Calculates the progress according the count of the contacts + * Calculates the progress according the count of the records * we will search * @param historyProgress int * @return int */ - private int getProgressMapping(int historyProgress) + private int getProgressMapping(ProgressEvent evt) { - currentProgress += (historyProgress - lastHistoryProgress)/contactCount; - - if(historyProgress == HistorySearchProgressListener.PROGRESS_MAXIMUM_VALUE) + double tmpHistoryProgress = + currentReaderProgressRatio * evt.getProgress(); + + currentProgress += tmpHistoryProgress - lastHistoryProgress; + + if(evt.getProgress() == HistorySearchProgressListener.PROGRESS_MAXIMUM_VALUE) { - currentContactCount++; lastHistoryProgress = 0; - + // this is the last one and the last event fire the max // there will be looses in currentProgress due to the devision - if(currentContactCount == contactCount) - currentProgress = + if((int)accumulatedRatio == raiser) + currentProgress = raiser * MessageHistorySearchProgressListener.PROGRESS_MAXIMUM_VALUE; } else - lastHistoryProgress = historyProgress; - - return currentProgress; + lastHistoryProgress = tmpHistoryProgress; + + return (int)currentProgress; } /** * clear the values */ void clear() - { - contactCount = 0; + { + allRecords = 0; currentProgress = 0; lastHistoryProgress = 0; - currentContactCount = 0; } } diff --git a/src/net/java/sip/communicator/service/history/HistoryReader.java b/src/net/java/sip/communicator/service/history/HistoryReader.java index 346c40e1b..0b45a3115 100644 --- a/src/net/java/sip/communicator/service/history/HistoryReader.java +++ b/src/net/java/sip/communicator/service/history/HistoryReader.java @@ -184,4 +184,15 @@ public QueryResultSet findByPeriod(Date startDate, Date endDate, * @param listener HistorySearchProgressListener */ public void removeSearchProgressListener(HistorySearchProgressListener listener); + + /** + * Total count of records that current history reader will read through + * + * @return the number of searched messages + * @throws UnsupportedOperationException + * Thrown if an exception occurs during the execution of the + * query, such as internal IO error. + */ + public int countRecords() + throws UnsupportedOperationException; }