Changeset b365817


Ignore:
Timestamp:
Apr 23, 2014 7:40:57 PM (6 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
1e4b433
Parents:
bbb0477
Message:
  • SusiMail?:
    • Queue deletions for a delayed background thread
    • Synch all folder access
    • NPE fixes
    • Javadoc fixes
Files:
1 added
7 edited

Legend:

Unmodified
Added
Removed
  • apps/susimail/src/src/i2p/susi/util/Folder.java

    rbbb0477 rb365817  
    4343 * currentPageIterator().
    4444 *
    45  * Warning - unsynchronized - not thread safe
     45 * All public methods are synchronized.
    4646 *
    4747 * @author susi
     
    7878         * @return Returns the current page.
    7979         */
    80         public int getCurrentPage() {
     80        public synchronized int getCurrentPage() {
    8181                return currentPage;
    8282        }
     
    8787         * @param currentPage The current page to set.
    8888         */
    89         public void setCurrentPage(int currentPage) {
     89        public synchronized void setCurrentPage(int currentPage) {
    9090                if( currentPage >= 1 && currentPage <= pages )
    9191                        this.currentPage = currentPage;
     
    9797         * @return Returns the size of the folder.
    9898         */
    99         public int getSize() {
     99        public synchronized int getSize() {
    100100                return elements != null ? elements.length : 0;
    101101        }
     
    105105         * @return Returns the number of pages.
    106106         */
    107         public int getPages() {
     107        public synchronized int getPages() {
    108108                return pages;
    109109        }
     
    115115         * @return Returns the pageSize.
    116116         */
    117         public int getPageSize() {
     117        public synchronized int getPageSize() {
    118118                return pageSize > 0 ? pageSize : Config.getProperty( PAGESIZE, DEFAULT_PAGESIZE );
    119119        }
     
    124124         * @param pageSize The page size to set.
    125125         */
    126         public void setPageSize(int pageSize) {
     126        public synchronized void setPageSize(int pageSize) {
    127127                if( pageSize > 0 )
    128128                        this.pageSize = pageSize;
     
    181181         * @param elements Array of Os.
    182182         */
    183         public void setElements( O[] elements )
     183        public synchronized void setElements( O[] elements )
    184184        {
    185185                if (elements.length > 0) {
     
    199199         * @param element to remove
    200200         */
    201         public void removeElement(O element) {
     201        public synchronized void removeElement(O element) {
    202202                removeElements(Collections.singleton(element));
    203203        }
     
    206206         * Remove elements
    207207         *
    208          * @param elements to remove
     208         * @param elems to remove
    209209         */
    210210        @SuppressWarnings("unchecked")
    211         public void removeElements(Collection<O> elems) {
     211        public synchronized void removeElements(Collection<O> elems) {
    212212                if (elements != null) {
    213213                        List<O> list = new ArrayList<O>(Arrays.asList(elements));
     
    229229        /**
    230230         * Returns an iterator containing the elements on the current page.
     231         * This iterator is over a copy of the current page, and so
     232         * is thread safe w.r.t. other operations on this folder,
     233         * but will not reflect subsequent changes, and iter.remove()
     234         * will not change the folder.
     235         *
    231236         * @return Iterator containing the elements on the current page.
    232237         */
    233         public Iterator<O> currentPageIterator()
     238        public synchronized Iterator<O> currentPageIterator()
    234239        {
    235240                ArrayList<O> list = new ArrayList<O>();
     
    248253         * Turns folder to next page.
    249254         */
    250         public void nextPage()
     255        public synchronized void nextPage()
    251256        {
    252257                currentPage++;
     
    258263         * Turns folder to previous page.
    259264         */
    260         public void previousPage()
     265        public synchronized void previousPage()
    261266        {
    262267                currentPage--;
     
    268273         * Sets folder to display first page.
    269274         */
    270         public void firstPage()
     275        public synchronized void firstPage()
    271276        {
    272277                currentPage = 1;
     
    276281         * Sets folder to display last page.
    277282         */
    278         public void lastPage()
     283        public synchronized void lastPage()
    279284        {
    280285                currentPage = pages;
     
    288293         * @param sorter a Comparator to sort the Array given by @link setElements()
    289294         */
    290         public void addSorter( String id, Comparator<O> sorter )
     295        public synchronized void addSorter( String id, Comparator<O> sorter )
    291296        {
    292297                this.sorter.put( id, sorter );
     
    300305         * @param id ID to identify the Comparator stored with @link addSorter()
    301306         */
    302         public void sortBy( String id )
     307        public synchronized void sortBy( String id )
    303308        {
    304309                currentSorter = sorter.get( id );
     
    314319         * @return Element on the current page on the given position.
    315320         */
    316         public O getElementAtPosXonCurrentPage( int x )
     321        public synchronized O getElementAtPosXonCurrentPage( int x )
    317322        {
    318323                O result = null;
     
    333338         * @param direction @link UP or @link DOWN
    334339         */
    335         public void setSortingDirection(SortOrder direction)
     340        public synchronized void setSortingDirection(SortOrder direction)
    336341        {
    337342                sortingDirection = direction;
     
    343348         * @return First element.
    344349         */
    345         public O getFirstElement()
     350        public synchronized O getFirstElement()
    346351        {
    347352                return elements == null ? null : getElement( 0 );
     
    353358         * @return Last element.
    354359         */
    355         public O getLastElement()
     360        public synchronized O getLastElement()
    356361        {
    357362                return elements == null ? null : getElement(  elements.length - 1 );
     
    380385         * @return The next element
    381386         */
    382         public O getNextElement( O element )
     387        public synchronized O getNextElement( O element )
    383388        {
    384389                O result = null;
     
    400405         * @return The previous element
    401406         */
    402         public O getPreviousElement( O element )
     407        public synchronized O getPreviousElement( O element )
    403408        {
    404409                O result = null;
     
    432437         * Returns true, if folder shows points to the last page.
    433438         */
    434         public boolean isLastPage()
     439        public synchronized boolean isLastPage()
    435440        {
    436441                return currentPage == pages;
     
    440445         * Returns true, if folder shows points to the first page.
    441446         */
    442         public boolean isFirstPage()
     447        public synchronized boolean isFirstPage()
    443448        {
    444449                return currentPage == 1;
     
    450455         * @param element
    451456         */
    452         public boolean isLastElement( O element )
     457        public synchronized boolean isLastElement( O element )
    453458        {
    454459                if( elements == null )
     
    462467         * @param element
    463468         */
    464         public boolean isFirstElement( O element )
     469        public synchronized boolean isFirstElement( O element )
    465470        {
    466471                if( elements == null )
  • apps/susimail/src/src/i2p/susi/webmail/Mail.java

    rbbb0477 rb365817  
    224224         * to the builder, separated by tabs.
    225225         *
    226          * @param text comma-separated
    227226         * @param buf out param
    228227         * @param prefix prepended to the addresses
  • apps/susimail/src/src/i2p/susi/webmail/MailCache.java

    rbbb0477 rb365817  
    262262                if (toDelete.isEmpty())
    263263                        return;
    264                 mailbox.delete(toDelete);
     264                mailbox.queueForDeletion(toDelete);
    265265        }
    266266
  • apps/susimail/src/src/i2p/susi/webmail/WebMail.java

    rbbb0477 rb365817  
    887887                                         * extract original sender from Reply-To: or From:
    888888                                         */
    889                                         MailPart part = mail.getPart();
     889                                        MailPart part = mail != null ? mail.getPart() : null;
    890890                                        if (part != null) {
    891891                                                if( reply || replyAll ) {
     
    11741174                                int hashCode = Integer.parseInt( str );
    11751175                                Mail mail = sessionObject.mailCache.getMail( sessionObject.showUIDL, MailCache.FETCH_ALL );
    1176                                 MailPart part = getMailPartFromHashCode( mail.getPart(), hashCode );
     1176                                MailPart part = mail != null ? getMailPartFromHashCode( mail.getPart(), hashCode ) : null;
    11771177                                if( part != null )
    11781178                                        sessionObject.showAttachment = part;
     
    19111911                        String uidl = it.next();
    19121912                        Mail mail = sessionObject.mailCache.getMail( uidl, MailCache.FETCH_HEADER );
     1913                        if (mail == null)
     1914                                continue;
    19131915                        String link = "<a href=\"" + myself + "?" + SHOW + "=" + i + "\">";
    19141916                       
  • apps/susimail/src/src/i2p/susi/webmail/pop3/POP3MailBox.java

    rbbb0477 rb365817  
    3737import java.util.HashMap;
    3838import java.util.List;
     39import java.util.Map;
     40import java.util.concurrent.atomic.AtomicLong;
    3941
    4042import net.i2p.data.DataHelper;
     
    6466
    6567        private Socket socket;
     68        private final AtomicLong lastActive;
    6669
    6770        private final Object synchronizer;
     71        private final DelayedDeleter delayedDeleter;
    6872
    6973        /**
     
    8892                // this appears in the UI so translate
    8993                lastLine = _("No response from server");
     94                lastActive = new AtomicLong(System.currentTimeMillis());
     95                delayedDeleter = new DelayedDeleter(this);
    9096        }
    9197
     
    233239        /**
    234240         * Call performDelete() after this or they will come back
     241         * UNUSED
    235242         *
    236243         * @param uidl
    237244         * @return Success of delete operation: true if successful.
    238245         */
     246/****
    239247        public boolean delete( String uidl )
    240248        {
     
    254262                }
    255263        }
    256 
    257         /**
    258          * Delete all at once, close and reconnect
    259          * Do NOT call performDelete() after this
    260          * Does not provide any success/failure result
     264****/
     265
     266        /**
     267         * Queue for later deletion. Non-blocking.
    261268         *
    262269         * @since 0.9.13
    263270         */
    264         public void delete(Collection<String> uidls) {
     271        public void queueForDeletion(Collection<String> uidls) {
     272                for (String uidl : uidls) {
     273                        delayedDeleter.queueDelete(uidl);
     274                }
     275        }
     276
     277        /**
     278         * Delete all at once and close. Does not reconnect.
     279         * Do NOT call performDelete() after this.
     280         * Returns all UIDLs successfully deleted OR were not known by the server.
     281         *
     282         * @since 0.9.13
     283         */
     284        Collection<String> delete(Collection<String> uidls) {
     285                List<String> rv = new ArrayList<String>(uidls.size());
    265286                List<SendRecv> srs = new ArrayList<SendRecv>(uidls.size() + 1);
    266287                synchronized( synchronizer ) {
     
    270291                        } catch (IOException ioe) {
    271292                                Debug.debug( Debug.DEBUG, "Error deleting: " + ioe);
    272                                 return;
     293                                return rv;
    273294                        }
    274295                        for (String uidl : uidls) {
    275296                                int id = getIDfromUIDL(uidl);
    276                                 if (id < 0)
     297                                if (id < 0) {
     298                                        // presumed already deleted
     299                                        rv.add(uidl);
    277300                                        continue;
     301                                }
    278302                                SendRecv sr = new SendRecv("DELE " + id, Mode.A1);
     303                                sr.savedObject = uidl;
    279304                                srs.add(sr);
    280305                        }
    281306                        if (srs.isEmpty())
    282                                 return;
     307                                return rv;
    283308                        // TODO don't quit now, just set timer to quit later
    284                         SendRecv sr = new SendRecv("QUIT", Mode.A1);
    285                         srs.add(sr);
     309                        SendRecv quit = new SendRecv("QUIT", Mode.A1);
     310                        srs.add(quit);
    286311                        try {
    287312                                sendCmds(srs);
     313                                // do NOT call close() here, we included QUIT above
    288314                                try {
    289315                                        socket.close();
    290316                                } catch (IOException e) {}
    291317                                clear();
     318                                // result of QUIT
     319                                boolean success = srs.get(srs.size() - 1).result;
     320                                if (success) {
     321                                        for (int i = 0; i < srs.size() - 1; i++) {
     322                                                SendRecv sr = srs.get(i);
     323                                                // ignore sr.result, if it failed it's because
     324                                                // it's already deleted
     325                                                rv.add((String) sr.savedObject);
     326                                        }
     327                                }
    292328                                // why reconnect?
    293329                                //connect();
     
    297333                        }
    298334                }
     335                return rv;
    299336        }
    300337       
    301338        /**
    302339         * delete message on pop3 server
     340         * UNUSED
    303341         *
    304342         * @param id message id
    305343         * @return Success of delete operation: true if successful.
    306344         */
     345/****
    307346        private boolean delete(int id)
    308347        {
     
    321360                return result;
    322361        }
     362****/
    323363
    324364        /**
     
    386426                                throw new IOException("Cannot connect");
    387427                }
     428        }
     429
     430        /**
     431         * Timestamp.
     432         *
     433         * @since 0.9.13
     434         */
     435        private void updateActivity() {
     436                lastActive.set(System.currentTimeMillis());
     437        }
     438
     439        /**
     440         * Timestamp.
     441         *
     442         * @since 0.9.13
     443         */
     444        long getLastActivity() {
     445                return lastActive.get();
    388446        }
    389447
     
    629687                socket.getOutputStream().flush();
    630688                String foo = DataHelper.readLine(socket.getInputStream());
     689                updateActivity();
    631690                // Debug.debug(Debug.DEBUG, "sendCmd1a: read " + read + " bytes");
    632691                if (foo != null) {
     
    685744                        }
    686745                        String foo = DataHelper.readLine(in);
     746                        updateActivity();
    687747                        if (foo == null) {
    688748                                lastError = _("No response from server");
     
    748808                cmd += "\r\n";
    749809                socket.getOutputStream().write(DataHelper.getASCII(cmd));
     810                updateActivity();
    750811        }
    751812
     
    830891                ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
    831892                while (DataHelper.readLine(input, buf)) {
     893                        updateActivity();
    832894                        int len = buf.length();
    833895                        if (len == 0)
     
    868930                StringBuilder buf = new StringBuilder(512);
    869931                while (DataHelper.readLine(input, buf)) {
     932                        updateActivity();
    870933                        int len = buf.length();
    871934                        if (len == 0)
     
    919982
    920983        /**
    921          *  Close without waiting for response
     984         *  Close without waiting for response,
     985         *  and remove any delayed tasks and resources.
     986         */
     987        public void destroy() {
     988                delayedDeleter.cancel();
     989                close(false);
     990        }
     991
     992        /**
     993         *  Close without waiting for response.
     994         *  Deletes all queued deletions.
    922995         */
    923996        public void close() {
     
    926999
    9271000        /**
    928          *  Close and optionally waiting for response
     1001         *  Close and optionally wait for response.
     1002         *  Deletes all queued deletions.
    9291003         *  @since 0.9.13
    9301004         */
     
    9341008                        if (socket != null && socket.isConnected()) {
    9351009                                try {
    936                                         if (shouldWait)
    937                                                 sendCmd1a("QUIT");
    938                                         else
     1010                                        Collection<String> toDelete = delayedDeleter.getQueued();
     1011                                        Map<String, Integer> sendDelete = new HashMap<String, Integer>(toDelete.size());
     1012                                        for (String uidl : toDelete) {
     1013                                                int id = getIDfromUIDL(uidl);
     1014                                                if (id >= 0) {
     1015                                                        sendDelete.put(uidl, Integer.valueOf(id));
     1016                                                }
     1017                                        }
     1018                                        if (shouldWait) {
     1019                                                if (!sendDelete.isEmpty()) {
     1020                                                        // Verify deleted, remove from the delete queue
     1021                                                        // this does the quit and close
     1022                                                        Collection<String> deleted = delete(sendDelete.keySet());
     1023                                                        for (String uidl : deleted) {
     1024                                                                delayedDeleter.removeQueued(uidl);
     1025                                                        }
     1026                                                } else {
     1027                                                        sendCmd1a("QUIT");
     1028                                                }
     1029                                        } else {
     1030                                                if (!sendDelete.isEmpty()) {
     1031                                                        // spray and pray the deletions, don't remove from delete queue
     1032                                                        for (Integer id : sendDelete.values()) {
     1033                                                                sendCmd1aNoWait("DELE " + id);
     1034                                                        }
     1035                                                }
    9391036                                                sendCmd1aNoWait("QUIT");
     1037                                        }
    9401038                                        socket.close();
    9411039                                } catch (IOException e) {}
     
    10131111        /**
    10141112         *  Close and reconnect. Takes a while.
    1015          */
     1113         *  UNUSED
     1114         */
     1115/****
    10161116        public void performDelete()
    10171117        {
     
    10221122                }
    10231123        }
    1024 
     1124****/
     1125
     1126        /** for SendRecv */
    10251127        private enum Mode {
    10261128                /** no extra lines (sendCmd1a) */
  • history.txt

    rbbb0477 rb365817  
     12014-04-23 zzz
     2 * SusiMail:
     3   - Queue deletions for a later thread
     4   - Synch all folder access
     5
    162014-04-22 zzz
    27 * SusiMail:
  • router/java/src/net/i2p/router/RouterVersion.java

    rbbb0477 rb365817  
    1919    public final static String ID = "Monotone";
    2020    public final static String VERSION = CoreVersion.VERSION;
    21     public final static long BUILD = 8;
     21    public final static long BUILD = 9;
    2222
    2323    /** for example "-test" */
Note: See TracChangeset for help on using the changeset viewer.