package org.apache.blur.store.buffer;
/**
* 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.
*/
import static org.apache.blur.metrics.MetricsConstants.INTERNAL_BUFFERS;
import static org.apache.blur.metrics.MetricsConstants.LOST;
import static org.apache.blur.metrics.MetricsConstants.LUCENE;
import static org.apache.blur.metrics.MetricsConstants.ORG_APACHE_BLUR;
import static org.apache.blur.metrics.MetricsConstants.SIZE_ALLOCATED;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import org.apache.blur.log.Log;
import org.apache.blur.log.LogFactory;
import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Meter;
import com.yammer.metrics.core.MetricName;
public class BufferStore implements Store {
private static final Log LOG = LogFactory.getLog(BufferStore.class);
private static final Store EMPTY = new Store() {
private final Meter _emptyCreated;
private final Meter _emptyLost;
{
_emptyCreated = Metrics.newMeter(new MetricName(ORG_APACHE_BLUR, LUCENE, "Not Configured " + SIZE_ALLOCATED,
INTERNAL_BUFFERS), INTERNAL_BUFFERS, TimeUnit.SECONDS);
_emptyLost = Metrics.newMeter(
new MetricName(ORG_APACHE_BLUR, LUCENE, "Not Configured " + LOST, INTERNAL_BUFFERS), INTERNAL_BUFFERS,
TimeUnit.SECONDS);
}
@Override
public byte[] takeBuffer(int bufferSize) {
_emptyCreated.mark();
return new byte[bufferSize];
}
@Override
public void putBuffer(byte[] buffer) {
_emptyLost.mark();
}
};
private final static ConcurrentMap<Integer, BufferStore> _bufferStores = new ConcurrentHashMap<Integer, BufferStore>();
private final BlockingQueue<byte[]> _buffers;
private final Meter _created;
private final Meter _lost;
private final int _bufferSize;
public synchronized static void initNewBuffer(int bufferSize, long totalAmount) {
if (totalAmount == 0) {
return;
}
BufferStore bufferStore = _bufferStores.get(bufferSize);
if (bufferStore == null) {
long count = totalAmount / bufferSize;
if (count > Integer.MAX_VALUE) {
count = Integer.MAX_VALUE;
}
BufferStore store = new BufferStore(bufferSize, (int) count);
_bufferStores.put(bufferSize, store);
} else {
LOG.warn("Buffer store for size [{0}] already setup.", bufferSize);
}
}
private BufferStore(int bufferSize, int count) {
_bufferSize = bufferSize;
_created = Metrics.newMeter(new MetricName(ORG_APACHE_BLUR, LUCENE, bufferSize + " " + SIZE_ALLOCATED,
INTERNAL_BUFFERS), INTERNAL_BUFFERS, TimeUnit.SECONDS);
_lost = Metrics.newMeter(new MetricName(ORG_APACHE_BLUR, LUCENE, bufferSize + " " + LOST, INTERNAL_BUFFERS),
INTERNAL_BUFFERS, TimeUnit.SECONDS);
_buffers = setupBuffers(bufferSize, count, _created);
}
private static BlockingQueue<byte[]> setupBuffers(int bufferSize, int count, Meter meter) {
BlockingQueue<byte[]> queue = new ArrayBlockingQueue<byte[]>(count);
for (int i = 0; i < count; i++) {
meter.mark();
queue.add(new byte[bufferSize]);
}
return queue;
}
public static Store instance(int bufferSize) {
BufferStore bufferStore = _bufferStores.get(bufferSize);
if (bufferStore == null) {
return EMPTY;
}
return bufferStore;
}
@Override
public byte[] takeBuffer(int bufferSize) {
if (bufferSize != _bufferSize) {
throw new RuntimeException("Buffer with length [" + bufferSize + "] does not match buffer size of ["
+ _bufferSize + "]");
}
return newBuffer(_buffers.poll());
}
@Override
public void putBuffer(byte[] buffer) {
if (buffer == null) {
return;
}
if (buffer.length != _bufferSize) {
throw new RuntimeException("Buffer with length [" + buffer.length + "] does not match buffer size of ["
+ _bufferSize + "]");
}
checkReturn(_buffers.offer(buffer));
}
private void checkReturn(boolean offer) {
if (!offer) {
_lost.mark();
}
}
private byte[] newBuffer(byte[] buf) {
if (buf != null) {
return buf;
}
_created.mark();
return new byte[_bufferSize];
}
}