/******************************************************************************* * Copyright 2010 Universidade do Minho, Ricardo Vila�a and Francisco Cruz * * Licensed 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.ublog.benchmark.social; import java.io.UnsupportedEncodingException; import java.rmi.NotBoundException; import java.rmi.RMISecurityManager; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; import org.apache.log4j.Logger; import org.ublog.utils.Pair; import org.ublog.benchmark.BenchOperation; import org.ublog.benchmark.ComplexBenchMarkClient; import org.ublog.benchmark.ComplexBenchmark; import org.ublog.benchmark.StatsCollector; import org.ublog.benchmark.operations.CollectionOperation; import org.ublog.benchmark.operations.MultiPutOperation; import org.ublog.graph.GraphInterface; import org.ublog.utils.Clock; public class SocialBenchmark extends ComplexBenchmark { public final static String userTable = "users"; public final static String tweetsTable = "tweets"; public final static String friendsTimeLineTable = "friendsTimeLine"; private Logger logger = Logger.getLogger(SocialBenchmark.class); //Values defined by configuration file private double initialTweetsFactor=10.0; private double probabilitySearchPerTopic=0.15; private double probabilitySearchPerOwner=0.25; private double probabilityGetRecentTweets=0.05; private double probabilityGetFriendsTimeline=0.45; private double probabilityStartFollowing=0.05; private double probabilityStopFollowing=0.05; private int totalSize=0; private boolean missingCreatingTables; private boolean missingAddingUsers; private int currentUser; private int currentTweet; private int currentNTweets; private BenchOperation currentTweetOp; private UserService clouderUserService; private int nOperations; private Random rndOp; private Random rndOwner; private Random rndTopic; private Random rndStartFollow; private double thinkTime; private SocialOperationsFactory opFactory; private GraphInterface remoteGraphServer; private boolean hasInitiated; public SocialBenchmark(StatsCollector statsCollector, SocialOperationsFactory opFactory, int sizeTotal, int size, int usernameStarter, int nOperations, double thinkTime) { super(statsCollector, usernameStarter); this.opFactory = opFactory; Utils.NUsers = size; this.nOperations = nOperations; this.thinkTime = thinkTime; this.clouderUserService = new UserService(); this.currentUser = 0; this.currentTweet = 0; this.currentNTweets = 0; this.missingCreatingTables = true; this.missingAddingUsers = true; this.totalSize=sizeTotal; } public double getProbabilitySearchPerTopic() { return probabilitySearchPerTopic; } public void setProbabilitySearchPerTopic(double probabilitySearchPerTopic) { this.probabilitySearchPerTopic = probabilitySearchPerTopic; } public double getProbabilitySearchPerOwner() { return probabilitySearchPerOwner; } public void setProbabilitySearchPerOwner(double probabilitySearchPerOwner) { this.probabilitySearchPerOwner = probabilitySearchPerOwner; } public double getProbabilityGetRecentTweets() { return probabilityGetRecentTweets; } public void setProbabilityGetRecentTweets(double probabilityGetRecentTweets) { this.probabilityGetRecentTweets = probabilityGetRecentTweets; } public double getProbabilityGetFriendsTimeline() { return probabilityGetFriendsTimeline; } public void setProbabilityGetFriendsTimeline( double probabilityGetFriendsTimeline) { this.probabilityGetFriendsTimeline = probabilityGetFriendsTimeline; } public double getProbabilityStartFollowing() { return probabilityStartFollowing; } public void setProbabilityStartFollowing(double probabilityStartFollowing) { this.probabilityStartFollowing = probabilityStartFollowing; } public double getProbabilityStopFollowing() { return probabilityStopFollowing; } public void setProbabilityStopFollowing(double probabilityStopFollowing) { this.probabilityStopFollowing = probabilityStopFollowing; } @Override public void initialize(Configuration conf) throws ConfigurationException { this.initialTweetsFactor=conf.getDouble("benchmark.social.initialTweetsFactor"); Utils.MAX_MESSAGES_IN_TIMELINE=conf.getInt("benchmark.social.maximumMessagesTimeline"); Utils.MaxNTweets=conf.getInt("benchmark.social.maximumTweetsPerUser"); long seedNextOperation=conf.containsKey("benchmark.social.seedNextOperation") ? conf.getLong("benchmark.social.seedNextOperation"): System.nanoTime(); long seedOwner=conf.containsKey("benchmark.social.seedOwner") ? conf.getLong("benchmark.social.seedOwner"): System.nanoTime(); long seedTopic=conf.containsKey("benchmark.social.seedTopic") ? conf.getLong("benchmark.social.seedTopic"): System.nanoTime(); long seedStartFollow=conf.containsKey("benchmark.social.seedStartFollow") ? conf.getLong("benchmark.social.seedStartFollow"): System.nanoTime(); this.rndOp = new Random(seedNextOperation); this.rndOwner = new Random(seedOwner); this.rndTopic = new Random(seedTopic); this.rndStartFollow = new Random(seedStartFollow); this.probabilitySearchPerTopic=conf.getDouble("benchmark.social.probabilities.probabilitySearchPerTopic"); this.probabilitySearchPerOwner=conf.getDouble("benchmark.social.probabilities.probabilitySearchPerOwner"); this.probabilityGetRecentTweets=conf.getDouble("benchmark.social.probabilities.probabilityGetRecentTweets"); this.probabilityGetFriendsTimeline=conf.getDouble("benchmark.social.probabilities.probabilityGetFriendsTimeline"); this.probabilityStartFollowing=conf.getDouble("benchmark.social.probabilities.probabilityStartFollowing"); this.probabilityStopFollowing=conf.getDouble("benchmark.social.probabilities.probabilityStopFollowing"); if (this.probabilityGetFriendsTimeline+this.probabilityGetRecentTweets+this.probabilitySearchPerOwner+ this.probabilitySearchPerTopic+this.probabilityStartFollowing+this.probabilityStopFollowing >1) { logger.warn("The sum of all probabilities must be less or equal than 1."); throw new ConfigurationException("The sum of all probabilities must be less or equal than 1."); } String serverName=conf.getString("benchmark.server.name"); int serverPort=conf.getInt("benchmark.server.port"); this.remoteGraphServer = this.getRemoteGraphServer(serverName,serverPort); try { this.hasInitiated = this.remoteGraphServer.init(this.totalSize); } catch (RemoteException e) { e.printStackTrace(); } } private GraphInterface getRemoteGraphServer(String serverName,int serverPort) { if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } try { if (logger.isInfoEnabled()) { logger.info("Trying to connect to graph server"); } Registry reg = LocateRegistry.getRegistry(serverName,serverPort); System.out.println("reg " + reg.list().toString()); return (GraphInterface) reg.lookup("Graph"); } catch (NotBoundException ex) { Logger.getLogger("global").log(null, ex); return null; } catch (RemoteException ex) { ex.printStackTrace(); Logger.getLogger("global").log(null, ex); return null; } } public String getPowerLawTag() { Random rnd = new Random(); int val = 0; int i = 0; try { val = rnd.nextInt(this.remoteGraphServer.getSomaGraus()) + 1; int sum = 0; for (i = 0; i < 64; i++) { sum += this.remoteGraphServer.degreeOfGrausTags("topico" + i); if (sum >= val) { break; } } } catch (RemoteException e) { e.printStackTrace(); } return "topico" + i; } public int getRandomFriend(User myUser) { int res; try { res = this.remoteGraphServer.getRandomFriend(myUser); } catch (RemoteException e) { e.printStackTrace(); res = -1; } if (res == -1) return Utils.NUsers; else return res; } @Override public ComplexBenchMarkClient createNewClient(Clock clock, int clientCount) { ComplexBenchMarkClient client; try { client = new SocialClient(clock, clientCount, this.remoteGraphServer.getClientCount(clientCount), this.nOperations, this.getStatsCollector(), this.thinkTime, this.rndOp, this, this.opFactory); } catch (RemoteException e) { e.printStackTrace(); client = null; } return client; } @Override public boolean hasMoreInitOperations() { int userID; if (this.hasInitiated == false) { try { userID = this.remoteGraphServer.getUserID(); // System.out.println("USERID HASMOREINIT:"+userID); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); userID = 1; } if (logger.isInfoEnabled()) logger.info("currentUser:" + this.currentUser + ";userID:" + userID + ";currentTweet:" + this.currentTweet + ";currentNTweets:" + this.currentNTweets); return this.missingCreatingTables || this.missingAddingUsers || this.currentUser < userID - 1 || this.currentTweetOp.hasMoreDBOperations() || this.currentTweet < this.currentNTweets - 1; } else return false; } @SuppressWarnings("unchecked") @Override public CollectionOperation nextInitOperation() throws UnsupportedEncodingException { CollectionOperation res; if (this.missingCreatingTables) { /* * TableMetaData<String> * metaData=this.collectionsMetadata.get(currentCollection); * this.currentCollection++; res=new * CreateTableOperation<String>(metaData); * this.missingCreatingCollections = false;///////fui q pus */ res = null; this.missingCreatingTables = false; } else { if (missingAddingUsers) { int userID; try { userID = this.remoteGraphServer.getUserID(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); userID = 1; } Map<String, Pair<Map<String, String>, List<Integer>>> puts = new HashMap<String, Pair<Map<String, String>, List<Integer>>>(); for (int i = 0; i < userID; i++) { // User currentUser=this.mapUser.get(i); User currentUser; try { currentUser = this.remoteGraphServer.getMapUser(i); } catch (RemoteException e1) { e1.printStackTrace(); currentUser = null; } Set<String> followers = new HashSet<String>(); Set<String> following = new HashSet<String>(); try { followers = this.remoteGraphServer .getFollowers(currentUser); following = this.remoteGraphServer .getFollowing(currentUser); } catch (RemoteException e) { e.printStackTrace(); } /* * for (DefaultEdge * edge:this.graph.incomingEdgesOf(currentUser)) { * followers. * add(this.graph.getEdgeSource(edge).getUsername()); } for * (DefaultEdge * edge:this.graph.outgoingEdgesOf(currentUser)) { * following. * add(this.graph.getEdgeTarget(edge).getUsername()); } */ // List<Integer> tags=new ArrayList<Integer>(); // tags.add(Utils.getTagUserID(currentUser.getUsername())); puts.put( currentUser.getUsername(), new Pair<Map<String, String>, List<Integer>>( this.clouderUserService.newUser( currentUser, Utils.toString(followers), Utils.toString(following)), null)); } CollectionOperation tmp = new MultiPutOperation(null, "users", puts); tmp.setInit(true); res = tmp; this.missingAddingUsers = false; this.currentUser = 0; this.currentTweet = 0; try { // this.currentNTweets=(int) // Math.ceil(this.graph.outDegreeOf(this.mapUser.get(this.currentUser))*initialTweetsFactor); this.currentNTweets = (int) Math .ceil(this.remoteGraphServer .getOutDegreeOf(currentUser) * initialTweetsFactor); // this.currentTweetOp=this.getNewTweetOperation(this.mapUser.get(this.currentUser), // null); this.currentTweetOp = this.getNewTweetOperation( this.remoteGraphServer.getMapUser(currentUser), null); // System.out.println("currentNTweets: "+currentNTweets); } catch (RemoteException e) { e.printStackTrace(); } this.currentTweetOp.setInit(true); // System.out.println("SET INIT op:"+this.currentTweetOp); } else { if (this.currentTweetOp.hasMoreDBOperations()) { res = this.currentTweetOp.getNextDBOperation(); } else { this.currentTweet++; if (this.currentTweet < this.currentNTweets) { try { // this.currentTweetOp=this.getNewTweetOperation(this.mapUser.get(this.currentUser), // null); this.currentTweetOp = this.getNewTweetOperation( this.remoteGraphServer .getMapUser(currentUser), null); } catch (RemoteException e) { e.printStackTrace(); } this.currentTweetOp.setInit(true); // System.out.println("SET INIT op:"+this.currentTweetOp); res = this.currentTweetOp.getNextDBOperation(); } else { this.currentUser++; this.currentTweet = 0; try { // this.currentNTweets=(int) // Math.ceil(this.graph.outDegreeOf(this.mapUser.get(this.currentUser))*initialTweetsFactor); this.currentNTweets = (int) Math .ceil(this.remoteGraphServer .getOutDegreeOf(currentUser) * initialTweetsFactor); // this.currentTweetOp=this.getNewTweetOperation(this.mapUser.get(this.currentUser), // null); this.currentTweetOp = this.getNewTweetOperation( this.remoteGraphServer .getMapUser(currentUser), null); } catch (RemoteException e) { e.printStackTrace(); } this.currentTweetOp.setInit(true); // System.out.println("SET INIT op:"+this.currentTweetOp); res = this.currentTweetOp.getNextDBOperation(); } } } } if (logger.isInfoEnabled()) logger.info("Next Init Operation is:" + res); return res; } public String getNextStartFollowingUser(User user) { // Da o utilizador com mais seguidores ao qual o user ainda nao segue String res = null; while (true) { int userID = this.rndStartFollow.nextInt(Utils.NUsers); boolean containsEdge; try { containsEdge = this.remoteGraphServer.graphContainsEdge(user, userID); } catch (RemoteException e) { e.printStackTrace(); containsEdge = false; } if (!containsEdge) { try { res = this.remoteGraphServer.getMapUser(userID) .getUsername(); } catch (RemoteException e) { e.printStackTrace(); } break; } } return res; } public String getNextStopFollowingUser(User user) { // Da o utilizador com menos seguidores ao qual o user ainda segue try { return this.remoteGraphServer.getNextStopFollowingUser(user); } catch (RemoteException e) { e.printStackTrace(); return null; } } public BenchOperation getNewTweetOperation(User user, SocialClient client) { // System.out.println("NEW TWEET OP"); double hasOwner = rndOwner.nextDouble(); double hasTopic = rndTopic.nextDouble(); // System.out.println("TAGS PROB: "+hasOwner+";"+hasTopic); Set<String> tags = new HashSet<String>(); if (hasTopic <= 0.05) // 0.05 { tags.add(this.getPowerLawTag()); } if (hasOwner <= 0.35) { int friend = this.getRandomFriend(user); tags.add("user" + friend); // System.out.println("user"+friend); } Message tweet = new Message(); // tweet.setDate(new Date()); tweet.setDate(Utils.getTimeUUID()); tweet.setText("qq"); tweet.setUser(user.getUsername()); return this.opFactory.getNewTweetOperation(client, tweet, tags); } }