/*
* Copyright 2014-2016 CyberVision, Inc.
*
* 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.kaaproject.kaa.client.logging.memory;
import org.kaaproject.kaa.client.logging.LogRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MemBucket {
private static final Logger LOG = LoggerFactory.getLogger(MemBucket.class);
protected final int id;
protected final long maxSize;
protected final int maxRecordCount;
private final List<LogRecord> records;
protected long size;
private MemBucketState state;
/**
* All-args constructor.
*/
public MemBucket(int id, long maxSize, int maxRecordCount) {
super();
this.id = id;
this.maxSize = maxSize;
this.maxRecordCount = maxRecordCount;
this.records = new ArrayList<LogRecord>();
this.state = MemBucketState.FREE;
}
public int getId() {
return id;
}
public long getSize() {
return size;
}
public int getCount() {
return records.size();
}
public List<LogRecord> getRecords() {
return records;
}
public MemBucketState getState() {
return state;
}
public void setState(MemBucketState state) {
this.state = state;
}
/**
* Adds a record to a bucket.
*
* @param record record
* @return true if record is added otherwise false
*/
public boolean addRecord(LogRecord record) {
if (size + record.getSize() > maxSize) {
LOG.trace("No space left in bucket. Current size: {}, record size: {}, max size: {}",
size, record.getSize(), maxSize);
return false;
}
if (getCount() + 1 > maxRecordCount) {
LOG.trace("No space left in bucket. Current count: {}, max count: {}", getCount(),
maxRecordCount);
return false;
}
records.add(record);
size += record.getSize();
return true;
}
/**
* Shrinks current bucket to the newSize.
*
* @param newSize expected max size of a bucket inclusively
* @param newCount the new count
* @return removed from the bucket records
*/
public List<LogRecord> shrinkToSize(long newSize, int newCount) {
LOG.trace("Shrinking {} bucket to the new size: [{}] and count [{}]", this, newSize, newCount);
if (newSize < 0 || newCount < 0) {
throw new IllegalArgumentException("New size and count values must be non-negative");
}
if (newSize >= size && newCount >= getCount()) {
return Collections.emptyList();
}
List<LogRecord> overSize = new ArrayList<>();
int lastIndex = records.size() - 1;
while ((size > newSize || getCount() > newCount) && lastIndex > 0) {
LogRecord curRecord = records.remove(lastIndex--);
overSize.add(curRecord);
size -= curRecord.getSize();
}
LOG.trace("Shrink over-sized elements: [{}]. New bucket size: [{}] and count [{}]",
overSize.size(), size, getCount());
return overSize;
}
@Override
public String toString() {
return "MemBucket{"
+ "id=" + id
+ ", maxSize=" + maxSize
+ ", maxRecordCount=" + maxRecordCount
+ ", records count=" + records.size()
+ ", size=" + size
+ ", state=" + state
+ '}';
}
public static enum MemBucketState {
FREE, FULL, PENDING
}
}