Changeset 7bf3ea5


Ignore:
Timestamp:
Apr 21, 2014 11:00:46 PM (7 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
611f991f, b43ebd2
Parents:
490727b
Message:
  • SusiMail?:
    • Pipeline all deletes and quit
    • Don't reconnect after delete and quit
    • Verify connected before each POP3 operation
    • Null check in comparators
    • Don't clear messages if a reconnection fails
    • Use locale-based sorting for strings
    • Increase limit for full fetch again
    • Increase default page size back again
Location:
apps/susimail/src
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • apps/susimail/src/src/i2p/susi/debug/Debug.java

    r490727b r7bf3ea5  
    3838        {
    3939                level = newLevel;
    40         }       
     40        }
     41
     42        /** @since 0.9.13 */
     43        public static int getLevel() {
     44                return level;
     45        }
    4146
    4247        public static void debug( int msgLevel, String msg )
  • apps/susimail/src/src/i2p/susi/util/Folder.java

    r490727b r7bf3ea5  
    2727import java.util.ArrayList;
    2828import java.util.Arrays;
     29import java.util.Collection;
     30import java.util.Collections;
    2931import java.util.Comparator;
    3032import java.util.Hashtable;
    3133import java.util.Iterator;
     34import java.util.List;
    3235
    3336/**
     
    186189                update();
    187190        }
     191
     192        /**
     193         * Remove an element
     194         *
     195         * @param element to remove
     196         */
     197        public void removeElement(O element) {
     198                removeElements(Collections.singleton(element));
     199        }
     200       
     201        /**
     202         * Remove elements
     203         *
     204         * @param elements to remove
     205         */
     206        @SuppressWarnings("unchecked")
     207        public void removeElements(Collection<O> elems) {
     208                if (elements != null) {
     209                        List<O> list = new ArrayList<O>(Arrays.asList(elements));
     210                        for (O e : elems) {
     211                                list.remove(e);
     212                        }
     213                        elements = (O[]) list.toArray(new Object[list.size()]);
     214                }
     215                if (unsortedElements != null) {
     216                        List<O> list = new ArrayList<O>(Arrays.asList(unsortedElements));
     217                        for (O e : elems) {
     218                                list.remove(e);
     219                        }
     220                        unsortedElements = (O[]) list.toArray(new Object[list.size()]);
     221                }
     222                update();
     223        }
    188224       
    189225        /**
  • apps/susimail/src/src/i2p/susi/webmail/Mail.java

    r490727b r7bf3ea5  
    7171
    7272        public boolean markForDeletion;
    73 
    74         public boolean deleted;
    7573       
    7674        public Mail(String uidl) {
  • apps/susimail/src/src/i2p/susi/webmail/MailCache.java

    r490727b r7bf3ea5  
    3030import java.util.ArrayList;
    3131import java.util.Collection;
     32import java.util.Collections;
    3233import java.util.Hashtable;
    3334import java.util.List;
     
    4748         *  and bodies will compress well.
    4849         */
    49         private static final int FETCH_ALL_SIZE = 3072;
     50        private static final int FETCH_ALL_SIZE = 4096;
    5051
    5152        /**
     
    6869                Mail mail = null, newMail = null;
    6970
    70                         /*
    71                          * synchronize update to hashtable
    72                          */
    73                         synchronized(mails) {
    74                                 mail = mails.get( uidl );
    75                                 if( mail == null ) {
    76                                         newMail = new Mail(uidl);
    77                                         mails.put( uidl, newMail );
    78                                 }
    79                         }
     71                /*
     72                 * synchronize update to hashtable
     73                 */
     74                synchronized(mails) {
     75                        mail = mails.get( uidl );
    8076                        if( mail == null ) {
    81                                 mail = newMail;
    82                                 mail.size = mailbox.getSize( uidl );
    83                         }
    84                         if( mail.size <= FETCH_ALL_SIZE)
    85                                 headerOnly = false;
     77                                newMail = new Mail(uidl);
     78                                mails.put( uidl, newMail );
     79                        }
     80                }
     81                if( mail == null ) {
     82                        mail = newMail;
     83                        mail.size = mailbox.getSize( uidl );
     84                }
     85                if (mail.markForDeletion)
     86                        return null;
     87                if( mail.size <= FETCH_ALL_SIZE)
     88                        headerOnly = false;
    8689                       
    87                         if( headerOnly ) {
    88                                 if(!mail.hasHeader())
    89                                         mail.setHeader(mailbox.getHeader(uidl));
    90                         }
    91                         else {
    92                                 if(!mail.hasBody()) {
    93                                         mail.setBody(mailbox.getBody(uidl));
    94                                 }
    95                         }
    96                 if( mail != null && mail.deleted )
    97                         mail = null;
     90                if( headerOnly ) {
     91                        if(!mail.hasHeader())
     92                                mail.setHeader(mailbox.getHeader(uidl));
     93                } else {
     94                        if(!mail.hasBody()) {
     95                                mail.setBody(mailbox.getBody(uidl));
     96                        }
     97                }
    9898                return mail;
    9999        }
     
    129129                                mail.size = mailbox.getSize( uidl );
    130130                        }
    131                         if(!mail.deleted) {
    132                                 mr.setMail(mail);
    133                                 if( mail.size <= FETCH_ALL_SIZE)
    134                                         headerOnly = false;
    135                                 if( headerOnly ) {
    136                                         if(!mail.hasHeader()) {
    137                                                 POP3Request pr = new POP3Request(mr, mail, true);
    138                                                 fetches.add(pr);
    139                                         }
    140                                 } else {
    141                                         if(!mail.hasBody()) {
    142                                                 POP3Request pr = new POP3Request(mr, mail, false);
    143                                                 fetches.add(pr);
    144                                         }
     131                        if (mail.markForDeletion)
     132                                continue;
     133                        mr.setMail(mail);
     134                        if( mail.size <= FETCH_ALL_SIZE)
     135                                headerOnly = false;
     136                        if( headerOnly ) {
     137                                if(!mail.hasHeader()) {
     138                                        POP3Request pr = new POP3Request(mr, mail, true);
     139                                        fetches.add(pr);
     140                                }
     141                        } else {
     142                                if(!mail.hasBody()) {
     143                                        POP3Request pr = new POP3Request(mr, mail, false);
     144                                        fetches.add(pr);
    145145                                }
    146146                        }
     
    169169
    170170        /**
     171         * Mark mail for deletion locally.
     172         * Send delete requests to POP3 then quit and reconnect.
     173         * No success/failure indication is returned.
     174         *
     175         * @since 0.9.13
     176         */
     177        public void delete(String uidl) {
     178                delete(Collections.singleton(uidl));
     179        }
     180
     181        /**
     182         * Mark mail for deletion locally.
     183         * Send delete requests to POP3 then quit and reconnect.
     184         * No success/failure indication is returned.
     185         *
     186         * @since 0.9.13
     187         */
     188        public void delete(Collection<String> uidls) {
     189                List<String> toDelete = new ArrayList<String>(uidls.size());
     190                for (String uidl : uidls) {
     191                        Mail mail = mails.get(uidl);
     192                        if (mail == null)
     193                                continue;
     194                        mail.markForDeletion = true;
     195                        toDelete.add(uidl);
     196                }
     197                if (toDelete.isEmpty())
     198                        return;
     199                mailbox.delete(toDelete);
     200        }
     201
     202        /**
    171203         *  Incoming to us
    172204         */
  • apps/susimail/src/src/i2p/susi/webmail/WebMail.java

    r490727b r7bf3ea5  
    4646import java.io.StringWriter;
    4747import java.io.UnsupportedEncodingException;
     48import java.text.Collator;
    4849import java.util.ArrayList;
    4950import java.util.Comparator;
     
    212213                        Mail a = mailCache.getMail( arg0, MailCache.FETCH_HEADER );
    213214                        Mail b = mailCache.getMail( arg1, MailCache.FETCH_HEADER );
     215                        if (a == null)
     216                                return (b == null) ? 0 : 1;
     217                        if (b == null)
     218                                return -1;
    214219                        return a.id - b.id;
    215220                }               
     
    222227         */
    223228        private static class SenderSorter implements Comparator<String> {
     229                private final Comparator collator = Collator.getInstance();
    224230                private final MailCache mailCache;
    225231               
     
    239245                        Mail a = mailCache.getMail( arg0, MailCache.FETCH_HEADER );
    240246                        Mail b = mailCache.getMail( arg1, MailCache.FETCH_HEADER );
    241                         return a.formattedSender.compareToIgnoreCase( b.formattedSender );
     247                        if (a == null)
     248                                return (b == null) ? 0 : 1;
     249                        if (b == null)
     250                                return -1;
     251                        return collator.compare(a.formattedSender, b.formattedSender);
    242252                }               
    243253        }
     
    249259        private static class SubjectSorter implements Comparator<String> {
    250260
     261                private final Comparator collator = Collator.getInstance();
    251262                private final MailCache mailCache;
    252263                /**
     
    265276                        Mail a = mailCache.getMail( arg0, MailCache.FETCH_HEADER );
    266277                        Mail b = mailCache.getMail( arg1, MailCache.FETCH_HEADER );
    267                         return a.formattedSubject.compareToIgnoreCase( b.formattedSubject );
     278                        if (a == null)
     279                                return (b == null) ? 0 : 1;
     280                        if (b == null)
     281                                return -1;
     282                        return collator.compare(a.formattedSubject, b.formattedSubject);
    268283                }               
    269284        }
     
    291306                        Mail a = mailCache.getMail( arg0, MailCache.FETCH_HEADER );
    292307                        Mail b = mailCache.getMail( arg1, MailCache.FETCH_HEADER );
     308                        if (a == null)
     309                                return (b == null) ? 0 : 1;
     310                        if (b == null)
     311                                return -1;
    293312                        return a.date != null ? ( b.date != null ? a.date.compareTo( b.date ) : -1 ) : ( b.date != null ? 1 : 0 );
    294313                }               
     
    316335                        Mail a = mailCache.getMail( arg0, MailCache.FETCH_HEADER );
    317336                        Mail b = mailCache.getMail( arg1, MailCache.FETCH_HEADER );
     337                        if (a == null)
     338                                return (b == null) ? 0 : 1;
     339                        if (b == null)
     340                                return -1;
    318341                        return a.size - b.size;
    319342                }               
     
    9911014                if( buttonPressed( request, REFRESH ) ) {
    9921015                        sessionObject.mailbox.refresh();
    993                         sessionObject.folder.setElements( sessionObject.mailbox.getUIDLs() );
     1016                        String[] uidls = sessionObject.mailbox.getUIDLs();
     1017                        if (uidls != null)
     1018                                sessionObject.folder.setElements(uidls);
    9941019                        sessionObject.pageChanged = true;
    9951020                }
     
    11151140                                        sessionObject.state = STATE_LIST;
    11161141                        }
    1117                         sessionObject.mailbox.delete( sessionObject.showUIDL );
    1118                         sessionObject.mailbox.performDelete();
    1119                         sessionObject.folder.setElements( sessionObject.mailbox.getUIDLs() );
     1142                        sessionObject.mailCache.delete( sessionObject.showUIDL );
     1143                        sessionObject.folder.removeElement(sessionObject.showUIDL);
    11201144                        sessionObject.showUIDL = nextUIDL;
    11211145                }
     
    12031227                }
    12041228                else {
    1205                         int numberDeleted = 0;
    12061229                        if( buttonPressed( request, REALLYDELETE ) ) {
     1230                                List<String> toDelete = new ArrayList<String>();
    12071231                                for( Enumeration<String> e = request.getParameterNames(); e.hasMoreElements(); ) {
    12081232                                        String parameter = e.nextElement();
     
    12121236                                                        int n = Integer.parseInt( number );
    12131237                                                        String uidl = sessionObject.folder.getElementAtPosXonCurrentPage( n );
    1214                                                         if( uidl != null ) {
    1215                                                                 Mail mail = sessionObject.mailCache.getMail( uidl, MailCache.FETCH_HEADER );
    1216                                                                 if( mail != null ) {
    1217                                                                         if( sessionObject.mailbox.delete( uidl ) ) {
    1218                                                                                 mail.markForDeletion = true;
    1219                                                                                 numberDeleted++;
    1220                                                                         }
    1221                                                                         else
    1222                                                                                 sessionObject.error += _("Error deleting message: {0}", sessionObject.mailbox.lastError()) + "<br>";
    1223                                                                 }
    1224                                                         }
    1225                                                 }
    1226                                                 catch( NumberFormatException nfe ) {
    1227                                                 }
     1238                                                        if( uidl != null )
     1239                                                                toDelete.add(uidl);
     1240                                                } catch( NumberFormatException nfe ) {}
    12281241                                        }
    12291242                                }
    1230                                 sessionObject.mailbox.performDelete();
    1231                                 sessionObject.folder.setElements( sessionObject.mailbox.getUIDLs() );
    1232                                 sessionObject.pageChanged = true;
    1233                                 sessionObject.info += ngettext("1 message deleted.", "{0} messages deleted.", numberDeleted);
     1243                                int numberDeleted = toDelete.size();
     1244                                if (numberDeleted > 0) {
     1245                                        sessionObject.mailCache.delete(toDelete);
     1246                                        sessionObject.folder.removeElements(toDelete);
     1247                                        sessionObject.pageChanged = true;
     1248                                        sessionObject.info += ngettext("1 message deleted.", "{0} messages deleted.", numberDeleted);
     1249                                        //sessionObject.error += _("Error deleting message: {0}", sessionObject.mailbox.lastError()) + "<br>";
     1250                                }
    12341251                        }
    12351252                        sessionObject.reallyDelete = false;
     
    14191436                         * update folder content
    14201437                         */
    1421                         if( sessionObject.state != STATE_AUTH )
    1422                                 sessionObject.folder.setElements( sessionObject.mailbox.getUIDLs() );
     1438                        if( sessionObject.state != STATE_AUTH ) {
     1439                                String[] uidls = sessionObject.mailbox.getUIDLs();
     1440                                if (uidls != null)
     1441                                        sessionObject.folder.setElements(uidls);
     1442                        }
    14231443
    14241444                        if( ! sendAttachment( sessionObject, response ) ) {
  • apps/susimail/src/src/i2p/susi/webmail/pop3/POP3MailBox.java

    r490727b r7bf3ea5  
    9696        public ReadBuffer getHeader( String uidl ) {
    9797                synchronized( synchronizer ) {
     98                        try {
     99                                // we must be connected to know the UIDL to ID mapping
     100                                checkConnection();
     101                        } catch (IOException ioe) {
     102                                Debug.debug( Debug.DEBUG, "Error fetching: " + ioe);
     103                                return null;
     104                        }
    98105                        int id = getIDfromUIDL(uidl);
    99106                        if (id < 0)
     
    141148        public ReadBuffer getBody( String uidl ) {
    142149                synchronized( synchronizer ) {
     150                        try {
     151                                // we must be connected to know the UIDL to ID mapping
     152                                checkConnection();
     153                        } catch (IOException ioe) {
     154                                Debug.debug( Debug.DEBUG, "Error fetching: " + ioe);
     155                                return null;
     156                        }
    143157                        int id = getIDfromUIDL(uidl);
    144158                        if (id < 0)
     
    158172                List<SendRecv> srs = new ArrayList<SendRecv>(requests.size());
    159173                synchronized( synchronizer ) {
     174                        try {
     175                                // we must be connected to know the UIDL to ID mapping
     176                                checkConnection();
     177                        } catch (IOException ioe) {
     178                                Debug.debug( Debug.DEBUG, "Error fetching: " + ioe);
     179                                return;
     180                        }
    160181                        for (FetchRequest fr : requests) {
    161182                                int id = getIDfromUIDL(fr.getUIDL());
     
    209230
    210231        /**
     232         * Call performDelete() after this or they will come back
    211233         *
    212234         * @param uidl
     
    217239                Debug.debug(Debug.DEBUG, "delete(" + uidl + ")");
    218240                synchronized( synchronizer ) {
     241                        try {
     242                                // we must be connected to know the UIDL to ID mapping
     243                                checkConnection();
     244                        } catch (IOException ioe) {
     245                                Debug.debug( Debug.DEBUG, "Error deleting: " + ioe);
     246                                return false;
     247                        }
    219248                        int id = getIDfromUIDL(uidl);
    220249                        if (id < 0)
    221250                                return false;
    222251                        return delete(id);
     252                }
     253        }
     254
     255        /**
     256         * Delete all at once, close and reconnect
     257         * Do NOT call performDelete() after this
     258         * Does not provide any success/failure result
     259         *
     260         * @since 0.9.13
     261         */
     262        public void delete(Collection<String> uidls) {
     263                List<SendRecv> srs = new ArrayList<SendRecv>(uidls.size() + 1);
     264                synchronized( synchronizer ) {
     265                        try {
     266                                // we must be connected to know the UIDL to ID mapping
     267                                checkConnection();
     268                        } catch (IOException ioe) {
     269                                Debug.debug( Debug.DEBUG, "Error deleting: " + ioe);
     270                                return;
     271                        }
     272                        for (String uidl : uidls) {
     273                                int id = getIDfromUIDL(uidl);
     274                                if (id < 0)
     275                                        continue;
     276                                SendRecv sr = new SendRecv("DELE " + id, Mode.A1);
     277                                srs.add(sr);
     278                        }
     279                        if (srs.isEmpty())
     280                                return;
     281                        SendRecv sr = new SendRecv("QUIT", Mode.A1);
     282                        srs.add(sr);
     283                        try {
     284                                sendCmds(srs);
     285                                try {
     286                                        socket.close();
     287                                } catch (IOException e) {}
     288                                clear();
     289                                // why reconnect?
     290                                //connect();
     291                        } catch (IOException ioe) {
     292                                Debug.debug( Debug.DEBUG, "Error deleting: " + ioe);
     293                                // todo maybe
     294                        }
    223295                }
    224296        }
     
    282354
    283355        /**
    284          * check whether connection is still alive
     356         * Is the connection is still alive
    285357         *
    286358         * @return true or false
    287359         */
    288360        public boolean isConnected() {
    289                 Debug.debug(Debug.DEBUG, "isConnected()");
    290 
    291361                if (socket == null
    292362                        || !socket.isConnected()
     
    297367                }
    298368                return connected;
     369        }
     370
     371        /**
     372         * If not connected, connect now.
     373         * Should be called from all public methods before sending a command.
     374         * Caller must sync.
     375         *
     376         * @return true or false
     377         */
     378        private void checkConnection() throws IOException {
     379                Debug.debug(Debug.DEBUG, "checkConnection()");
     380                if (!isConnected()) {
     381                        connect();
     382                        if (!isConnected())
     383                                throw new IOException("Cannot connect");
     384                }
    299385        }
    300386
     
    382468        public void refresh() {
    383469                synchronized( synchronizer ) {
    384                         close();
     470                        close(true);
    385471                        connect();
    386472                }
     
    404490        private void connect() {
    405491                Debug.debug(Debug.DEBUG, "connect()");
     492                if (Debug.getLevel() == Debug.DEBUG)
     493                        (new Exception()).printStackTrace();
    406494
    407495                clear();
     
    650738        {
    651739                synchronized (synchronizer) {
    652                         if (!isConnected())
    653                                 connect();
    654740                        try {
    655741                                return sendCmdNa(cmd);
     
    789875                synchronized( synchronizer ) {
    790876                        Debug.debug(Debug.DEBUG, "getNumMails()");
    791 
    792                         if (!isConnected())
    793                                 connect();
    794 
     877                        try {
     878                                checkConnection();
     879                        } catch (IOException ioe) {}
    795880                        return connected ? mails : 0;
    796881                }
     
    833918                                                sendCmd1aNoWait("QUIT");
    834919                                        socket.close();
    835                                 } catch (IOException e) {
    836                                         Debug.debug( Debug.DEBUG, "Error while closing connection: " + e);
    837                                 }
     920                                } catch (IOException e) {}
    838921                        }
    839922                        socket = null;
    840923                        connected = false;
     924                        clear();
    841925                }
    842926        }
     
    878962
    879963        /**
     964         * Only if connected. Does not force a connect.
     965         * If not connected, returns null.
    880966         *
    881967         * @return A new array of the available UIDLs. No particular order.
     
    883969        public String[] getUIDLs()
    884970        {
     971                if (!isConnected())
     972                        return null;
    885973                synchronized( synchronizer ) {
    886974                       return uidlToID.keySet().toArray(new String[uidlToID.size()]);
     
    909997                synchronized( synchronizer ) {
    910998                        close(true);
    911                         connect();
     999                        // why reconnect?
     1000                        //connect();
    9121001                }
    9131002        }
  • apps/susimail/src/susimail.properties

    r490727b r7bf3ea5  
    1010susimail.sender.domain=mail.i2p
    1111
    12 susimail.pager.pagesize=20
     12susimail.pager.pagesize=30
    1313
    1414susimail.composer.cols=80
Note: See TracChangeset for help on using the changeset viewer.