mahout-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sro...@apache.org
Subject svn commit: r1001298 - in /mahout/trunk/core/src: main/java/org/apache/mahout/cf/taste/impl/common/ main/java/org/apache/mahout/cf/taste/impl/model/file/ main/java/org/apache/mahout/cf/taste/impl/recommender/ main/java/org/apache/mahout/cf/taste/impl/r...
Date Sat, 25 Sep 2010 18:59:52 GMT
Author: srowen
Date: Sat Sep 25 18:59:51 2010
New Revision: 1001298

URL: http://svn.apache.org/viewvc?rev=1001298&view=rev
Log:
Simplify, standardize and in some cases fix much 'reload' logic, by having constructors reload
upfront

Added:
    mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/file/FileItemItemSimilarityIterable.java
    mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/file/FileItemItemSimilarityIterator.java
Modified:
    mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/RefreshHelper.java
    mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/file/FileDataModel.java
    mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/file/FileIDMigrator.java
    mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/ItemAverageRecommender.java
    mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/ItemUserAverageRecommender.java
    mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/TreeClusteringRecommender.java
    mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/TreeClusteringRecommender2.java
    mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/slopeone/file/FileDiffStorage.java
    mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/file/FileItemSimilarity.java
    mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/similarity/file/FileItemSimilarityTest.java

Modified: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/RefreshHelper.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/RefreshHelper.java?rev=1001298&r1=1001297&r2=1001298&view=diff
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/RefreshHelper.java
(original)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/RefreshHelper.java
Sat Sep 25 18:59:51 2010
@@ -71,8 +71,7 @@ public final class RefreshHelper impleme
    */
   @Override
   public void refresh(Collection<Refreshable> alreadyRefreshed) {
-    if (!refreshLock.isLocked()) {
-      refreshLock.lock();
+    if (refreshLock.tryLock()) {
       try {
         alreadyRefreshed = buildRefreshed(alreadyRefreshed);
         for (Refreshable dependency : dependencies) {

Modified: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/file/FileDataModel.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/file/FileDataModel.java?rev=1001298&r1=1001297&r2=1001298&view=diff
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/file/FileDataModel.java
(original)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/file/FileDataModel.java
Sat Sep 25 18:59:51 2010
@@ -125,7 +125,6 @@ public class FileDataModel extends Abstr
   private final char delimiter;
   private final Pattern delimiterPattern;
   private final boolean hasPrefValues;
-  private boolean loaded;
   private DataModel delegate;
   private final ReentrantLock reloadLock;
   private final boolean transpose;
@@ -186,6 +185,8 @@ public class FileDataModel extends Abstr
     this.reloadLock = new ReentrantLock();
     this.transpose = transpose;
     this.minReloadIntervalMS = minReloadIntervalMS;
+
+    reload();
   }
 
   public File getDataFile() {
@@ -197,11 +198,9 @@ public class FileDataModel extends Abstr
   }
 
   protected void reload() {
-    if (!reloadLock.isLocked()) {
-      reloadLock.lock();
+    if (reloadLock.tryLock()) {
       try {
         delegate = buildModel();
-        loaded = true;
       } catch (IOException ioe) {
         log.warn("Exception while reloading", ioe);
       } finally {
@@ -598,11 +597,6 @@ public class FileDataModel extends Abstr
       itemTimestamps.remove(itemID);
     }
   }
-  private void checkLoaded() {
-    if (!loaded) {
-      reload();
-    }
-  }
 
   /**
    * Subclasses may wish to override this if ID values in the file are not numeric. This
provides a hook by
@@ -632,61 +626,51 @@ public class FileDataModel extends Abstr
 
   @Override
   public LongPrimitiveIterator getUserIDs() throws TasteException {
-    checkLoaded();
     return delegate.getUserIDs();
   }
 
   @Override
   public PreferenceArray getPreferencesFromUser(long userID) throws TasteException {
-    checkLoaded();
     return delegate.getPreferencesFromUser(userID);
   }
 
   @Override
   public FastIDSet getItemIDsFromUser(long userID) throws TasteException {
-    checkLoaded();
     return delegate.getItemIDsFromUser(userID);
   }
 
   @Override
   public LongPrimitiveIterator getItemIDs() throws TasteException {
-    checkLoaded();
     return delegate.getItemIDs();
   }
 
   @Override
   public PreferenceArray getPreferencesForItem(long itemID) throws TasteException {
-    checkLoaded();
     return delegate.getPreferencesForItem(itemID);
   }
 
   @Override
   public Float getPreferenceValue(long userID, long itemID) throws TasteException {
-    checkLoaded();
     return delegate.getPreferenceValue(userID, itemID);
   }
 
   @Override
   public Long getPreferenceTime(long userID, long itemID) throws TasteException {
-    checkLoaded();
     return delegate.getPreferenceTime(userID, itemID);
   }
 
   @Override
   public int getNumItems() throws TasteException {
-    checkLoaded();
     return delegate.getNumItems();
   }
 
   @Override
   public int getNumUsers() throws TasteException {
-    checkLoaded();
     return delegate.getNumUsers();
   }
 
   @Override
   public int getNumUsersWithPreferenceFor(long... itemIDs) throws TasteException {
-    checkLoaded();
     return delegate.getNumUsersWithPreferenceFor(itemIDs);
   }
 
@@ -698,14 +682,12 @@ public class FileDataModel extends Abstr
    */
   @Override
   public void setPreference(long userID, long itemID, float value) throws TasteException
{
-    checkLoaded();
     delegate.setPreference(userID, itemID, value);
   }
 
   /** See the warning at {@link #setPreference(long, long, float)}. */
   @Override
   public void removePreference(long userID, long itemID) throws TasteException {
-    checkLoaded();
     delegate.removePreference(userID, itemID);
   }
 
@@ -720,19 +702,16 @@ public class FileDataModel extends Abstr
 
   @Override
   public boolean hasPreferenceValues() {
-    checkLoaded();
     return delegate.hasPreferenceValues();
   }
 
   @Override
   public float getMaxPreference() {
-    checkLoaded();
     return delegate.getMaxPreference();
   }
 
   @Override
   public float getMinPreference() {
-    checkLoaded();    
     return delegate.getMinPreference();
   }
 

Modified: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/file/FileIDMigrator.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/file/FileIDMigrator.java?rev=1001298&r1=1001297&r2=1001298&view=diff
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/file/FileIDMigrator.java
(original)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/file/FileIDMigrator.java
Sat Sep 25 18:59:51 2010
@@ -46,11 +46,10 @@ public class FileIDMigrator extends Abst
   public static final long DEFAULT_MIN_RELOAD_INTERVAL_MS = 60 * 1000L; // 1 minute?
 
   private final File dataFile;
-  private final FastByIDMap<String> longToString;
+  private FastByIDMap<String> longToString;
   private final ReentrantLock reloadLock;
 
   private long lastModified;
-  private boolean loaded;
   private long minReloadIntervalMS;
 
   private static final Logger log = LoggerFactory.getLogger(FileIDMigrator.class);
@@ -60,7 +59,6 @@ public class FileIDMigrator extends Abst
   }
 
   public FileIDMigrator(File dataFile, long minReloadIntervalMS) throws FileNotFoundException
{
-    super();
     longToString = new FastByIDMap<String>(100);
     if (dataFile == null) {
       throw new IllegalArgumentException("dataFile is null");
@@ -74,30 +72,20 @@ public class FileIDMigrator extends Abst
     this.dataFile = dataFile;
     this.reloadLock = new ReentrantLock();
     this.lastModified = dataFile.lastModified();
-    this.loaded = false;
     this.minReloadIntervalMS = minReloadIntervalMS;
+
+    reload();
   }
 
   @Override
   public String toStringID(long longID) {
-    if (!loaded) {
-      reload();
-    }
-    synchronized (longToString) {
-      return longToString.get(longID);
-    }
+    return longToString.get(longID);
   }
 
   private void reload() {
-    if (!reloadLock.isLocked()) {
-      reloadLock.lock();
+    if (reloadLock.tryLock()) {
       try {
-        longToString.clear();
-        for (String line : new FileLineIterable(dataFile)) {
-          longToString.put(toLongID(line), line);
-        }
-        lastModified = dataFile.lastModified();
-        loaded = true;
+        longToString = buildMapping();
       } catch (IOException ioe) {
         throw new IllegalStateException(ioe);
       } finally {
@@ -106,9 +94,18 @@ public class FileIDMigrator extends Abst
     }
   }
 
+  private FastByIDMap<String> buildMapping() throws IOException {
+    FastByIDMap<String> mapping = new FastByIDMap<String>();
+    for (String line : new FileLineIterable(dataFile)) {
+      mapping.put(toLongID(line), line);
+    }
+    lastModified = dataFile.lastModified();
+    return mapping;
+  }
+
   @Override
   public void refresh(Collection<Refreshable> alreadyRefreshed) {
-    if (!loaded || dataFile.lastModified() > lastModified + minReloadIntervalMS) {
+    if (dataFile.lastModified() > lastModified + minReloadIntervalMS) {
       log.debug("File has changed; reloading...");
       reload();
     }

Modified: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/ItemAverageRecommender.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/ItemAverageRecommender.java?rev=1001298&r1=1001297&r2=1001298&view=diff
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/ItemAverageRecommender.java
(original)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/ItemAverageRecommender.java
Sat Sep 25 18:59:51 2010
@@ -51,11 +51,10 @@ public final class ItemAverageRecommende
   private static final Logger log = LoggerFactory.getLogger(ItemAverageRecommender.class);
   
   private final FastByIDMap<RunningAverage> itemAverages;
-  private boolean averagesBuilt;
   private final ReadWriteLock buildAveragesLock;
   private final RefreshHelper refreshHelper;
   
-  public ItemAverageRecommender(DataModel dataModel) {
+  public ItemAverageRecommender(DataModel dataModel) throws TasteException {
     super(dataModel);
     this.itemAverages = new FastByIDMap<RunningAverage>();
     this.buildAveragesLock = new ReentrantReadWriteLock();
@@ -67,6 +66,7 @@ public final class ItemAverageRecommende
       }
     });
     refreshHelper.addDependency(dataModel);
+    buildAverageDiffs();
   }
   
   @Override
@@ -75,8 +75,7 @@ public final class ItemAverageRecommende
       throw new IllegalArgumentException("howMany must be at least 1");
     }
     log.debug("Recommending items for user ID '{}'", userID);
-    checkAverageDiffsBuilt();
-    
+
     FastIDSet possibleItemIDs = getAllOtherItems(userID);
     
     TopItems.Estimator<Long> estimator = new Estimator();
@@ -95,7 +94,6 @@ public final class ItemAverageRecommende
     if (actualPref != null) {
       return actualPref;
     }
-    checkAverageDiffsBuilt();
     return doEstimatePreference(itemID);
   }
   
@@ -109,12 +107,6 @@ public final class ItemAverageRecommende
     }
   }
   
-  private void checkAverageDiffsBuilt() throws TasteException {
-    if (!averagesBuilt) {
-      buildAverageDiffs();
-    }
-  }
-  
   private void buildAverageDiffs() throws TasteException {
     try {
       buildAveragesLock.writeLock().lock();
@@ -133,7 +125,6 @@ public final class ItemAverageRecommende
           average.addDatum(prefs.getValue(i));
         }
       }
-      averagesBuilt = true;
     } finally {
       buildAveragesLock.writeLock().unlock();
     }

Modified: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/ItemUserAverageRecommender.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/ItemUserAverageRecommender.java?rev=1001298&r1=1001297&r2=1001298&view=diff
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/ItemUserAverageRecommender.java
(original)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/ItemUserAverageRecommender.java
Sat Sep 25 18:59:51 2010
@@ -54,11 +54,10 @@ public final class ItemUserAverageRecomm
   private final FastByIDMap<RunningAverage> itemAverages;
   private final FastByIDMap<RunningAverage> userAverages;
   private final RunningAverage overallAveragePrefValue;
-  private boolean averagesBuilt;
   private final ReadWriteLock buildAveragesLock;
   private final RefreshHelper refreshHelper;
   
-  public ItemUserAverageRecommender(DataModel dataModel) {
+  public ItemUserAverageRecommender(DataModel dataModel) throws TasteException {
     super(dataModel);
     this.itemAverages = new FastByIDMap<RunningAverage>();
     this.userAverages = new FastByIDMap<RunningAverage>();
@@ -72,6 +71,7 @@ public final class ItemUserAverageRecomm
       }
     });
     refreshHelper.addDependency(dataModel);
+    buildAverageDiffs();
   }
   
   @Override
@@ -80,8 +80,7 @@ public final class ItemUserAverageRecomm
       throw new IllegalArgumentException("howMany must be at least 1");
     }
     log.debug("Recommending items for user ID '{}'", userID);
-    checkAverageDiffsBuilt();
-    
+
     FastIDSet possibleItemIDs = getAllOtherItems(userID);
     
     TopItems.Estimator<Long> estimator = new Estimator(userID);
@@ -100,7 +99,6 @@ public final class ItemUserAverageRecomm
     if (actualPref != null) {
       return actualPref;
     }
-    checkAverageDiffsBuilt();
     return doEstimatePreference(userID, itemID);
   }
   
@@ -121,13 +119,7 @@ public final class ItemUserAverageRecomm
       buildAveragesLock.readLock().unlock();
     }
   }
-  
-  private void checkAverageDiffsBuilt() throws TasteException {
-    if (!averagesBuilt) {
-      buildAverageDiffs();
-    }
-  }
-  
+
   private void buildAverageDiffs() throws TasteException {
     try {
       buildAveragesLock.writeLock().lock();
@@ -145,7 +137,6 @@ public final class ItemUserAverageRecomm
           overallAveragePrefValue.addDatum(value);
         }
       }
-      averagesBuilt = true;
     } finally {
       buildAveragesLock.writeLock().unlock();
     }

Modified: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/TreeClusteringRecommender.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/TreeClusteringRecommender.java?rev=1001298&r1=1001297&r2=1001298&view=diff
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/TreeClusteringRecommender.java
(original)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/TreeClusteringRecommender.java
Sat Sep 25 18:59:51 2010
@@ -23,7 +23,6 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Random;
 import java.util.concurrent.Callable;
-import java.util.concurrent.locks.ReentrantLock;
 
 import org.apache.mahout.cf.taste.common.Refreshable;
 import org.apache.mahout.cf.taste.common.TasteException;
@@ -74,8 +73,6 @@ public final class TreeClusteringRecomme
   private FastByIDMap<List<RecommendedItem>> topRecsByUserID;
   private FastIDSet[] allClusters;
   private FastByIDMap<FastIDSet> clustersByUserID;
-  private boolean clustersBuilt;
-  private final ReentrantLock buildClustersLock;
   private final RefreshHelper refreshHelper;
   
   /**
@@ -88,7 +85,8 @@ public final class TreeClusteringRecomme
    * @throws IllegalArgumentException
    *           if arguments are <code>null</code>, or <code>numClusters</code>
is less than 2
    */
-  public TreeClusteringRecommender(DataModel dataModel, ClusterSimilarity clusterSimilarity,
int numClusters) {
+  public TreeClusteringRecommender(DataModel dataModel, ClusterSimilarity clusterSimilarity,
int numClusters)
+    throws TasteException {
     this(dataModel, clusterSimilarity, numClusters, 1.0);
   }
   
@@ -109,7 +107,7 @@ public final class TreeClusteringRecomme
   public TreeClusteringRecommender(DataModel dataModel,
                                    ClusterSimilarity clusterSimilarity,
                                    int numClusters,
-                                   double samplingRate) {
+                                   double samplingRate) throws TasteException {
     super(dataModel);
     if (clusterSimilarity == null) {
       throw new IllegalArgumentException("clusterSimilarity is null");
@@ -125,7 +123,6 @@ public final class TreeClusteringRecomme
     this.clusteringThreshold = Double.NaN;
     this.clusteringByThreshold = false;
     this.samplingRate = samplingRate;
-    this.buildClustersLock = new ReentrantLock();
     this.refreshHelper = new RefreshHelper(new Callable<Object>() {
       @Override
       public Object call() throws TasteException {
@@ -135,6 +132,7 @@ public final class TreeClusteringRecomme
     });
     refreshHelper.addDependency(dataModel);
     refreshHelper.addDependency(clusterSimilarity);
+    buildClusters();
   }
   
   /**
@@ -150,7 +148,7 @@ public final class TreeClusteringRecomme
    */
   public TreeClusteringRecommender(DataModel dataModel,
                                    ClusterSimilarity clusterSimilarity,
-                                   double clusteringThreshold) {
+                                   double clusteringThreshold) throws TasteException {
     this(dataModel, clusterSimilarity, clusteringThreshold, 1.0);
   }
   
@@ -172,7 +170,7 @@ public final class TreeClusteringRecomme
   public TreeClusteringRecommender(DataModel dataModel,
                                    ClusterSimilarity clusterSimilarity,
                                    double clusteringThreshold,
-                                   double samplingRate) {
+                                   double samplingRate) throws TasteException {
     super(dataModel);
     if (clusterSimilarity == null) {
       throw new IllegalArgumentException("clusterSimilarity is null");
@@ -188,7 +186,6 @@ public final class TreeClusteringRecomme
     this.clusteringThreshold = clusteringThreshold;
     this.clusteringByThreshold = true;
     this.samplingRate = samplingRate;
-    this.buildClustersLock = new ReentrantLock();
     this.refreshHelper = new RefreshHelper(new Callable<Object>() {
       @Override
       public Object call() throws TasteException {
@@ -198,6 +195,7 @@ public final class TreeClusteringRecomme
     });
     refreshHelper.addDependency(dataModel);
     refreshHelper.addDependency(clusterSimilarity);
+    buildClusters();
   }
   
   @Override
@@ -267,39 +265,27 @@ public final class TreeClusteringRecomme
   }
 
   private void buildClusters() throws TasteException {
-    if (clustersBuilt) {
-      return;
-    }
-    buildClustersLock.lock();
-    try {
-      if (clustersBuilt) {
-        return;
-      }
-      DataModel model = getDataModel();
-      int numUsers = model.getNumUsers();
-      if (numUsers > 0) {
-        List<FastIDSet> newClusters = new ArrayList<FastIDSet>(numUsers);
-        // Begin with a cluster for each user:
-        LongPrimitiveIterator it = model.getUserIDs();
-        while (it.hasNext()) {
-          FastIDSet newCluster = new FastIDSet();
-          newCluster.add(it.nextLong());
-          newClusters.add(newCluster);
-        }
-        if (numUsers > 1) {
-          findClusters(newClusters);
-        }
-        topRecsByUserID = computeTopRecsPerUserID(newClusters);
-        clustersByUserID = computeClustersPerUserID(newClusters);
-        allClusters = newClusters.toArray(new FastIDSet[newClusters.size()]);
-      } else {
-        topRecsByUserID = new FastByIDMap<List<RecommendedItem>>();
-        clustersByUserID = new FastByIDMap<FastIDSet>();
-        allClusters = NO_CLUSTERS;
-      }
-      clustersBuilt = true;
-    } finally {
-      buildClustersLock.unlock();
+    DataModel model = getDataModel();
+    int numUsers = model.getNumUsers();
+    if (numUsers > 0) {
+      List<FastIDSet> newClusters = new ArrayList<FastIDSet>(numUsers);
+      // Begin with a cluster for each user:
+      LongPrimitiveIterator it = model.getUserIDs();
+      while (it.hasNext()) {
+        FastIDSet newCluster = new FastIDSet();
+        newCluster.add(it.nextLong());
+        newClusters.add(newCluster);
+      }
+      if (numUsers > 1) {
+        findClusters(newClusters);
+      }
+      topRecsByUserID = computeTopRecsPerUserID(newClusters);
+      clustersByUserID = computeClustersPerUserID(newClusters);
+      allClusters = newClusters.toArray(new FastIDSet[newClusters.size()]);
+    } else {
+      topRecsByUserID = new FastByIDMap<List<RecommendedItem>>();
+      clustersByUserID = new FastByIDMap<FastIDSet>();
+      allClusters = NO_CLUSTERS;
     }
   }
   

Modified: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/TreeClusteringRecommender2.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/TreeClusteringRecommender2.java?rev=1001298&r1=1001297&r2=1001298&view=diff
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/TreeClusteringRecommender2.java
(original)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/TreeClusteringRecommender2.java
Sat Sep 25 18:59:51 2010
@@ -26,7 +26,6 @@ import java.util.ListIterator;
 import java.util.PriorityQueue;
 import java.util.Queue;
 import java.util.concurrent.Callable;
-import java.util.concurrent.locks.ReentrantLock;
 
 import org.apache.mahout.cf.taste.common.Refreshable;
 import org.apache.mahout.cf.taste.common.TasteException;
@@ -80,8 +79,6 @@ public final class TreeClusteringRecomme
   private FastByIDMap<List<RecommendedItem>> topRecsByUserID;
   private FastIDSet[] allClusters;
   private FastByIDMap<FastIDSet> clustersByUserID;
-  private boolean clustersBuilt;
-  private final ReentrantLock buildClustersLock;
   private final RefreshHelper refreshHelper;
   
   /**
@@ -94,7 +91,8 @@ public final class TreeClusteringRecomme
    * @throws IllegalArgumentException
    *           if arguments are <code>null</code>, or <code>numClusters</code>
is less than 2
    */
-  public TreeClusteringRecommender2(DataModel dataModel, ClusterSimilarity clusterSimilarity,
int numClusters) {
+  public TreeClusteringRecommender2(DataModel dataModel, ClusterSimilarity clusterSimilarity,
int numClusters)
+    throws TasteException {
     super(dataModel);
     if (clusterSimilarity == null) {
       throw new IllegalArgumentException("clusterSimilarity is null");
@@ -106,7 +104,6 @@ public final class TreeClusteringRecomme
     this.numClusters = numClusters;
     this.clusteringThreshold = Double.NaN;
     this.clusteringByThreshold = false;
-    this.buildClustersLock = new ReentrantLock();
     this.refreshHelper = new RefreshHelper(new Callable<Object>() {
       @Override
       public Object call() throws TasteException {
@@ -116,6 +113,7 @@ public final class TreeClusteringRecomme
     });
     refreshHelper.addDependency(dataModel);
     refreshHelper.addDependency(clusterSimilarity);
+    buildClusters();
   }
   
   /**
@@ -132,7 +130,7 @@ public final class TreeClusteringRecomme
    */
   public TreeClusteringRecommender2(DataModel dataModel,
                                     ClusterSimilarity clusterSimilarity,
-                                    double clusteringThreshold) {
+                                    double clusteringThreshold) throws TasteException {
     super(dataModel);
     if (clusterSimilarity == null) {
       throw new IllegalArgumentException("clusterSimilarity is null");
@@ -144,7 +142,6 @@ public final class TreeClusteringRecomme
     this.numClusters = Integer.MIN_VALUE;
     this.clusteringThreshold = clusteringThreshold;
     this.clusteringByThreshold = true;
-    this.buildClustersLock = new ReentrantLock();
     this.refreshHelper = new RefreshHelper(new Callable<Object>() {
       @Override
       public Object call() throws TasteException {
@@ -154,6 +151,7 @@ public final class TreeClusteringRecomme
     });
     refreshHelper.addDependency(dataModel);
     refreshHelper.addDependency(clusterSimilarity);
+    buildClusters();
   }
   
   @Override
@@ -276,47 +274,34 @@ public final class TreeClusteringRecomme
   }
   
   private void buildClusters() throws TasteException {
-    if (clustersBuilt) {
-      return;
-    }
-    buildClustersLock.lock();
-    try {
-      if (clustersBuilt) {
-        return;
+    DataModel model = getDataModel();
+    int numUsers = model.getNumUsers();
+
+    if (numUsers == 0) {
+
+      topRecsByUserID = new FastByIDMap<List<RecommendedItem>>();
+      clustersByUserID = new FastByIDMap<FastIDSet>();
+
+    } else {
+
+      List<FastIDSet> clusters = new ArrayList<FastIDSet>();
+      // Begin with a cluster for each user:
+      LongPrimitiveIterator it = model.getUserIDs();
+      while (it.hasNext()) {
+        FastIDSet newCluster = new FastIDSet();
+        newCluster.add(it.nextLong());
+        clusters.add(newCluster);
       }
-      DataModel model = getDataModel();
-      int numUsers = model.getNumUsers();
-      
-      if (numUsers == 0) {
-        
-        topRecsByUserID = new FastByIDMap<List<RecommendedItem>>();
-        clustersByUserID = new FastByIDMap<FastIDSet>();
-        
-      } else {
-        
-        List<FastIDSet> clusters = new ArrayList<FastIDSet>();
-        // Begin with a cluster for each user:
-        LongPrimitiveIterator it = model.getUserIDs();
-        while (it.hasNext()) {
-          FastIDSet newCluster = new FastIDSet();
-          newCluster.add(it.nextLong());
-          clusters.add(newCluster);
-        }
-        
-        boolean done = false;
-        while (!done) {
-          done = mergeClosestClusters(numUsers, clusters, done);
-        }
-        
-        topRecsByUserID = computeTopRecsPerUserID(clusters);
-        clustersByUserID = computeClustersPerUserID(clusters);
-        allClusters = clusters.toArray(new FastIDSet[clusters.size()]);
-        
+
+      boolean done = false;
+      while (!done) {
+        done = mergeClosestClusters(numUsers, clusters, done);
       }
-      
-      clustersBuilt = true;
-    } finally {
-      buildClustersLock.unlock();
+
+      topRecsByUserID = computeTopRecsPerUserID(clusters);
+      clustersByUserID = computeClustersPerUserID(clusters);
+      allClusters = clusters.toArray(new FastIDSet[clusters.size()]);
+
     }
   }
   

Modified: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/slopeone/file/FileDiffStorage.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/slopeone/file/FileDiffStorage.java?rev=1001298&r1=1001297&r2=1001298&view=diff
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/slopeone/file/FileDiffStorage.java
(original)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/slopeone/file/FileDiffStorage.java
Sat Sep 25 18:59:51 2010
@@ -62,7 +62,6 @@ public final class FileDiffStorage imple
   
   private final File dataFile;
   private long lastModified;
-  private boolean loaded;
   private final long maxEntries;
   private final FastByIDMap<FastByIDMap<RunningAverage>> averageDiffs;
   private final FastIDSet allRecommendableItemIDs;
@@ -95,6 +94,8 @@ public final class FileDiffStorage imple
     this.averageDiffs = new FastByIDMap<FastByIDMap<RunningAverage>>();
     this.allRecommendableItemIDs = new FastIDSet();
     this.buildAverageDiffsLock = new ReentrantReadWriteLock();
+
+    buildDiffs();
   }
   
   private void buildDiffs() {
@@ -206,17 +207,9 @@ public final class FileDiffStorage imple
     allRecommendableItemIDs.rehash();
   }
   
-  private void checkLoaded() {
-    if (!loaded) {
-      buildDiffs();
-      loaded = true;
-    }
-  }
-  
   @Override
   public RunningAverage getDiff(long itemID1, long itemID2) {
-    checkLoaded();
-    
+
     boolean inverted = false;
     if (itemID1 > itemID2) {
       inverted = true;
@@ -248,7 +241,6 @@ public final class FileDiffStorage imple
   
   @Override
   public RunningAverage[] getDiffs(long userID, long itemID, PreferenceArray prefs) {
-    checkLoaded();
     try {
       buildAverageDiffsLock.readLock().lock();
       int size = prefs.length();
@@ -264,13 +256,11 @@ public final class FileDiffStorage imple
   
   @Override
   public RunningAverage getAverageItemPref(long itemID) {
-    checkLoaded();
     return null; // TODO can't do this without a DataModel
   }
   
   @Override
   public void updateItemPref(long itemID, float prefDelta, boolean remove) {
-    checkLoaded();
     try {
       buildAverageDiffsLock.readLock().lock();
       for (Map.Entry<Long,FastByIDMap<RunningAverage>> entry : averageDiffs.entrySet())
{
@@ -303,7 +293,6 @@ public final class FileDiffStorage imple
   
   @Override
   public FastIDSet getRecommendableItemIDs(long userID) {
-    checkLoaded();
     try {
       buildAverageDiffsLock.readLock().lock();
       return allRecommendableItemIDs.clone();

Added: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/file/FileItemItemSimilarityIterable.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/file/FileItemItemSimilarityIterable.java?rev=1001298&view=auto
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/file/FileItemItemSimilarityIterable.java
(added)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/file/FileItemItemSimilarityIterable.java
Sat Sep 25 18:59:51 2010
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.mahout.cf.taste.impl.similarity.file;
+
+import org.apache.mahout.cf.taste.impl.similarity.GenericItemSimilarity;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+
+/**
+ * {@link Iterable} to be able to read a file linewise into a {@link GenericItemSimilarity}
+ */
+final class FileItemItemSimilarityIterable implements Iterable<GenericItemSimilarity.ItemItemSimilarity>
{
+
+  private final File similaritiesFile;
+
+  FileItemItemSimilarityIterable(File similaritiesFile) {
+    this.similaritiesFile = similaritiesFile;
+  }
+
+  @Override
+  public Iterator<GenericItemSimilarity.ItemItemSimilarity> iterator() {
+    try {
+      return new FileItemItemSimilarityIterator(similaritiesFile);
+    } catch (IOException ioe) {
+      throw new IllegalStateException("Can't read " + similaritiesFile);
+    }
+  }
+
+}

Added: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/file/FileItemItemSimilarityIterator.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/file/FileItemItemSimilarityIterator.java?rev=1001298&view=auto
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/file/FileItemItemSimilarityIterator.java
(added)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/file/FileItemItemSimilarityIterator.java
Sat Sep 25 18:59:51 2010
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.mahout.cf.taste.impl.similarity.file;
+
+import org.apache.mahout.cf.taste.impl.similarity.GenericItemSimilarity;
+import org.apache.mahout.common.FileLineIterator;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.regex.Pattern;
+
+/**
+ * a simple iterator using a {@link org.apache.mahout.common.FileLineIterator} internally,
parsing each
+ * line into an {@link org.apache.mahout.cf.taste.impl.similarity.GenericItemSimilarity.ItemItemSimilarity}
+ */
+final class FileItemItemSimilarityIterator implements Iterator<GenericItemSimilarity.ItemItemSimilarity>
{
+
+  private static final Pattern SEPARATOR = Pattern.compile("[,\t]");
+
+  private final FileLineIterator lineIterator;
+
+  FileItemItemSimilarityIterator(File similaritiesFile) throws IOException {
+    lineIterator = new FileLineIterator(similaritiesFile);
+  }
+
+  @Override
+  public boolean hasNext() {
+    return lineIterator.hasNext();
+  }
+
+  @Override
+  public GenericItemSimilarity.ItemItemSimilarity next() {
+    String line = lineIterator.next();
+    String[] tokens = SEPARATOR.split(line);
+    return new GenericItemSimilarity.ItemItemSimilarity(Long.parseLong(tokens[0]),
+                                                        Long.parseLong(tokens[1]),
+                                                        Double.parseDouble(tokens[2]));
+  }
+
+  @Override
+  public void remove() {
+    throw new UnsupportedOperationException();
+  }
+}

Modified: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/file/FileItemSimilarity.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/file/FileItemSimilarity.java?rev=1001298&r1=1001297&r2=1001298&view=diff
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/file/FileItemSimilarity.java
(original)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/file/FileItemSimilarity.java
Sat Sep 25 18:59:51 2010
@@ -18,19 +18,13 @@
 package org.apache.mahout.cf.taste.impl.similarity.file;
 
 import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
 import java.util.Collection;
-import java.util.Iterator;
 import java.util.concurrent.locks.ReentrantLock;
-import java.util.regex.Pattern;
 
 import org.apache.mahout.cf.taste.common.Refreshable;
 import org.apache.mahout.cf.taste.common.TasteException;
 import org.apache.mahout.cf.taste.impl.similarity.GenericItemSimilarity;
-import org.apache.mahout.cf.taste.impl.similarity.GenericItemSimilarity.ItemItemSimilarity;
 import org.apache.mahout.cf.taste.similarity.ItemSimilarity;
-import org.apache.mahout.common.FileLineIterator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -65,7 +59,6 @@ public class FileItemSimilarity implemen
   private final ReentrantLock reloadLock;
   private final File dataFile;
   private long lastModified;
-  private boolean loaded;
   private final long minReloadIntervalMS;
 
   private static final Logger log = LoggerFactory.getLogger(FileItemSimilarity.class);
@@ -73,9 +66,8 @@ public class FileItemSimilarity implemen
   /**
    * @param dataFile
    *          file containing the similarity data
-   * @throws IOException
    */
-  public FileItemSimilarity(File dataFile) throws IOException {
+  public FileItemSimilarity(File dataFile) {
     this(dataFile, DEFAULT_MIN_RELOAD_INTERVAL_MS);
   }
 
@@ -85,57 +77,48 @@ public class FileItemSimilarity implemen
    *          when refresh() is called
    * @see #FileItemSimilarity(File)
    */
-  public FileItemSimilarity(File dataFile, long minReloadIntervalMS) throws IOException {
+  public FileItemSimilarity(File dataFile, long minReloadIntervalMS) {
     if (dataFile == null) {
       throw new IllegalArgumentException("dataFile is null");
     }
     if (!dataFile.exists() || dataFile.isDirectory()) {
-      throw new FileNotFoundException(dataFile.toString());
+      throw new IllegalArgumentException("dataFile is missing or a directory: " + dataFile);
     }
 
     log.info("Creating FileItemSimilarity for file {}", dataFile);
 
     this.dataFile = dataFile.getAbsoluteFile();
     this.lastModified = dataFile.lastModified();
-    this.loaded = false;
     this.minReloadIntervalMS = minReloadIntervalMS;
     this.reloadLock = new ReentrantLock();
+
+    reload();
   }
 
   @Override
   public double[] itemSimilarities(long itemID1, long[] itemID2s) throws TasteException {
-    checkLoaded();
     return delegate.itemSimilarities(itemID1, itemID2s);
   }
 
   @Override
   public double itemSimilarity(long itemID1, long itemID2) throws TasteException {
-    checkLoaded();
     return delegate.itemSimilarity(itemID1, itemID2);
   }
 
   @Override
   public void refresh(Collection<Refreshable> alreadyRefreshed) {
-    if (delegate == null || dataFile.lastModified() > lastModified + minReloadIntervalMS)
{
+    if (dataFile.lastModified() > lastModified + minReloadIntervalMS) {
       log.debug("File has changed; reloading...");
       reload();
     }
   }
 
-  private void checkLoaded() {
-    if (!loaded) {
-      reload();
-    }
-  }
-
   protected void reload() {
-    if (!reloadLock.isLocked()) {
-      reloadLock.lock();
+    if (reloadLock.tryLock()) {
       try {
         long newLastModified = dataFile.lastModified();
         delegate = new GenericItemSimilarity(new FileItemItemSimilarityIterable(dataFile));
         lastModified = newLastModified;
-        loaded = true;
       } finally {
         reloadLock.unlock();
       }
@@ -147,58 +130,4 @@ public class FileItemSimilarity implemen
     return "FileItemSimilarity[dataFile:" + dataFile + ']';
   }
 
-  /**
-   * {@link Iterable} to be able to read a file linewise into a {@link GenericItemSimilarity}
-   */
-  static class FileItemItemSimilarityIterable implements Iterable<ItemItemSimilarity>
{
-
-    private final File similaritiesFile;
-
-    FileItemItemSimilarityIterable(File similaritiesFile) {
-      this.similaritiesFile = similaritiesFile;
-    }
-
-    @Override
-    public Iterator<ItemItemSimilarity> iterator() {
-      return new FileItemItemSimilarityIterator(similaritiesFile);
-    }
-
-    /**
-     * a simple iterator using a {@link FileLineIterator} internally, parsing each
-     * line into an {@link ItemItemSimilarity}
-     */
-    static class FileItemItemSimilarityIterator implements Iterator<ItemItemSimilarity>
{
-
-      private static final Pattern SEPARATOR = Pattern.compile("[,\t]");
-
-      private final FileLineIterator lineIterator;
-
-      FileItemItemSimilarityIterator(File similaritiesFile) {
-        try {
-          lineIterator = new FileLineIterator(similaritiesFile);
-        } catch (IOException e) {
-          throw new IllegalArgumentException("Cannot read similarities file", e);
-        }
-      }
-
-      @Override
-      public boolean hasNext() {
-        return lineIterator.hasNext();
-      }
-
-      @Override
-      public ItemItemSimilarity next() {
-        String line = lineIterator.next();
-        String[] tokens = SEPARATOR.split(line);
-        return new ItemItemSimilarity(Long.parseLong(tokens[0]), Long.parseLong(tokens[1]),
-            Double.parseDouble(tokens[2]));
-      }
-
-      @Override
-      public void remove() {
-        throw new UnsupportedOperationException();
-      }
-    }
-
-  }
 }

Modified: mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/similarity/file/FileItemSimilarityTest.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/similarity/file/FileItemSimilarityTest.java?rev=1001298&r1=1001297&r2=1001298&view=diff
==============================================================================
--- mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/similarity/file/FileItemSimilarityTest.java
(original)
+++ mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/similarity/file/FileItemSimilarityTest.java
Sat Sep 25 18:59:51 2010
@@ -18,7 +18,6 @@
 package org.apache.mahout.cf.taste.impl.similarity.file;
 
 import java.io.File;
-import java.io.FileNotFoundException;
 
 import org.apache.mahout.cf.taste.impl.TasteTestCase;
 import org.apache.mahout.cf.taste.impl.similarity.GenericItemSimilarity;
@@ -110,16 +109,14 @@ public final class FileItemSimilarityTes
     assertEquals(0.112, similarity.itemSimilarity(8L, 7L), EPSILON);
   }
 
-  @Test
+  @Test(expected = IllegalArgumentException.class)
   public void testFileNotFoundExceptionForNonExistingFile() throws Exception {
-    try {
-      new FileItemSimilarity(new File("xKsdfksdfsdf"));
-      fail();
-    } catch (FileNotFoundException e) {}
+    new FileItemSimilarity(new File("xKsdfksdfsdf"));
   }
 
+  @Test
   public void testFileItemItemSimilarityIterable() throws Exception {
-    Iterable<ItemItemSimilarity> similarityIterable = new FileItemSimilarity.FileItemItemSimilarityIterable(testFile);
+    Iterable<ItemItemSimilarity> similarityIterable = new FileItemItemSimilarityIterable(testFile);
     GenericItemSimilarity similarity = new GenericItemSimilarity(similarityIterable);
 
     assertEquals(0.125, similarity.itemSimilarity(1L, 5L), EPSILON);



Mime
View raw message