/******************************************************************************* * 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.cassandra; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; 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.DeleteOperation; import org.ublog.benchmark.operations.GetOperation; 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 StopFollowingOperation implements BenchOperation, OperationListener { private enum Phase { UPDATE_FOLLOWERS, UPDATE_FOLLOWING, UPDATE_TIMELINE } private ComplexBenchMarkClient client; private String userId, toStopUser; private Phase currentPhase; private Map<String, String> user; private Map<String, String> toStop; private boolean get; private boolean finish; private List<String> timeLine; public StopFollowingOperation(ComplexBenchMarkClient client, String userId, String toStopUser) { this.client = client; this.userId = userId; this.toStopUser = toStopUser; this.currentPhase = Phase.UPDATE_FOLLOWERS; this.get = false; this.finish = false; this.user = null; this.toStop = null; } private void addToTimeline(List<String> timeline, int timelineIdx, String timelineId) { timeline.add(timelineIdx, timelineId); } private String getTimelineId(Message tweet) { return tweet.getId() + ":" + tweet.getDate().toString(); } @SuppressWarnings("unchecked") @Override public void handleFinishedOperation(DataStoreOperation op) { switch (this.currentPhase) { case UPDATE_FOLLOWERS: if (this.toStop == null) { this.toStop = (Map<String, String>) ((GetOperation) op) .getResult(); } else this.currentPhase = Phase.UPDATE_FOLLOWING; break; case UPDATE_FOLLOWING: if (this.user == null) { this.user = (Map<String, String>) ((GetOperation) op) .getResult(); } else this.currentPhase = Phase.UPDATE_TIMELINE; break; case UPDATE_TIMELINE: if (this.timeLine == null) { this.timeLine = (List<String>) ((GetOperation) op).getResult(); if (this.timeLine == null) this.timeLine = new ArrayList<String>(); } else this.client.handleFinishedComplexOperation(this); break; } } @Override public String getName() { return "twitter:stopFollowing"; } @SuppressWarnings("unchecked") @Override public CollectionOperation getNextDBOperation() throws UnsupportedEncodingException { CollectionOperation res = null; switch (this.currentPhase) { case UPDATE_FOLLOWERS: if (!this.get) { // CASSANDRA List<byte[]> columns = new ArrayList<byte[]>(); columns.add("followers".getBytes("UTF-8")); // FINISHED res = new GetOperation(client, SocialBenchmark.userTable, this.toStopUser, columns); this.get = true; } else { Set<String> followers = Utils.asSet(this.toStop .get(UserService.FOLLOWERS)); followers.remove(userId); this.toStop.put(UserService.FOLLOWERS, Utils.toString(followers)); res = new PutOperation(client, SocialBenchmark.userTable, this.toStopUser, this.toStop, null); this.get = false; } break; case UPDATE_FOLLOWING: if (!this.get) { // CASSANDRA List<byte[]> columns = new ArrayList<byte[]>(); columns.add("following".getBytes("UTF-8")); // FINISHED res = new GetOperation(client, SocialBenchmark.userTable, this.userId, columns); this.get = true; } else { Set<String> following = Utils.asSet(user .get(UserService.FOLLOWING)); following.remove(toStopUser); this.user.put(UserService.FOLLOWING, Utils.toString(following)); res = new PutOperation(client, SocialBenchmark.userTable, this.userId, this.user, null); this.get = false; } break; case UPDATE_TIMELINE: if (!this.get) { this.timeLine = null; res = new GetOperation(client, SocialBenchmark.friendsTimeLineTable, this.userId, 250); this.get = true; } else { // CASSANDRA: DEL SPECIFIED COLUMNS List<byte[]> columns = new ArrayList<byte[]>(); // /FINISH for (Iterator<String> itr = this.timeLine.iterator(); itr .hasNext();) { String idAndTime = itr.next(); String[] split = idAndTime.split(":"); String id = split[0]; String date = split[1]; if (id.startsWith(this.toStopUser + "-")) { itr.remove(); columns.add(Utils.asByteArray(java.util.UUID .fromString(date))); } } List<Integer> tags = new ArrayList<Integer>(); tags.add(Utils.getTagUserID(this.userId)); res = new DeleteOperation(client, SocialBenchmark.friendsTimeLineTable, this.userId, columns); // res=new // PutOperation(client,TwitterBenchmark.friendsTimeLineTable,this.userId,timeLine,tags); this.finish = true; } break; } res.addListener(this); return res; } @Override public boolean hasMoreDBOperations() { return !this.finish; } @Override public String toString() { return "StopFollowingOperation [toStopUser=" + toStopUser + ", userId=" + userId + "]"; } @Override public boolean isReadOnly() { return false; } @Override public boolean isInit() { // TODO Auto-generated method stub return false; } @Override public void setInit(boolean init) { // TODO Auto-generated method stub } }