/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.cassandra.streaming; import java.net.InetAddress; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.log4j.Logger; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; class StreamInManager { private static final Logger logger = Logger.getLogger(StreamInManager.class); /* Maintain a stream context per host that is the source of the stream */ public static final Map<InetAddress, List<PendingFile>> ctxBag_ = new Hashtable<InetAddress, List<PendingFile>>(); public static final Map<InetAddress, Map<String, String>> fileLocations_ = new Hashtable<InetAddress, Map<String, String>>(); /* Maintain in this map the status of the streams that need to be sent back to the source */ public static final Map<InetAddress, List<CompletedFileStatus>> streamStatusBag_ = new Hashtable<InetAddress, List<CompletedFileStatus>>(); /* Maintains a callback handler per endpoint to notify the app that a stream from a given endpoint has been handled */ public static final Map<InetAddress, IStreamComplete> streamNotificationHandlers_ = new HashMap<InetAddress, IStreamComplete>(); public static final Multimap<InetAddress, PendingFile> activeStreams = Multimaps.synchronizedMultimap(HashMultimap.<InetAddress, PendingFile>create()); public synchronized static PendingFile getStreamContext(InetAddress key) { List<PendingFile> context = ctxBag_.get(key); if ( context == null ) throw new IllegalStateException("Streaming context has not been set for " + key); PendingFile pendingFile = context.remove(0); if ( context.isEmpty() ) ctxBag_.remove(key); return pendingFile; } public synchronized static String getFileLocation(InetAddress key, String fileName) { Map<String, String> context = fileLocations_.get(key); if ( context == null ){ return null; } return context.get(fileName); } public synchronized static void setFileLocation(InetAddress key, String fileName, String fileLocation) { Map<String, String> context = fileLocations_.get(key); if ( context == null ){ context = new HashMap<String, String>(); fileLocations_.put(key, context); } context.put(fileName, fileLocation); } public synchronized static CompletedFileStatus getStreamStatus(InetAddress key) { List<CompletedFileStatus> status = streamStatusBag_.get(key); if ( status == null ) throw new IllegalStateException("Streaming status has not been set for " + key); CompletedFileStatus streamStatus = status.remove(0); if ( status.isEmpty() ) streamStatusBag_.remove(key); return streamStatus; } /** query method to determine which hosts are streaming to this node. */ public static Set<InetAddress> getSources() { HashSet<InetAddress> set = new HashSet<InetAddress>(); set.addAll(ctxBag_.keySet()); set.addAll(activeStreams.keySet()); return set; } /** query the status of incoming files. */ public static List<PendingFile> getIncomingFiles(InetAddress host) { // avoid returning null. List<PendingFile> list = new ArrayList<PendingFile>(); if (ctxBag_.containsKey(host)) list.addAll(ctxBag_.get(host)); list.addAll(activeStreams.get(host)); return list; } /* * This method helps determine if the StreamCompletionHandler needs * to be invoked for the data being streamed from a source. */ public synchronized static boolean isDone(InetAddress key) { return (ctxBag_.get(key) == null); } public synchronized static IStreamComplete getStreamCompletionHandler(InetAddress key) { return streamNotificationHandlers_.get(key); } public synchronized static void removeStreamCompletionHandler(InetAddress key) { streamNotificationHandlers_.remove(key); } public synchronized static void registerStreamCompletionHandler(InetAddress key, IStreamComplete streamComplete) { streamNotificationHandlers_.put(key, streamComplete); } public synchronized static void addStreamContext(InetAddress key, PendingFile pendingFile, CompletedFileStatus streamStatus) { /* Record the stream context */ List<PendingFile> context = ctxBag_.get(key); if ( context == null ) { context = new ArrayList<PendingFile>(); ctxBag_.put(key, context); } context.add(pendingFile); /* Record the stream status for this stream context */ List<CompletedFileStatus> status = streamStatusBag_.get(key); if ( status == null ) { status = new ArrayList<CompletedFileStatus>(); streamStatusBag_.put(key, status); } status.add( streamStatus ); } }