Changeset 224ebb1


Ignore:
Timestamp:
Oct 9, 2008 11:58:00 AM (12 years ago)
Author:
sponge <sponge@…>
Branches:
master
Children:
4ec82be
Parents:
cb17fb8
Message:

Bugfixes for BOB, Important database locking to prevent thread collisions.

Files:
10 edited

Legend:

Unmodified
Added
Removed
  • apps/BOB/src/net/i2p/BOB/I2Plistener.java

    rcb17fb8 r224ebb1  
    4141public class I2Plistener implements Runnable {
    4242
    43         private nickname info;
     43        private nickname info,  database;
    4444        private Log _log;
    4545        private int tgwatch;
     
    5151         * @param S
    5252         * @param info
     53         * @param database
    5354         * @param _log
    5455         */
    55         I2Plistener(I2PSocketManager S, nickname info, Log _log) {
     56        I2Plistener(I2PSocketManager S, nickname info, nickname database, Log _log) {
     57                this.database = database;
    5658                this.info = info;
    5759                this._log = _log;
     
    6365        /**
    6466         * Simply listen on I2P port, and thread connections
    65          * 
    66          * @throws RuntimeException 
     67         *
     68         * @throws RuntimeException
    6769         */
    6870        public void run() throws RuntimeException {
     
    7072                I2PSocket sessSocket = null;
    7173
    72                 // needed to hack in this method :-/
    7374                serverSocket.setSoTimeout(1000);
     75                database.getReadLock();
     76                info.getReadLock();
    7477                if(info.exists("INPORT")) {
    7578                        tgwatch = 2;
    7679                }
    77                 while(info.get("RUNNING").equals(Boolean.TRUE)) {
     80                info.releaseReadLock();
     81                database.releaseReadLock();
     82                boolean spin = true;
     83                while(spin) {
     84
     85                        database.getReadLock();
     86                        info.getReadLock();
     87                        spin = info.get("RUNNING").equals(Boolean.TRUE);
     88                        info.releaseReadLock();
     89                        database.releaseReadLock();
    7890                        try {
    7991                                try {
     
    8294                                } catch(ConnectException ce) {
    8395                                        g = false;
    84                                 } catch (SocketTimeoutException ste) {
     96                                } catch(SocketTimeoutException ste) {
    8597                                        g = false;
    8698                                }
     
    88100                                        g = false;
    89101                                        // toss the connection to a new thread.
    90                                         I2PtoTCP conn_c = new I2PtoTCP(sessSocket, info);
     102                                        I2PtoTCP conn_c = new I2PtoTCP(sessSocket, info, database);
    91103                                        Thread t = new Thread(conn_c, "BOBI2PtoTCP");
    92104                                        t.start();
     
    94106
    95107                        } catch(I2PException e) {
    96                                 System.out.println("Exception "+e);
     108                        //      System.out.println("Exception " + e);
    97109                        }
    98110                }
  • apps/BOB/src/net/i2p/BOB/I2PtoTCP.java

    rcb17fb8 r224ebb1  
    3737
    3838        private I2PSocket I2P;
    39         private nickname info;
     39        private nickname info, database;
    4040        private Socket sock;
    4141
     
    4444         *
    4545         * @param I2Psock
    46          * @param db
     46         * @param info
     47         * @param database
    4748         */
    48         I2PtoTCP(I2PSocket I2Psock, nickname db) {
     49        I2PtoTCP(I2PSocket I2Psock, nickname info, nickname database) {
    4950                this.I2P = I2Psock;
    50                 this.info = db;
     51                this.info = info;
     52                this.database = database;
    5153        }
    5254
     
    5860
    5961                try {
    60                         sock = new Socket(info.get("OUTHOST").toString(), Integer.parseInt(info.get("OUTPORT").toString()));
     62                        database.getReadLock();
     63                        info.getReadLock();
     64                        String host = info.get("OUTHOST").toString();
     65                        int port = Integer.parseInt(info.get("OUTPORT").toString());
     66                        boolean tell = info.get("QUIET").equals(Boolean.FALSE);
     67                        info.releaseReadLock();
     68                        database.releaseReadLock();
     69                        sock = new Socket(host, port);
    6170                        // make readers/writers
    6271                        InputStream in = sock.getInputStream();
     
    6675                        I2P.setReadTimeout(0); // temp bugfix, this *SHOULD* be the default
    6776
    68                         if(info.get("QUIET").equals(Boolean.FALSE)) {
     77                        if(tell) {
    6978                                // tell who is connecting
    7079                                out.write(I2P.getPeerDestination().toBase64().getBytes());
     
    7382                        }
    7483                        // setup to cross the streams
    75                         TCPio conn_c = new TCPio(in, Iout, info); // app -> I2P
    76                         TCPio conn_a = new TCPio(Iin, out, info); // I2P -> app
     84                        TCPio conn_c = new TCPio(in, Iout, info, database); // app -> I2P
     85                        TCPio conn_a = new TCPio(Iin, out, info, database); // I2P -> app
    7786                        Thread t = new Thread(conn_c, "TCPioA");
    7887                        Thread q = new Thread(conn_a, "TCPioB");
  • apps/BOB/src/net/i2p/BOB/MUXlisten.java

    rcb17fb8 r224ebb1  
    4040public class MUXlisten implements Runnable {
    4141
    42         private nickname info;
     42        private nickname database,  info;
    4343        private Log _log;
    4444        private I2PSocketManager socketManager;
     
    5151         *
    5252         * @param info
     53         * @param database
    5354         * @param _log
    5455         * @throws net.i2p.I2PException
    5556         * @throws java.io.IOException
    5657         */
    57         MUXlisten(nickname info, Log _log) throws I2PException, IOException {
     58        MUXlisten(nickname database, nickname info, Log _log) throws I2PException, IOException {
     59                this.database = database;
    5860                this.info = info;
    5961                this._log = _log;
    60                 this.info.add("STARTING", Boolean.TRUE);
    6162
     63                this.database.getReadLock();
     64                this.info.getReadLock();
    6265                N = this.info.get("NICKNAME").toString();
    6366                prikey = new ByteArrayInputStream((byte[])info.get("KEYS"));
    64                 socketManager = I2PSocketManagerFactory.createManager(prikey, (Properties)info.get("PROPERTIES"));
     67                Properties Q = (Properties)info.get("PROPERTIES");
     68                this.database.releaseReadLock();
     69                this.info.releaseReadLock();
     70
     71                this.database.getWriteLock();
     72                this.info.getWriteLock();
     73                this.info.add("STARTING", Boolean.TRUE);
     74                this.info.releaseWriteLock();
     75                this.database.releaseWriteLock();
     76               
     77                socketManager = I2PSocketManagerFactory.createManager(prikey, Q);
    6578        }
    6679
     
    7184        public void run() {
    7285
    73                 tg = new ThreadGroup(N);
     86                this.database.getWriteLock();
     87                this.info.getWriteLock();
    7488                info.add("RUNNING", Boolean.TRUE);
    7589                info.add("STARTING", Boolean.FALSE);
     90                this.info.releaseWriteLock();
     91                this.database.releaseWriteLock();
    7692
    77                 // toss the connections to a new threads.
    78                 // will wrap with TCP and UDP when UDP works
    79                 if(info.exists("OUTPORT")) {
    80                         // I2P -> TCP
    81                         I2Plistener conn = new I2Plistener(socketManager, info, _log);
    82                         Thread t = new Thread(tg, conn, "BOBI2Plistener " + N);
    83                         t.start();
    84                 }
    85                 if(info.exists("INPORT")) {
    86                         // TCP -> I2P
    87                         TCPlistener conn = new TCPlistener(socketManager, info, _log);
    88                         Thread q = new Thread(tg, conn,"BOBTCPlistener" + N);
    89                         q.start();
     93                try {
     94                        tg = new ThreadGroup(N);
     95
     96                        // toss the connections to a new threads.
     97                        // will wrap with TCP and UDP when UDP works
     98                        this.database.getReadLock();
     99                        this.info.getReadLock();
     100                        boolean go_out = info.exists("OUTPORT");
     101                        boolean come_in = info.exists("INPORT");
     102                        this.database.releaseReadLock();
     103                        this.info.releaseReadLock();
     104
     105                        if(go_out) {
     106                                // I2P -> TCP
     107                                I2Plistener conn = new I2Plistener(socketManager, info, database, _log);
     108                                Thread t = new Thread(tg, conn, "BOBI2Plistener " + N);
     109                                t.start();
     110                        }
     111
     112                        if(come_in) {
     113                                // TCP -> I2P
     114                                TCPlistener conn = new TCPlistener(socketManager, info, database, _log);
     115                                Thread q = new Thread(tg, conn, "BOBTCPlistener" + N);
     116                                q.start();
     117                        }
     118
     119                        boolean spin = true;
     120                        while(spin) {
     121                                try {
     122                                        Thread.sleep(1000); //sleep for 1000 ms (One second)
     123                                } catch(InterruptedException e) {
     124                                        // nop
     125                                }
     126
     127                                this.database.getReadLock();
     128                                this.info.getReadLock();
     129                                spin = info.get("STOPPING").equals(Boolean.FALSE);
     130                                this.database.releaseReadLock();
     131                                this.info.releaseReadLock();
     132                        }
     133
     134                        this.database.getWriteLock();
     135                        this.info.getWriteLock();
     136                        info.add("RUNNING", Boolean.FALSE);
     137                        this.info.releaseWriteLock();
     138                        this.database.releaseWriteLock();
     139
     140                        // wait for child threads and thread groups to die
     141                        while(tg.activeCount() + tg.activeGroupCount() != 0) {
     142                                try {
     143                                        Thread.sleep(1000); //sleep for 1000 ms (One second)
     144                                } catch(InterruptedException ex) {
     145                                        // nop
     146                                }
     147                        }
     148                        tg.destroy();
     149                        // Zap reference to the ThreadGroup so the JVM can GC it.
     150                        tg = null;
     151                } catch(Exception e) {
    90152                }
    91153
    92                 while(info.get("STOPPING").equals(Boolean.FALSE)) {
    93                         try {
    94                                 Thread.sleep(1000); //sleep for 1000 ms (One second)
    95                         } catch(InterruptedException e) {
    96                                 // nop
    97                         }
    98                 }
    99 
     154                socketManager.destroySocketManager();
     155                // zero out everything, just incase.
     156                this.database.getWriteLock();
     157                this.info.getWriteLock();
     158                info.add("STARTING", Boolean.FALSE);
     159                info.add("STOPPING", Boolean.FALSE);
    100160                info.add("RUNNING", Boolean.FALSE);
    101                 // wait for child threads and thread groups to die
    102                 while (tg.activeCount() + tg.activeGroupCount() != 0) {
    103                         try {
    104                                 Thread.sleep(1000); //sleep for 1000 ms (One second)
    105                         } catch(InterruptedException ex) {
    106                                 // nop
    107                         }                       
    108                 }
    109                
    110                 socketManager.destroySocketManager();
    111                 tg.destroy();
    112                 // Zap reference to the ThreadGroup so the JVM can GC it.
    113                 tg = null;
    114                 info.add("STOPPING", Boolean.FALSE);
    115                 info.add("STARTING", Boolean.FALSE);
    116 
     161                this.info.releaseWriteLock();
     162                this.database.releaseWriteLock();
    117163        }
    118164}
  • apps/BOB/src/net/i2p/BOB/TCPio.java

    rcb17fb8 r224ebb1  
    3737        private InputStream Ain;
    3838        private OutputStream Aout;
    39         private nickname info;
     39        private nickname info,  database;
    4040
    4141        /**
     
    4444         * @param Ain
    4545         * @param Aout
    46          * @param db
     46         * @param info
     47         * @param database
    4748         */
    48         TCPio(InputStream Ain, OutputStream Aout, nickname db) {
     49        TCPio(InputStream Ain, OutputStream Aout, nickname info, nickname database) {
    4950                this.Ain = Ain;
    5051                this.Aout = Aout;
    51                 this.info = db;
     52                this.info = info;
     53                this.database = database;
    5254        }
    5355
     
    6466                int b;
    6567                byte a[] = new byte[1];
     68                boolean spin = true;
    6669                try {
    67                         while(info.get("RUNNING").equals(Boolean.TRUE)) {
     70                        while(spin) {
     71                                database.getReadLock();
     72                                info.getReadLock();
     73                                spin = info.get("RUNNING").equals(Boolean.TRUE);
     74                                info.releaseReadLock();
     75                                database.releaseReadLock();
     76
    6877                                b = Ain.read(a, 0, 1);
    6978                                // System.out.println(info.get("NICKNAME").toString() + " " + b);
    7079                                if(b > 0) {
    71                                         Aout.write(a,0,1);
    72                                         // Aout.flush(); too slow!
     80                                        Aout.write(a, 0, 1);
     81                                // Aout.flush(); too slow!
    7382                                } else if(b == 0) {
    7483                                        try {
     
    8897                                }
    8998                        }
    90                 } catch(IOException e) {
     99                } catch(Exception e) {
    91100                }
    92101        }
  • apps/BOB/src/net/i2p/BOB/TCPlistener.java

    rcb17fb8 r224ebb1  
    4242public class TCPlistener implements Runnable {
    4343
    44         private nickname info;
     44        private nickname info, database;
    4545        private Log _log;
    4646        private int tgwatch;
     
    5353         * @param S
    5454         * @param info
     55         * @param database
    5556         * @param _log
    5657         */
    57         TCPlistener(I2PSocketManager S, nickname info, Log _log) {
     58        TCPlistener(I2PSocketManager S, nickname info, nickname database, Log _log) {
     59                this.database = database;
    5860                this.info = info;
    5961                this._log = _log;
     
    6870        public void run() throws RuntimeException {
    6971                boolean g = false;
     72                                database.getReadLock();
     73                info.getReadLock();
    7074                if(info.exists("OUTPORT")) {
    7175                        tgwatch = 2;
     
    7680                        Socket server = new Socket();
    7781                        listener.setSoTimeout(1000);
    78                         while(info.get("RUNNING").equals(Boolean.TRUE)) {
     82                info.releaseReadLock();
     83                database.releaseReadLock();
     84                boolean spin = true;
     85                while(spin) {
     86                        database.getReadLock();
     87                        info.getReadLock();
     88                        spin = info.get("RUNNING").equals(Boolean.TRUE);
     89                        info.releaseReadLock();
     90                        database.releaseReadLock();
    7991//                              System.out.println("Thread count " + Thread.activeCount());
    8092                                try {
     
    8698                                if(g) {
    8799                                        // toss the connection to a new thread.
    88                                         TCPtoI2P conn_c = new TCPtoI2P(socketManager, server, info);
     100                                        TCPtoI2P conn_c = new TCPtoI2P(socketManager, server, info, database);
    89101                                        Thread t = new Thread(conn_c, "BOBTCPtoI2P");
    90102                                        t.start();
  • apps/BOB/src/net/i2p/BOB/TCPtoI2P.java

    rcb17fb8 r224ebb1  
    4646
    4747        private I2PSocket I2P;
    48         private nickname info;
     48        private nickname info, database;
    4949        private Socket sock;
    5050        private I2PSocketManager socketManager;
     
    8585         * @param i2p
    8686         * @param socket
    87          * @param db
     87         * @param info
     88         * @param database
    8889         */
    89         TCPtoI2P(I2PSocketManager i2p, Socket socket, nickname db) {
     90        TCPtoI2P(I2PSocketManager i2p, Socket socket, nickname info, nickname database) {
    9091                this.sock = socket;
    91                 this.info = db;
     92                this.info = info;
     93                this.database = database;
    9294                this.socketManager = i2p;
    9395        }
     
    137139                                        OutputStream Iout = I2P.getOutputStream();
    138140                                        // setup to cross the streams
    139                                         TCPio conn_c = new TCPio(in, Iout, info); // app -> I2P
    140                                         TCPio conn_a = new TCPio(Iin, out, info); // I2P -> app
     141                                        TCPio conn_c = new TCPio(in, Iout, info, database); // app -> I2P
     142                                        TCPio conn_a = new TCPio(Iin, out, info, database); // I2P -> app
    141143                                        Thread t = new Thread(conn_c, "TCPioA");
    142144                                        Thread q = new Thread(conn_a, "TCPioB");
  • apps/BOB/src/net/i2p/BOB/doCMDS.java

    rcb17fb8 r224ebb1  
    4747        // FIX ME
    4848        // I need a better way to do versioning, but this will do for now.
    49         public static final String BMAJ = "00",  BMIN = "00",  BREV = "01",  BEXT = "-8";
     49        public static final String BMAJ = "00",  BMIN = "00",  BREV = "01",  BEXT = "-9";
    5050        public static final String BOBversion = BMAJ + "." + BMIN + "." + BREV + BEXT;
    5151        private Socket server;
     
    154154        }
    155155
     156        private void rlock() {
     157                rlock(nickinfo);
     158        }
     159
     160        private void rlock(nickname Arg) {
     161                database.getReadLock();
     162                Arg.getReadLock();
     163        }
     164
     165        private void runlock() {
     166                runlock(nickinfo);
     167        }
     168
     169        private void runlock(nickname Arg) {
     170                Arg.releaseReadLock();
     171                database.releaseReadLock();
     172        }
     173
     174        private void wlock() {
     175                wlock(nickinfo);
     176        }
     177
     178        private void wlock(nickname Arg) {
     179                database.getWriteLock();
     180                Arg.getWriteLock();
     181        }
     182
     183        private void wunlock() {
     184                wunlock(nickinfo);
     185        }
     186
     187        private void wunlock(nickname Arg) {
     188                Arg.releaseWriteLock();
     189                database.releaseWriteLock();
     190        }
     191
    156192        /**
    157193         * Try to print info from the database
     
    162198         */
    163199        public void trypnt(PrintStream out, nickname info, Object key) {
    164                 out.print(" " + key + ": ");
    165                 if(info.exists(key)) {
    166                         out.print(info.get(key));
    167                 } else {
    168                         out.print("not_set");
     200                rlock(info);
     201                try {
     202                        out.print(" " + key + ": ");
     203                        if(info.exists(key)) {
     204                                out.print(info.get(key));
     205                        } else {
     206                                out.print("not_set");
     207                        }
     208                } catch(Exception e) {
    169209                }
     210                runlock(info);
    170211        }
    171212
     
    178219         */
    179220        public void tfpnt(PrintStream out, nickname info, Object key) {
    180                 out.print(" " + key + ": ");
    181                 out.print(info.exists(key));
     221                rlock(info);
     222                try {
     223                        out.print(" " + key + ": ");
     224                        out.print(info.exists(key));
     225                } catch(Exception e) {
     226                }
     227                runlock(info);
    182228        }
    183229
     
    198244         */
    199245        public void nickprint(PrintStream out, nickname info) {
     246                rlock(info);
    200247                trypnt(out, info, P_NICKNAME);
    201248                trypnt(out, info, P_STARTING);
     
    208255                trypnt(out, info, P_OUTPORT);
    209256                trypnt(out, info, P_OUTHOST);
    210                 out.println();
    211 
     257                try {
     258                        out.println();
     259                } catch(Exception e) {
     260                }
     261                runlock(info);
    212262        }
    213263
     
    215265         * Print information on a specific record, indicated by nickname
    216266         * @param out
    217          * @param database
    218267         * @param Arg
    219268         */
    220         public void ttlpnt(PrintStream out, nickname database, Object Arg) {
     269        public void ttlpnt(PrintStream out, Object Arg) {
     270                database.getReadLock();
    221271                if(database.exists(Arg)) {
    222                         out.print("DATA");
     272                        try {
     273                                out.print("DATA");
     274                        } catch(Exception e) {
     275                        }
    223276                        nickprint(out, (nickname)database.get(Arg));
    224277                }
     278                database.releaseReadLock();
    225279        }
    226280
     
    232286         */
    233287        public boolean tunnelactive(nickname Arg) {
    234                 return (Arg.get(P_STARTING).equals(Boolean.TRUE) ||
     288                rlock(Arg);
     289                boolean retval = (Arg.get(P_STARTING).equals(Boolean.TRUE) ||
    235290                        Arg.get(P_STOPPING).equals(Boolean.TRUE) ||
    236291                        Arg.get(P_RUNNING).equals(Boolean.TRUE));
    237 
     292                runlock(Arg);
     293                return retval;
    238294        }
    239295
     
    268324                        out.println("OK");
    269325                        while((line = in.readLine()) != null) {
    270                                 System.gc(); // yes, this does make a huge difference...
    271326                                StringTokenizer token = new StringTokenizer(line, " "); // use a space as a delimiter
    272327                                String Command = "";
     
    294349                                                if(ns) {
    295350                                                        if(dk) {
    296                                                                 out.println("OK " + nickinfo.get(P_DEST));
     351                                                                rlock();
     352                                                                try {
     353                                                                        out.println("OK " + nickinfo.get(P_DEST));
     354                                                                } catch(Exception e) {
     355                                                                }
     356                                                                runlock();
    297357                                                        } else {
    298358                                                                out.println("ERROR keys not set.");
     
    303363                                        } else if(Command.equals(C_list)) {
    304364                                                // Produce a formatted list of all nicknames
     365                                                database.getReadLock();
    305366                                                for(int i = 0; i < database.getcount(); i++) {
    306367                                                        try {
    307368                                                                info = (nickname)database.getnext(i);
    308                                                         } catch(RuntimeException b) {
     369                                                        } catch(Exception b) {
    309370                                                                break; // something bad happened.
    310371                                                        }
    311 
    312                                                         out.print("DATA");
     372                                                        try {
     373
     374                                                                out.print("DATA");
     375                                                        } catch(Exception e) {
     376                                                        }
     377                                                        info.getReadLock();
    313378                                                        nickprint(out, info);
    314                                                 }
     379                                                        info.releaseReadLock();
     380                                                }
     381                                                database.releaseReadLock();
    315382                                                out.println("OK Listing done");
    316383                                        } else if(Command.equals(C_quit)) {
     
    326393                                                                        prikey = new ByteArrayOutputStream();
    327394                                                                        d = I2PClientFactory.createClient().createDestination(prikey);
    328                                                                         dk = true;
     395                                                                        wlock();
    329396                                                                        nickinfo.add(P_KEYS, prikey.toByteArray());
    330397                                                                        nickinfo.add(P_DEST, d.toBase64());
    331                                                                         // System.out.println(prikey.toByteArray().length);
    332                                                                         out.println("OK " + nickinfo.get(P_DEST));
     398                                                                        dk = true;
     399                                                                        wunlock();
     400                                                                        rlock();
     401                                                                        try {
     402                                                                                out.println("OK " + nickinfo.get(P_DEST));
     403                                                                        } catch(Exception e) {
     404                                                                        }
     405                                                                        runlock();
    333406                                                                } catch(IOException ioe) {
    334407                                                                        BOB.error("Error generating keys" + ioe);
     
    346419                                                if(dk) {
    347420                                                        prikey = new ByteArrayOutputStream();
     421                                                        rlock();
    348422                                                        prikey.write(((byte[])nickinfo.get(P_KEYS)));
     423                                                        runlock();
    349424                                                        out.println("OK " + net.i2p.data.Base64.encode(prikey.toByteArray()));
    350425                                                } else {
     
    356431                                                                out.println("ERROR tunnel is active");
    357432                                                        } else {
     433                                                                wlock();
    358434                                                                nickinfo.add(P_QUIET, new Boolean(Boolean.parseBoolean(Arg) == true));
     435                                                                wunlock();
    359436                                                                out.println("OK Quiet set");
    360437                                                        }
     
    376453                                                                }
    377454                                                                if((Arg.length() == 884) && is64ok(Arg)) {
     455                                                                        wlock();
    378456                                                                        nickinfo.add(P_KEYS, prikey.toByteArray());
    379457                                                                        nickinfo.add(P_DEST, d.toBase64());
    380                                                                         out.println("OK " + nickinfo.get(P_DEST));
    381458                                                                        dk = true;
     459                                                                        wunlock();
     460                                                                        rlock();
     461                                                                        try {
     462                                                                                out.println("OK " + nickinfo.get(P_DEST));
     463                                                                        } catch(Exception e) {
     464                                                                        }
     465                                                                        runlock();
    382466                                                                } else {
    383467                                                                        out.println("ERROR not in BASE64 format");
     
    389473                                        } else if(Command.equals(C_setnick)) {
    390474                                                ns = dk = ip = op = false;
     475                                                database.getReadLock();
    391476                                                try {
    392477                                                        nickinfo = (nickname)database.get(Arg);
     
    395480                                                                ns = true;
    396481                                                        }
    397                                                 } catch(RuntimeException b) {
     482                                                } catch(Exception b) {
    398483                                                        nickinfo = null;
    399484                                                        ns = true;
    400485                                                }
    401 
     486                                                database.releaseReadLock();
    402487                                                // Clears and Sets the initial nickname structure to work with
    403488                                                if(ns) {
    404489                                                        nickinfo = new nickname();
     490                                                        wlock();
    405491                                                        database.add(Arg, nickinfo);
    406492                                                        nickinfo.add(P_NICKNAME, Arg);
     
    411497                                                        nickinfo.add(P_INHOST, "localhost");
    412498                                                        nickinfo.add(P_OUTHOST, "localhost");
    413                                                         Properties Q = props;
    414                                                         Q.setProperty("inbound.nickname", (String)nickinfo.get(P_NICKNAME));
    415                                                         Q.setProperty("outbound.nickname", (String)nickinfo.get(P_NICKNAME));
     499                                                        Properties Q = new Properties(props);
     500                                                        Q.setProperty("inbound.nickname", Arg);
     501                                                        Q.setProperty("outbound.nickname", Arg);
    416502                                                        nickinfo.add(P_PROPERTIES, Q);
     503                                                        wunlock();
    417504                                                        out.println("OK Nickname set to " + Arg);
    418505                                                } else {
     
    430517                                                                        String pname = otoken.nextToken();
    431518                                                                        String pval = otoken.nextToken();
     519                                                                        rlock();
    432520                                                                        Properties Q = (Properties)nickinfo.get(P_PROPERTIES);
     521                                                                        runlock();
    433522                                                                        Q.setProperty(pname, pval);
     523                                                                        wlock();
    434524                                                                        nickinfo.add(P_PROPERTIES, Q);
     525                                                                        wunlock();
    435526                                                                        out.println("OK " + pname + " set to " + pval);
    436527                                                                }
     
    441532                                        } else if(Command.equals(C_getnick)) {
    442533                                                // Get the nickname to work with...
     534                                                database.getReadLock();
    443535                                                try {
    444536                                                        nickinfo = (nickname)database.get(Arg);
     
    447539                                                        nns(out);
    448540                                                }
    449                                                 if(ns) {
     541                                                database.releaseReadLock();
     542                                                if(ns) {
     543                                                        rlock();
    450544                                                        dk = nickinfo.exists(P_KEYS);
    451545                                                        ip = nickinfo.exists(P_INPORT);
    452546                                                        op = nickinfo.exists(P_OUTPORT);
     547                                                        runlock();
    453548                                                        // Finally say OK.
    454549                                                        out.println("OK Nickname set to " + Arg);
     
    462557                                                        } else {
    463558                                                                int prt;
     559                                                                wlock();
    464560                                                                nickinfo.kill(P_INPORT);
    465561                                                                try {
     
    471567                                                                        out.println("ERROR not a number");
    472568                                                                }
     569                                                                wunlock();
     570                                                                rlock();
    473571                                                                ip = nickinfo.exists(P_INPORT);
     572                                                                runlock();
    474573                                                                if(ip) {
    475574                                                                        out.println("OK inbound port set");
     
    489588                                                        } else {
    490589                                                                int prt;
     590                                                                wlock();
    491591                                                                nickinfo.kill(P_OUTPORT);
    492592                                                                try {
     
    498598                                                                        out.println("ERROR not a number");
    499599                                                                }
     600                                                                wunlock();
     601                                                                rlock();
    500602                                                                ip = nickinfo.exists(P_OUTPORT);
     603                                                                runlock();
    501604                                                                if(ip) {
    502605                                                                        out.println("OK outbound port set");
     
    513616                                                                out.println("ERROR tunnel is active");
    514617                                                        } else {
     618                                                                wlock();
    515619                                                                nickinfo.add(P_INHOST, Arg);
     620                                                                wunlock();
    516621                                                                out.println("OK inhost set");
    517622                                                        }
     
    524629                                                                out.println("ERROR tunnel is active");
    525630                                                        } else {
     631                                                                wlock();
    526632                                                                nickinfo.add(P_OUTHOST, Arg);
     633                                                                wunlock();
    527634                                                                out.println("OK outhost set");
    528635                                                        }
     
    534641                                                if(ns) {
    535642                                                        out.print("OK");
     643                                                        rlock();
    536644                                                        nickprint(out, nickinfo);
     645                                                        runlock();
    537646                                                } else {
    538647                                                        nns(out);
     
    546655                                                                MUXlisten tunnel;
    547656                                                                try {
    548                                                                         tunnel = new MUXlisten(nickinfo, _log);
     657                                                                        tunnel = new MUXlisten(database, nickinfo, _log);
    549658                                                                        Thread t = new Thread(tunnel);
    550                                                                         nickinfo.add(P_STARTING, Boolean.TRUE);
    551659                                                                        t.start();
    552660                                                                        out.println("OK tunnel starting");
     
    563671                                                // Stop the tunnel, if it is running
    564672                                                if(ns) {
    565                                                         if(nickinfo.get(P_RUNNING).equals(Boolean.TRUE) && nickinfo.get(P_STOPPING).equals(Boolean.FALSE)) {
     673                                                        rlock();
     674                                                        if(nickinfo.get(P_RUNNING).equals(Boolean.TRUE) && nickinfo.get(P_STOPPING).equals(Boolean.FALSE) && nickinfo.get(P_STARTING).equals(Boolean.FALSE)) {
     675                                                                runlock();
     676                                                                wlock();
    566677                                                                nickinfo.add(P_STOPPING, Boolean.TRUE);
     678                                                                wunlock();
    567679                                                                out.println("OK tunnel stopping");
    568680                                                        } else {
     681                                                                runlock();
    569682                                                                out.println("ERROR tunnel is inactive");
    570683                                                        }
     
    578691                                                                out.println("ERROR tunnel is active");
    579692                                                        } else {
     693                                                                database.getWriteLock();
    580694                                                                database.kill(nickinfo.get(P_NICKNAME));
     695                                                                database.releaseWriteLock();
    581696                                                                dk = ns = ip = op = false;
    582697                                                                out.println("OK cleared");
     
    589704                                                        // Show status of a nickname
    590705                                                        out.print("OK ");
    591                                                         ttlpnt(out, database, Arg);
     706                                                        ttlpnt(out, Arg);
    592707                                                } else {
    593708                                                        nns(out);
  • apps/BOB/src/net/i2p/BOB/nickname.java

    rcb17fb8 r224ebb1  
    2222 * ...for any additional details and liscense questions.
    2323 */
    24 
    2524package net.i2p.BOB;
    2625
     
    3029 * @author sponge
    3130 */
    32 public class  nickname  {
    33 
    34         private Object[][] data;
    35         private int index = 0;
    36 
     31public class nickname {
     32
     33        private static final int maxWritersWaiting = 2;
     34        private volatile Object[][] data;
     35        private volatile int index, writersWaiting, readers;
     36        private volatile boolean writingInProgress;
    3737        /**
    3838         * make initial NULL object
     
    4040         */
    4141        public nickname() {
    42                 data = new Object[1][2];
     42                this.data = new Object[1][2];
     43                this.index = this.writersWaiting = this.readers = 0;
     44                this.writingInProgress = false;
     45        }
     46
     47        synchronized public void getReadLock() {
     48                while(writingInProgress | (writersWaiting >= maxWritersWaiting)) {
     49                        try {
     50                                wait();
     51                        } catch(InterruptedException ie) {
     52                        }
     53                        readers++;
     54                }
     55        }
     56
     57        synchronized public void releaseReadLock() {
     58                readers--;
     59                if((readers == 0) & (writersWaiting > 0)) {
     60                        notifyAll();
     61                }
     62        }
     63
     64        synchronized public void getWriteLock() {
     65                writersWaiting++;
     66                while((readers > 0) | writingInProgress) {
     67                        try {
     68                                wait();
     69                        } catch(InterruptedException ie) {
     70                        }
     71                }
     72                writersWaiting--;
     73                writingInProgress = true;
     74        }
     75
     76        synchronized public void releaseWriteLock() {
     77                writingInProgress = false;
     78                notifyAll();
    4379        }
    4480
     
    75111                olddata = new Object[index + 2][2];
    76112                // copy to olddata, skipping 'k'
    77                 for(i = 0      , l = 0; l < index; i++, l++) {
     113                for(i = 0          , l = 0; l < index; i++, l++) {
    78114                        if(i == k) {
    79115                                l++;
  • history.txt

    rcb17fb8 r224ebb1  
     12008-10-09 sponge
     2    * Update version to -3
     3    * BOB database threadlocking fixes
     4
    152008-10-08 sponge
    26    * Update version to -2
  • router/java/src/net/i2p/router/RouterVersion.java

    rcb17fb8 r224ebb1  
    1818    public final static String ID = "$Revision: 1.548 $ $Date: 2008-06-07 23:00:00 $";
    1919    public final static String VERSION = "0.6.4";
    20     public final static long BUILD = 2;
     20    public final static long BUILD = 3;
    2121    public static void main(String args[]) {
    2222        System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
Note: See TracChangeset for help on using the changeset viewer.