/*******************************************************************************
* 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.mysql;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.ublog.utils.Pair;
import org.ublog.benchmark.BenchOperation;
import org.ublog.benchmark.ComplexBenchMarkClient;
import org.ublog.benchmark.operations.CollectionOperation;
import org.ublog.benchmark.operations.DataStoreOperation;
import org.ublog.benchmark.operations.GetOperation;
import org.ublog.benchmark.operations.MultiPutOperation;
import org.ublog.benchmark.operations.OperationListener;
import org.ublog.benchmark.operations.PutOperation;
import org.ublog.benchmark.social.Message;
import org.ublog.benchmark.social.SocialBenchmark;
import org.ublog.benchmark.social.UserService;
import org.ublog.benchmark.social.Utils;
public class TweetOperation implements BenchOperation,OperationListener{
private Logger logger= Logger.getLogger(TweetOperation.class);
private enum Phase {USER,TWEET,FOLLOWERS};
private Phase phase;
private boolean get;
private boolean finish;
private ComplexBenchMarkClient client;
private Message tweet;
private Map<String, String> tweetMap;
private Map<String, String> user;
private String tweetId;
private Set<String> followers;
private Map<String, Pair<List<String>, List<Integer>>> mapTimeLine;
private Map<String, Pair<String,Object>> tweetFriendsTimeline;
private Set<String> tags;
private boolean init;
public TweetOperation(ComplexBenchMarkClient client,Message tweet,Set<String> tags2)
{
this.client=client;
this.tweet=tweet;
this.phase=Phase.USER;
this.get=false;
this.finish=false;
this.user=null;
this.mapTimeLine=null;
this.tags=tags2;
this.setInit(false);
logger.setLevel(Level.OFF);
}
private void insertTweet() {
String dateStr = tweetMap.get(Utils.DATE);
Long date = new Long(dateStr);
String timelineId = tweetId + ":" + dateStr;
cycle://////
for(String key:this.mapTimeLine.keySet())
{
List<String> timeLine=this.mapTimeLine.get(key).getFirst();
for (int i = 0; i < timeLine.size(); i++) {
String id =timeLine.get(i/*0*/);
String[] split = id.split(":");
Long timelineDate = new Long(split[1]);
if (timelineDate < date) {
timeLine.add(i, timelineId);
continue cycle;//////
//return;
}
}
timeLine.add(timelineId);
}
}
@SuppressWarnings("unchecked")
private void setTweetToFriendsTimeLine(){
String dateStr = tweetMap.get(Utils.DATE);
String timelineId = tweetId + ":" + dateStr;
this.tweetFriendsTimeline = new HashMap<String,Pair<String,Object>>();
for(String follower:this.followers){
this.tweetFriendsTimeline.put(follower,new Pair(dateStr, tweetId));
}
}
@SuppressWarnings("unchecked")
@Override
public void handleFinishedOperation(DataStoreOperation op) {
switch(this.phase)
{
case USER:
if (this.user==null)
{
this.user=(Map<String,String>) ((GetOperation) op).getResult();
if (this.user==null)
{
this.finish=true;
}
else
{
this.followers =Utils.asSet(user.get(UserService.FOLLOWERS));
//Also update my timeLine
this.followers.add(this.tweet.getUser());
}
}
else
this.phase=Phase.TWEET;
break;
case TWEET:
this.phase=Phase.FOLLOWERS;
break;
case FOLLOWERS:
if (!init){
this.client.handleFinishedComplexOperation(this);
}
break;
}
}
@Override
public String getName() {
return "twitter:tweet";
}
@Override
public CollectionOperation getNextDBOperation() throws UnsupportedEncodingException {
CollectionOperation res=null;
switch(this.phase)
{
case USER:
if (!this.get)
{
tweet.setDate(Utils.getTimeUUID());
this.tweetMap = Utils.toMap(tweet);
String userId = tweet.getUser();
List<String> columns = new ArrayList<String>();
columns.add("lastTweet");
columns.add("followers");
res=new GetOperation(client,SocialBenchmark.userTable,userId,columns);
this.get=true;
}
else
{
String lastTweetStr = user.get(UserService.LAST_TWEET);
int lastTweet = Integer.valueOf(lastTweetStr);
int tweetIdx = ++lastTweet;
user.put(UserService.LAST_TWEET, new Integer(tweetIdx).toString());
this.tweetId=tweet.getUser() + "-" + Utils.getTweetPadding(tweetIdx);
res=new PutOperation(client,SocialBenchmark.userTable,tweet.getUser(),user,null);
this.get=false;
}
break;
case TWEET:
tweetMap.put(Utils.ID, this.tweetId);
res=new PutOperation(client,SocialBenchmark.tweetsTable,tweetId,tweetMap,this.tags);
this.get=false;
break;
case FOLLOWERS:
this.setTweetToFriendsTimeLine();
res=new MultiPutOperation<String,String>(client,SocialBenchmark.friendsTimeLineTable,this.tweetFriendsTimeline);
this.finish=true;
break;
}
res.addListener(this);
if (init)
res.setInit(true);
return res;
}
@Override
public boolean hasMoreDBOperations() {
return !finish;
}
@Override
public String toString() {
return "TweetOperation [tweet=" + tweet + ";tags:"+tags+"]";
}
public void setInit(boolean init) {
this.init = init;
}
public boolean isInit() {
return init;
}
@Override
public boolean isReadOnly() {
return false;
}
}