Author: xor
Date: 2008-11-04 12:13:55 +0000 (Tue, 04 Nov 2008)
New Revision: 23306

Modified:
   trunk/plugins/FMSPlugin/FMS.java
   trunk/plugins/FMSPlugin/FMSBoard.java
   trunk/plugins/FMSPlugin/FMSIdentityManager.java
   trunk/plugins/FMSPlugin/FMSMessage.java
   trunk/plugins/FMSPlugin/FMSMessageManager.java
   trunk/plugins/FMSPlugin/WoT/FMSIdentityManagerWoT.java
   trunk/plugins/FMSPlugin/WoT/FMSMessageManagerWoT.java
   trunk/plugins/FMSPlugin/WoT/FMSMessageWoT.java
Log:
Major refactoring: FMS now completely relies on db4o, no more hashtables / 
linkedlists - if db4o works well then FMS should scale well. I changed so much 
of the code that I cannot split into small commits, sorry.

Modified: trunk/plugins/FMSPlugin/FMS.java
===================================================================
--- trunk/plugins/FMSPlugin/FMS.java    2008-11-04 10:24:00 UTC (rev 23305)
+++ trunk/plugins/FMSPlugin/FMS.java    2008-11-04 12:13:55 UTC (rev 23306)
@@ -99,8 +99,11 @@
                Configuration cache_config = Db4o.newConfiguration();
                for(String f : FMSMessage.getIndexedFields())
                        
cache_config.objectClass(FMSMessage.class).objectField(f).indexed(true);
+               
cache_config.objectClass(FMSMessage.class).cascadeOnUpdate(true);
+               // TODO: decide about cascade on delete. 
                for(String f : FMSBoard.getIndexedFields())
                        
cache_config.objectClass(FMSBoard.class).objectField(f).indexed(true);
+               
                db_cache = Db4o.openFile(cache_config, "fms_cache.db4o");

                // while develop wipe cache on startup

Modified: trunk/plugins/FMSPlugin/FMSBoard.java
===================================================================
--- trunk/plugins/FMSPlugin/FMSBoard.java       2008-11-04 10:24:00 UTC (rev 
23305)
+++ trunk/plugins/FMSPlugin/FMSBoard.java       2008-11-04 12:13:55 UTC (rev 
23306)
@@ -3,55 +3,33 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package plugins.FMSPlugin;

-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.LinkedList;
-import java.util.ListIterator;
-import java.util.NoSuchElementException;

 import com.db4o.ObjectContainer;
 import com.db4o.ObjectSet;
 import com.db4o.query.Query;

 import freenet.keys.FreenetURI;
-import freenet.support.DoublyLinkedList;
 import freenet.support.IndexableUpdatableSortedLinkedListItem;
 import freenet.support.UpdatableSortedLinkedListItemImpl;
 import freenet.support.UpdatableSortedLinkedListKilledException;
 import freenet.support.UpdatableSortedLinkedListWithForeignIndex;
-import freenet.support.DoublyLinkedList.Item;

 /**
  * @author xor
  *
  */
-public class FMSBoard extends UpdatableSortedLinkedListItemImpl implements 
IndexableUpdatableSortedLinkedListItem {
-       
-       private ObjectContainer db;
+public class FMSBoard {

-       /**
-        * Contains all threads in this board, both as a Hashmap and as a 
linked list which is sorted by date.
-        * The hashmap is useful for checking whether a message was already 
stored.
-        * The linked list allows fast displaying of all messages.
-        */
-       private UpdatableSortedLinkedListWithForeignIndex mThreads = new 
UpdatableSortedLinkedListWithForeignIndex();
-       
-       /**
-        * Contains orphans for which even the parent thread did not exist. 
They are currently listed in the threads list and have to be removed
-        * from it if their thread is found.
-        */
-       private LinkedList<FMSMessage> mAbsoluteOrphans = new 
LinkedList<FMSMessage>(); 
+       private transient final ObjectContainer db;

-       private final FMSBoard self = this;
-       
-       private final FMSMessageManager mMessageManager;
-       
+       private transient final FMSBoard self = this;
+
+       private transient final FMSMessageManager mMessageManager;
+
        private final String mName;
-       
-       private String mDescription;
-       
+
        /**
         * Get a list of fields which the database should create an index on.
         */
@@ -59,65 +37,56 @@
                return new String[] {"mName"};
        }

-       public FMSBoard(FMSMessageManager newMessageManager, String newName, 
String newDescription) {
+       public FMSBoard(ObjectContainer myDB, FMSMessageManager 
newMessageManager, String newName) {
                if(newName==null || newName.length() == 0)
                        throw new IllegalArgumentException("Empty board name.");
-               
+
+               assert(myDB != null);
                assert(newMessageManager != null);
+
+               db = myDB;
                mMessageManager = newMessageManager;
-               // FIXME: Remove anything dangerous from name and description.
+               // FIXME: Validate name and description.
                mName = newName;
-               setDescription(newDescription);
+               
+               db.store(this);
+               db.commit();
        }

        /**
-        * @return the Description
+        * @return The name.
         */
-       public String getDescription() {
-               return mDescription;
-       }
-       
-       /**
-        * @param description The description to set.
-        */
-       public void setDescription(String newDescription) {
-               //FIXME: Remove anything dangerous from description.
-               mDescription = newDescription!=null ? newDescription : "";
-       }
-
-       /**
-        * @return The name
-        */
        public String getName() {
                return mName;
        }
-       
+
        /**
         * Called by the <code>FMSMessageManager</code> to add a just received 
message to the board.
         * The job for this function is to find the right place in the 
thread-tree for the new message and to move around older messages
         * if a parent message of them is received.
         */
-       public void addMessage(FMSMessage newMessage) throws 
UpdatableSortedLinkedListKilledException { 
-               if(newMessage.isThread()) {     /* The message is a thread */
-                       mThreads.add(newMessage);
-               }
-               else
+       public synchronized void addMessage(FMSMessage newMessage) throws 
UpdatableSortedLinkedListKilledException {    
+               db.store(newMessage);
+               db.commit();
+
+               if(!newMessage.isThread())
                {
                        FreenetURI parentURI = newMessage.getParentURI();
                        FMSMessage parentMessage = 
mMessageManager.get(parentURI); /* TODO: This allows crossposting. Figure out 
whether we need to handle it specially */
+                       FMSMessage parentThread = findParentThread(newMessage);
+
+                       if(parentThread != null)
+                               newMessage.setThread(parentThread);
+
                        if(parentMessage != null) {
-                               parentMessage.addChild(newMessage);
-                               db.store(parentMessage);
+                               newMessage.setParent(parentMessage);
                        } else { /* The message is an orphan */
-                               FMSMessage parentThread = 
mMessageManager.get(newMessage.getParentThreadURI());
                                if(parentThread != null) {
-                                       parentThread.addChild(newMessage);      
/* We found its parent thread so just stick it in there for now */
-                                       db.store(parentThread);
+                                       newMessage.setParent(parentThread);     
/* We found its parent thread so just stick it in there for now */
                                }
-                               else { /* The message is an absolute orphan */
-                                       mThreads.add(newMessage); /* TODO: 
Instead of hiding the message completely, we make it look like a thread. 
Reconsider this. */
-                                       mAbsoluteOrphans.add(newMessage);
-                                       
+                               else {
+                                        /* The message is an absolute orphan */
+
                                        /* 
                                         * FIXME: The MessageManager should try 
to download the parent message if it's poster has enough trust.
                                         * If it is programmed to do that, it 
will check its Hashtable whether the parent message already exists.
@@ -126,70 +95,84 @@
                                }
                        } 
                }
-               
-               db.commit();
-               
+
                linkOrphansToNewParent(newMessage);
        }
-       
-       private void linkOrphansToNewParent(FMSMessage newMessage) throws 
UpdatableSortedLinkedListKilledException {
+
+       private synchronized void linkOrphansToNewParent(FMSMessage newMessage) 
throws UpdatableSortedLinkedListKilledException {
                if(newMessage.isThread()) {
-                       for(FMSMessage o : mAbsoluteOrphans) {  /* Search in 
the orphans for messages which belong to this thread */
-                               
if(o.getParentThreadURI().equals(newMessage.getURI())) {
-                                       newMessage.addChild(o);
-                                       mAbsoluteOrphans.remove(o);
-                                       mThreads.remove(o);
-                               }
+                       Iterator<FMSMessage> absoluteOrphans = 
absoluteOrphanIterator(newMessage.getURI());
+                       while(absoluteOrphans.hasNext()){       /* Search in 
the absolute orphans for messages which belong to this thread  */
+                               FMSMessage orphan = absoluteOrphans.next();
+                               orphan.setParent(newMessage);
                        }
                }
                else {
-                       FMSMessage parentThread = 
(FMSMessage)mThreads.get(newMessage.getParentThreadURI());
+                       FMSMessage parentThread = newMessage.getThread();
                        if(parentThread != null) {      /* Search in its parent 
thread for its children */
-                               Iterator<FMSMessage> iter = 
parentThread.childrenIterator();
+                               Iterator<FMSMessage> iter = 
parentThread.childrenIterator(this);
                                while(iter.hasNext()) {
                                        FMSMessage parentThreadChild = 
iter.next();

                                        
if(parentThreadChild.getParentURI().equals(newMessage.getURI())) { /* We found 
its parent, yeah! */
-                                               iter.remove();  /* It's a child 
of the newMessage, not of the parentThread */
-                                               
newMessage.addChild(parentThreadChild);
+                                               
parentThreadChild.setParent(newMessage); /* It's a child of the newMessage, not 
of the parentThread */
                                        }
                                }
-                               db.store(parentThread);
-                       } else { /* The new message is an absolute orphan, find 
its children amongst the other absolute orphans */
-                               for(FMSMessage o : mAbsoluteOrphans) {
-                                       
if(o.getParentURI().equals(newMessage.getURI())) {
-                                               newMessage.addChild(o);
-                                               mAbsoluteOrphans.remove(o);
-                                       }
+                       }
+                       else { /* The new message is an absolute orphan, find 
its children amongst the other absolute orphans */
+                               Iterator<FMSMessage> absoluteOrphans = 
absoluteOrphanIterator(newMessage.getURI());
+                               while(absoluteOrphans.hasNext()){       /* 
Search in the orphans for messages which belong to this message  */
+                                       FMSMessage orphan = 
absoluteOrphans.next();
+                                       /*
+                                        * The following if() could be joined 
into the db4o query in absoluteOrphanIterator(). I did not do it because we 
could
+                                        * cache the list of absolute orphans 
locally. 
+                                        */
+                                       
if(orphan.getParentURI().equals(newMessage.getURI()))
+                                               orphan.setParent(newMessage);
                                }
                        }
                }
+       }
+       
+       protected synchronized FMSMessage findParentThread(FMSMessage m) {
+               Query q = db.query();
+               q.constrain(FMSMessage.class);
+               /* FIXME: I assume that db4o is configured to keep an URI index 
per board. We still have to ensure in FMS.java that it is configured to do so.
+                * If my second assumption - that the descend() statements are 
evaluated in the specified order - is true, then it might be faste because the
+                * URI index is smaller per board than the global URI index. */
+               q.descend("mBoards").constrain(mName); 
+               q.descend("mURI").constrain(m.getParentThreadURI());
+               ObjectSet<FMSMessage> parents = q.execute();

-               db.store(newMessage);
-               db.commit();
+               assert(parents.size() <= 1);
+               
+               return (parents.size() != 0 ? parents.next()  : null);
        }


        /**
-        * Get all messages in the board. The view is specified to the 
FMSOwnIdentity displaying it, therefore you have to pass one as parameter.
+        * Get all threads in the board. The view is specified to the 
FMSOwnIdentity displaying it, therefore you have to pass one as parameter.
         * @param identity The identity viewing the board.
         * @return An iterator of the message which the identity will see 
(based on its trust levels).
         */
        public synchronized Iterator<FMSMessage> threadIterator(final 
FMSOwnIdentity identity) {
                return new Iterator<FMSMessage>() {
                        private final FMSOwnIdentity mIdentity = identity;
-                       private final ObjectSet<FMSMessage> mMessages;
                        private final Iterator<FMSMessage> iter;
                        private FMSMessage next;

                        {
+                               /* FIXME: If db4o supports precompiled queries, 
this one should be stored precompiled.
+                                * Reason: We sort the threads by date.
+                                * Maybe we can just keep the Query-object and 
call q.execute() as many times as we like to?
+                                * Or somehow tell db4o to keep a per-board 
thread index which is sorted by Date? - This would be the best solution */
                                Query q = db.query();
                                q.constrain(FMSMessage.class);
                                q.descend("mBoards").constrain(mName); /* 
FIXME: mBoards is an array. Does constrain() check whether it contains the 
element mName? */
-                               q.descend("mParentURI").constrain(null);
-                               q.orderDescending();
-                               mMessages = q.execute();
-                               iter = mMessages.iterator();
+                               q.descend("mThread").constrain(null);
+                               q.descend("mDate").orderDescending();
+
+                               iter = q.execute().iterator();
                                next = iter.hasNext() ? iter.next() : null;
                        }

@@ -214,19 +197,38 @@

                };
        }
-
-       /* (non-Javadoc)
-        * @see 
freenet.support.IndexableUpdatableSortedLinkedListItem#indexValue()
+       
+       /**
+        * Get an iterator over messages for which the parent thread with the 
given URI was not known. 
         */
-       public Object indexValue() {
-               return mName;
-       }
+       public synchronized Iterator<FMSMessage> absoluteOrphanIterator(final 
FreenetURI thread) {
+               return new Iterator<FMSMessage>() {
+                       private final ObjectSet<FMSMessage> mMessages;
+                       private final Iterator<FMSMessage> iter;

-       /* (non-Javadoc)
-        * @see java.lang.Comparable#compareTo(java.lang.Object)
-        */
-       public int compareTo(Object o) {
-               FMSBoard b = (FMSBoard)o;
-               return mName.compareTo(b.getName());
+                       {
+                               /* FIXME: This query should be accelerated. The 
amount of absolute orphans is very small usually, so we should configure db4o
+                                * to keep a separate list of those. */
+                               Query q = db.query();
+                               q.constrain(FMSMessage.class);
+                               q.descend("mBoards").constrain(mName); /* 
FIXME: mBoards is an array. Does constrain() check whether it contains the 
element mName? */
+                               q.descend("mThreadURI").constrain(thread);
+                               q.descend("mThread").constrain(null);
+                               mMessages = q.execute();
+                               iter = mMessages.iterator();
+                       }
+
+                       public boolean hasNext() {
+                               return mMessages.hasNext();
+                       }
+
+                       public FMSMessage next() {
+                               return mMessages.next();
+                       }
+
+                       public void remove() {
+                               throw new UnsupportedOperationException();
+                       }
+               };
        }
 }

Modified: trunk/plugins/FMSPlugin/FMSIdentityManager.java
===================================================================
--- trunk/plugins/FMSPlugin/FMSIdentityManager.java     2008-11-04 10:24:00 UTC 
(rev 23305)
+++ trunk/plugins/FMSPlugin/FMSIdentityManager.java     2008-11-04 12:13:55 UTC 
(rev 23306)
@@ -3,21 +3,51 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package plugins.FMSPlugin;

+import java.util.Iterator;
 import java.util.Set;

+import com.db4o.ObjectContainer;
+import com.db4o.ObjectSet;
+
+import plugins.FMSPlugin.WoT.FMSIdentityWoT;
+import plugins.FMSPlugin.WoT.FMSOwnIdentityWoT;
+
 import freenet.support.Executor;

 /**
  * @author saces, xor
- *
+ * 
  */
-public abstract class FMSIdentityManager {
+public abstract class FMSIdentityManager implements Iterable<FMSIdentity> {

-       private final Executor mExecutor;
+       protected final ObjectContainer db;

-       public FMSIdentityManager(Executor newExecutor) {
+       protected final Executor mExecutor;
+
+       public FMSIdentityManager(ObjectContainer myDB, Executor newExecutor) {
+               db = myDB;
                mExecutor = newExecutor;
+       }

+       public synchronized Iterator<FMSIdentity> iterator() {
+               ObjectSet<FMSIdentity> ids = db.query(FMSIdentity.class);
+               return ids.iterator();
        }

+       public synchronized Iterator<FMSOwnIdentity> ownIdentityIterator() {
+               ObjectSet<FMSOwnIdentity> oids = db.query(FMSOwnIdentity.class);
+               return oids.iterator();
+       }
+
+       public synchronized boolean anyOwnIdentityWantsMessagesFrom(FMSIdentity 
identity) {
+               Iterator<FMSOwnIdentity> iter = ownIdentityIterator();
+
+               while (iter.hasNext()) {
+                       FMSOwnIdentity oid = iter.next();
+                       if (oid.wantsMessagesFrom(identity))
+                               return true;
+               }
+
+               return false;
+       }
 }

Modified: trunk/plugins/FMSPlugin/FMSMessage.java
===================================================================
--- trunk/plugins/FMSPlugin/FMSMessage.java     2008-11-04 10:24:00 UTC (rev 
23305)
+++ trunk/plugins/FMSPlugin/FMSMessage.java     2008-11-04 12:13:55 UTC (rev 
23306)
@@ -5,10 +5,14 @@

 import java.util.Arrays;
 import java.util.Date;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;

+import com.db4o.ObjectContainer;
+import com.db4o.query.Query;
+
 import freenet.keys.FreenetURI;
 import freenet.support.IndexableUpdatableSortedLinkedListItem;
 import freenet.support.UpdatableSortedLinkedList;
@@ -19,8 +23,10 @@
  * @author saces, xor
  *
  */
-public abstract class FMSMessage extends UpdatableSortedLinkedListItemImpl 
implements IndexableUpdatableSortedLinkedListItem {
+public abstract class FMSMessage {

+       protected ObjectContainer db;
+       
        /**
         * The URI of this message.
         */
@@ -63,18 +69,23 @@
        private final FreenetURI[] mAttachments;

        /**
-        * The replies to this messages.
+        * The thread to which this message is a reply.
         */
-       private UpdatableSortedLinkedList mChildren = new 
UpdatableSortedLinkedList();
+       private FMSMessage mThread = null;

        /**
+        * The message to which this message is a reply.
+        */
+       private FMSMessage mParent = null;
+       
+       /**
         * Get a list of fields which the database should create an index on.
         */
        public static String[] getIndexedFields() {
-               return new String[] { "mURI", "mBoards" };
+               return new String[] { "mURI", "mThreadURI", "mBoards"};
        }

-       public FMSMessage(FreenetURI newURI, FreenetURI newThreadURI, 
FreenetURI newParentURI, Set<FMSBoard> newBoards, FMSIdentity newAuthor, String 
newTitle, Date newDate, String newText, List<FreenetURI> newAttachments) {
+       public FMSMessage(ObjectContainer db, FreenetURI newURI, FreenetURI 
newThreadURI, FreenetURI newParentURI, Set<FMSBoard> newBoards, FMSIdentity 
newAuthor, String newTitle, Date newDate, String newText, List<FreenetURI> 
newAttachments) {
                if (newURI == null || newBoards == null || newAuthor == null)
                        throw new IllegalArgumentException();

@@ -167,40 +178,64 @@
                return mAttachments;
        }

-       public synchronized void addChild(FMSMessage newChild) throws 
UpdatableSortedLinkedListKilledException {
-               if(mChildren.contains(newChild)) {
-                       assert(false); // TODO: check whether this should be 
allowed to happen.
-                       return;
-               }
-               
-               mChildren.add(newChild);
+       public synchronized FMSMessage getThread() {
+               return mThread;
        }

-       public synchronized Iterator<FMSMessage> childrenIterator() {
-               return mChildren.iterator();
+       public synchronized void setThread(FMSMessage newParentThread) {
+               assert(mThread == null);
+               assert(mThreadURI == null);
+               mThread = newParentThread;
+               db.store(this);
+               db.commit();
        }

-       /**
-        * Compare by Date to the other FMSMessage.
-        * @param o An object of type FMSMessage 
-        */
-       public int compareTo(Object o) {
-               FMSMessage m = (FMSMessage)o;
-               return mDate.compareTo(m.getDate());
+       public synchronized FMSMessage getParent() {
+               return mParent;
        }
+
+       public synchronized void setParent(FMSMessage newParent) throws 
UpdatableSortedLinkedListKilledException {
+               /* TODO: assert(newParent contains at least one board which 
mBoards contains) */
+               mParent = newParent;
+               db.store(this);
+               db.commit();
+       }

-       /**
-        * Get the index value for IndexableUpdatableSortedLinkedListItem.
-        */
-       public Object indexValue() {
-               return mURI;
+       public synchronized Iterator<FMSMessage> childrenIterator(final 
FMSBoard board) {
+               return new Iterator<FMSMessage>() {
+                       private Iterator<FMSMessage> iter;
+                       
+                       {
+                               /* TODO: Accelerate this query: configure db4o 
to keep a per-message date-sorted index of children.
+                                * - Not very important for now since threads 
are usually small. */
+                               Query q = db.query();
+                               q.constrain(FMSMessage.class);
+                               q.descend("mBoard").constrain(board.getName());
+                               q.descend("mParent").constrain(this);
+                               q.descend("mDate").orderDescending();
+                               
+                               iter = q.execute().iterator();
+                       }
+
+                       public boolean hasNext() {
+                               return iter.hasNext();
+                       }
+
+                       public FMSMessage next() {
+                               return iter.next();
+                       }
+
+                       public void remove() {
+                               throw new UnsupportedOperationException("Use 
child.setParent(null) instead.");
+                       }
+               };
        }

        /**
         * Checks whether the title of the message is valid. Validity 
conditions:
         * - ...
         */
-       static boolean isTitleValid(String title) {
+       static public boolean isTitleValid(String title) {
                // FIXME: Implement.
                return true;
        }
@@ -209,7 +244,7 @@
         * Checks whether the text of the message is valid. Validity conditions:
         * - ...
         */
-       static boolean isTextValid(String text) {
+       static public boolean isTextValid(String text) {
                // FIXME: Implement.
                return true;
        }
@@ -218,7 +253,7 @@
         * Makes the passed title valid in means of <code>isTitleValid()</code>
         * @see isTitleValid
         */
-       static String makeTitleValid(String title) {
+       static public String makeTitleValid(String title) {
                // FIXME: Implement.
                return title;
        }
@@ -227,7 +262,7 @@
         * Makes the passed text valid in means of <code>isTextValid()</code>
         * @see isTextValid
         */
-       static String makeTextValid(String text) {
+       static public String makeTextValid(String text) {
                // FIXME: Implement.
                return text;
        }

Modified: trunk/plugins/FMSPlugin/FMSMessageManager.java
===================================================================
--- trunk/plugins/FMSPlugin/FMSMessageManager.java      2008-11-04 10:24:00 UTC 
(rev 23305)
+++ trunk/plugins/FMSPlugin/FMSMessageManager.java      2008-11-04 12:13:55 UTC 
(rev 23306)
@@ -17,43 +17,59 @@
  *
  */
 public abstract class FMSMessageManager {
-       
+
        protected ObjectContainer db;
-       
-       /**
-        * Contains all boards which where found in a message. References to 
all messages of a board are stored in
-        * the board. Adding a newly downloaded message therefore is done by 
searching its board and calling 
-        * <code>addMessage()</code> on that board. Further, the message is 
also added to mMessages, see below.
-        */
-       protected UpdatableSortedLinkedListWithForeignIndex mBoards = new 
UpdatableSortedLinkedListWithForeignIndex();
-       
+
+       protected FMSIdentityManager mIdentityManager;
+
+       public FMSMessageManager(ObjectContainer myDB, FMSIdentityManager 
myIdentityManager) {
+               assert(myDB != null);
+               assert(myIdentityManager != null);
+
+               db = myDB;
+               mIdentityManager = myIdentityManager;
+       }
+
        public synchronized FMSMessage get(FreenetURI uri) {
                Query query = db.query();
                query.constrain(FMSMessage.class);
                query.descend("mURI").constrain(uri);
                ObjectSet<FMSMessage> result = query.execute();
-               
+
+               assert(result.size() <= 1);
+
                return (result.size() == 0) ? null : result.next();
        }
-       
+
        public synchronized FMSBoard getBoardByName(String name) {
-               return (FMSBoard)mBoards.get(name);
+               Query query = db.query();
+               query.constrain(FMSBoard.class);
+               query.descend("mName").constrain(name);
+               ObjectSet<FMSBoard> result = query.execute();
+
+               assert(result.size() <= 1);
+
+               return (result.size() == 0) ? null : result.next();
        }
-       
+
        /**
-        * Get an iterator of boards which the identity could subscribe to.
-        * @param identity
-        * @return
+        * Get an iterator of all boards.
         */
-       public synchronized Iterator<FMSBoard> boardIterator(FMSOwnIdentity 
identity) {
-               return (Iterator<FMSBoard>)mBoards.iterator();
+       public synchronized Iterator<FMSBoard> boardIterator() {
+               /* FIXME: Accelerate this query. db4o should be configured to 
keep an alphabetic index of boards */
+               Query query = db.query();
+               query.constrain(FMSBoard.class);
+               query.descend("mName").orderDescending();
+
+               ObjectSet<FMSBoard> result = query.execute();
+
+               return result.iterator();
        }
-       

        /**
         * Returns true if the message was not downloaded yet and any of the 
FMSOwnIdentity wants the message.
-        * @param uri
-        * @return
         */
-       protected abstract boolean shouldDownloadMessage(FreenetURI uri);
+       protected synchronized boolean shouldDownloadMessage(FreenetURI uri, 
FMSIdentity author) {
+               return (get(uri) != null) || 
mIdentityManager.anyOwnIdentityWantsMessagesFrom(author);
+       }
 }

Modified: trunk/plugins/FMSPlugin/WoT/FMSIdentityManagerWoT.java
===================================================================
--- trunk/plugins/FMSPlugin/WoT/FMSIdentityManagerWoT.java      2008-11-04 
10:24:00 UTC (rev 23305)
+++ trunk/plugins/FMSPlugin/WoT/FMSIdentityManagerWoT.java      2008-11-04 
12:13:55 UTC (rev 23306)
@@ -6,9 +6,13 @@
 import java.util.Collection;
 import java.util.Iterator;

+import com.db4o.ObjectContainer;
+import com.db4o.ObjectSet;
+
 import freenet.support.Executor;
 import plugins.FMSPlugin.FMSIdentity;
 import plugins.FMSPlugin.FMSIdentityManager;
+import plugins.FMSPlugin.FMSOwnIdentity;

 import plugins.WoT.WoT;
 import plugins.WoT.Identity;
@@ -27,17 +31,8 @@
        /**
         * @param executor
         */
-       public FMSIdentityManagerWoT(Executor executor, WoT newWoT) {
-               super(executor);
+       public FMSIdentityManagerWoT(ObjectContainer myDB, Executor executor, 
WoT newWoT) {
+               super(myDB, executor);
                mWoT = newWoT;
        }
-
-       public Iterator<FMSOwnIdentityWoT> ownIdentityIterator() {
-               return null;
-       }
-
-       public Iterator<FMSIdentityWoT> iterator() {
-               // TODO Auto-generated method stub
-               return null;
-       }
 }

Modified: trunk/plugins/FMSPlugin/WoT/FMSMessageManagerWoT.java
===================================================================
--- trunk/plugins/FMSPlugin/WoT/FMSMessageManagerWoT.java       2008-11-04 
10:24:00 UTC (rev 23305)
+++ trunk/plugins/FMSPlugin/WoT/FMSMessageManagerWoT.java       2008-11-04 
12:13:55 UTC (rev 23306)
@@ -30,41 +30,36 @@

 public class FMSMessageManagerWoT extends FMSMessageManager {

-       protected synchronized boolean shouldDownloadMessage(FreenetURI uri) {
-               Query query = db.query();
-               query.constrain(FMSMessage.class);
-               query.descend("mURI").constrain(uri);
-               ObjectSet<FMSMessage> result = query.execute();
-               
-               if(result.size() > 1) { /* Duplicate messages */
-                       assert(false);
-                       /* FIXME: Add logging!*/
-                       deleteMessage(uri);
-                       return true;
-               }
-               
-               return (result.size() == 0);
+       protected FMSIdentityManagerWoT mIdentityManager;
+
+       public FMSMessageManagerWoT(ObjectContainer myDB, FMSIdentityManagerWoT 
myIdentityManager) {
+               super(myDB, myIdentityManager);
+               mIdentityManager = myIdentityManager;
        }
-       
+
        protected synchronized void deleteMessage(FreenetURI uri) throws 
NoSuchElementException {
                /* FIXME: implement */
        }
-       
+
        private synchronized void onMessageReceived(String newMessageData) 
throws UpdatableSortedLinkedListKilledException { 
-               FMSMessageWoT newMessage = new FMSMessageWoT(null, null, null, 
null, null, null, null, null, null);
+               FMSMessageWoT newMessage = new FMSMessageWoT(db, null, null, 
null, null, null, null, null, null, null);
                String boardName = "";
-               String boardDescription = "";
-               FMSBoard board = getBoardByName(boardName);
-               if(board == null) {
-                       board = new FMSBoard(this, boardName, boardDescription);
-                       mBoards.add(board);
+               /* FIXME: Store the description in FMSOwnIdentity. We cannot 
store in FMSBoard because we want to allow per-identity customization */
+
+               String[] boardNames = new String[0];
+               FMSBoard[] boards = new FMSBoard[boardNames.length];
+                                                   
+               for(int idx = 0; idx < boards.length; ++idx) {
+                       FMSBoard board = getBoardByName(boardNames[idx]);
+                       
+                       if(board == null)
+                               board = new FMSBoard(db, this, boardName);
+                       
+                       boards[idx] = board;
                }

-               db.store(newMessage);
-               db.commit();
-               
-               board.addMessage(newMessage);
-               db.store(board);
-               db.commit();
+               for(FMSBoard b : boards) {
+                       b.addMessage(newMessage);
+               }
        }
 }

Modified: trunk/plugins/FMSPlugin/WoT/FMSMessageWoT.java
===================================================================
--- trunk/plugins/FMSPlugin/WoT/FMSMessageWoT.java      2008-11-04 10:24:00 UTC 
(rev 23305)
+++ trunk/plugins/FMSPlugin/WoT/FMSMessageWoT.java      2008-11-04 12:13:55 UTC 
(rev 23306)
@@ -9,6 +9,8 @@
 import java.util.Set;
 import java.util.SortedSet;

+import com.db4o.ObjectContainer;
+
 import freenet.keys.FreenetURI;
 import freenet.support.DoublyLinkedList;
 import plugins.FMSPlugin.FMSBoard;
@@ -21,9 +23,9 @@
  */
 public class FMSMessageWoT extends FMSMessage {

-       public FMSMessageWoT(FreenetURI newURI, FreenetURI newThreadURI, 
FreenetURI newParentURI, Set<FMSBoard> newBoards, FMSIdentity newAuthor,
+       public FMSMessageWoT(ObjectContainer myDB, FreenetURI newURI, 
FreenetURI newThreadURI, FreenetURI newParentURI, Set<FMSBoard> newBoards, 
FMSIdentity newAuthor,
                        String newTitle, Date newDate, String newText, 
List<FreenetURI> newAttachments) {
-               super(newURI, newThreadURI, newParentURI, newBoards, newAuthor, 
newTitle, newDate, newText, newAttachments);
+               super(myDB, newURI, newThreadURI, newParentURI, newBoards, 
newAuthor, newTitle, newDate, newText, newAttachments);
                // TODO Auto-generated constructor stub
        }



Reply via email to