/*
* Copyright 2014 Alexey Plotnik
*
* 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.stem.streaming;
import com.twitter.crunch.MappingDiff;
import com.twitter.crunch.Node;
import org.stem.utils.TopologyUtils;
import java.util.*;
public class DiskMovementMap {
/**
* {
* "src_disk_UUID": {
* vBucket: "dst_disk_UUID"
* }
* }
*/
private Map<String, Map<Long, String>> diskMovementMap = new HashMap<String, Map<Long, String>>();
private DiskMovementMap(Map<String, Map<Long, String>> diskMovementMap, boolean b) // "b" to avoid erasure ambiguity
{
this.diskMovementMap = diskMovementMap;
}
public Map<String, Map<Long, String>> getMap() {
return diskMovementMap;
}
public DiskMovementMap(Map<Long, List<MappingDiff.Value<Node>>> mappingDiff) // TODO: translate to factory method
{
for (Map.Entry<Long, List<MappingDiff.Value<Node>>> entry : mappingDiff.entrySet()) {
Long vBucket = entry.getKey();
List<MappingDiff.Value<Node>> diffs = entry.getValue();
List<String> disksOut = new ArrayList<String>(); // disks we are going stream from
List<String> disksIn = new ArrayList<String>(); // the endpoints of streams
for (MappingDiff.Value<Node> diff : diffs) {
String diskId = TopologyUtils.extractDiskUUID(diff.get().getName());
switch (diff.getDifferenceType()) {
case ADDED:
disksIn.add(diskId);
break;
case REMOVED:
disksOut.add(diskId);
break;
}
}
// TODO: !!!! This MUST be investigated with love (case: disks of the different sizes) !!!
if (disksIn.size() != disksOut.size())
throw new RuntimeException("Number of disks removed is not equal to added ones");
for (int i = 0; i < disksOut.size(); i++) {
String out = disksOut.get(i);
String in = disksIn.get(i);
Map<Long, String> movementInfo = diskMovementMap.get(out);
if (null == movementInfo) {
movementInfo = new HashMap<Long, String>();
diskMovementMap.put(out, movementInfo);
}
movementInfo.put(vBucket, in);
}
}
}
public int getDisksInvolved() {
return diskMovementMap.size();
}
public int size() {
return diskMovementMap.size();
}
public long getVBucketsNumber(UUID diskId) {
Map<Long, String> buckets = diskMovementMap.get(diskId.toString());
if (null == buckets)
return 0;
return buckets.size();
}
public int getReceiversNumber(UUID diskId) {
Map<Long, String> buckets = diskMovementMap.get(diskId.toString());
if (null == buckets)
return 0;
Set<String> receivers = new HashSet<String>(buckets.values());
return receivers.size();
}
public DiskMovementMap getSlice(List<UUID> disksIds) {
Set<UUID> ids = new HashSet<UUID>(disksIds);
Map<String, Map<Long, String>> slice = new HashMap<String, Map<Long, String>>();
for (Map.Entry<String, Map<Long, String>> entry : diskMovementMap.entrySet()) {
String srcDisk = entry.getKey();
Map<Long, String> dst = entry.getValue();
if (ids.contains(UUID.fromString(srcDisk))) {
slice.put(srcDisk, dst);
}
}
return new DiskMovementMap(slice, true);
}
}