/* * 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.domain; import com.twitter.crunch.*; import org.stem.streaming.BucketStreamingPart; import org.stem.streaming.DiskMovement; import org.stem.streaming.DiskMovementMap; import org.stem.streaming.StreamSession; import org.stem.utils.TopologyUtils; import java.util.*; public class Topology { private Node crunchTopology; private Map<Long, List<Node>> CRUSHMap; private Map<Long, List<MappingDiff.Value<Node>>> mappingDiff = null; private SimpleCRUSHMapping mappingFunction; private Map<UUID, StorageNode> disksMap = new HashMap<UUID, StorageNode>(); private Map<String, StorageNode> storagesMap = new HashMap<String, StorageNode>(); public Collection<StorageNode> getStorages() { return storagesMap.values(); } public Map<Long, List<Node>> getCRUSHMap() { return CRUSHMap; } public Map<UUID, StorageNode> getDisksMap() { return disksMap; } public Topology(String name, int rf) { crunchTopology = TopologyUtils.createSingleDCCluster(name); PlacementRules rules = new RackIsolationPlacementRules(); mappingFunction = new SimpleCRUSHMapping(rf, rules); } public boolean storageExists(StorageNode storageNode) { return null != storagesMap.get(storageNode.getEndpoint()); } public boolean storageExists(String endpoint) { return null != storagesMap.get(endpoint); } // TODO: What should we do when storage going down? public void addStorage(StorageNode storageNode) { Node storage = TopologyUtils.createStorage(storageNode.getEndpoint(), storageNode.getDiskIds()); Node rack = TopologyUtils.createSingleStorageRack(storage); TopologyUtils.addChildren(rack, getDC()); for (String diskId : storageNode.getDiskIds()) { disksMap.put(UUID.fromString(diskId), storageNode); } storagesMap.put(storageNode.getEndpoint(), storageNode); } private Node getDC() { return crunchTopology.findChildren(StorageSystemTypes.DATA_CENTER).get(0); } public void computeMappings(int vBuckets) { List<Long> vBucketsIds = TopologyUtils.generateVBucketsIds(vBuckets); Map<Long, List<Node>> newMapping = mappingFunction.computeMapping(vBucketsIds, crunchTopology); if (null != this.CRUSHMap) { mappingDiff = MappingDiff.calculateDiff(CRUSHMap, newMapping); } CRUSHMap = newMapping; } public List<StreamSession> computeStreamingSessions() // TODO: synchronized ? { List<StreamSession> sessions = new ArrayList<StreamSession>(); if (null == mappingDiff) return sessions; DiskMovementMap diskMovementMap = new DiskMovementMap(mappingDiff); // Generate session for (StorageNode outStorageNode : getStorages()) { DiskMovementMap slice = diskMovementMap.getSlice(outStorageNode.getDiskUUIDs()); if (0 == slice.size()) { continue; } Map<UUID, DiskMovement> movements = new HashMap<UUID, DiskMovement>(); for (Map.Entry<String, Map<Long, String>> entry : slice.getMap().entrySet()) { //Map<Long, BucketStreamingPart> inBucketParts = new HashMap<Long, BucketStreamingPart>(); UUID outDisk = UUID.fromString(entry.getKey()); DiskMovement diskMovement = new DiskMovement(outDisk); Map<Long, String> in = entry.getValue(); for (Map.Entry<Long, String> entry2 : in.entrySet()) { Long vBucket = entry2.getKey(); UUID inDisk = UUID.fromString(entry2.getValue()); // TODO: null check StorageNode inStorageNode = disksMap.get(inDisk); // TODO: null check BucketStreamingPart part = new BucketStreamingPart(vBucket, inStorageNode.getEndpoint(), inDisk); diskMovement.put(vBucket, part); } movements.put(outDisk, diskMovement); } StreamSession outgoingSession = new StreamSession(outStorageNode.getEndpoint(), movements); sessions.add(outgoingSession); } return sessions; } public StorageNode getStorage(String endpoint) { return storagesMap.get(endpoint); } }