/** * 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.hadoop.io.compress; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.util.ReflectionUtils; /** * A global compressor/decompressor pool used to save and reuse * (possibly native) compression/decompression codecs. */ public class CodecPool { private static final Log LOG = LogFactory.getLog(CodecPool.class); /** * A global compressor pool used to save the expensive * construction/destruction of (possibly native) decompression codecs. */ private static final Map, List> compressorPool = new HashMap, List>(); /** * A global decompressor pool used to save the expensive * construction/destruction of (possibly native) decompression codecs. */ private static final Map, List> decompressorPool = new HashMap, List>(); private static T borrow(Map, List> pool, Class codecClass) { T codec = null; // Check if an appropriate codec is available synchronized (pool) { if (pool.containsKey(codecClass)) { List codecList = pool.get(codecClass); if (codecList != null) { synchronized (codecList) { if (!codecList.isEmpty()) { codec = codecList.remove(codecList.size()-1); } } } } } return codec; } private static void payback(Map, List> pool, T codec) { if (codec != null) { Class codecClass = ReflectionUtils.getClass(codec); synchronized (pool) { if (!pool.containsKey(codecClass)) { pool.put(codecClass, new ArrayList()); } List codecList = pool.get(codecClass); synchronized (codecList) { codecList.add(codec); } } } } /** * Get a {@link Compressor} for the given {@link CompressionCodec} from the * pool or a new one. * * @param codec the CompressionCodec for which to get the * Compressor * @return Compressor for the given * CompressionCodec from the pool or a new one */ public static Compressor getCompressor(CompressionCodec codec) { Compressor compressor = borrow(compressorPool, codec.getCompressorType()); if (compressor == null) { compressor = codec.createCompressor(); LOG.info("Got brand-new compressor"); } else { LOG.debug("Got recycled compressor"); } return compressor; } /** * Get a {@link Decompressor} for the given {@link CompressionCodec} from the * pool or a new one. * * @param codec the CompressionCodec for which to get the * Decompressor * @return Decompressor for the given * CompressionCodec the pool or a new one */ public static Decompressor getDecompressor(CompressionCodec codec) { Decompressor decompressor = borrow(decompressorPool, codec.getDecompressorType()); if (decompressor == null) { decompressor = codec.createDecompressor(); LOG.info("Got brand-new decompressor"); } else { LOG.debug("Got recycled decompressor"); } return decompressor; } /** * Return the {@link Compressor} to the pool. * * @param compressor the Compressor to be returned to the pool */ public static void returnCompressor(Compressor compressor) { if (compressor == null) { return; } compressor.reset(); payback(compressorPool, compressor); } /** * Return the {@link Decompressor} to the pool. * * @param decompressor the Decompressor to be returned to the * pool */ public static void returnDecompressor(Decompressor decompressor) { if (decompressor == null) { return; } decompressor.reset(); payback(decompressorPool, decompressor); } }