/*
* 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.db;
import org.stem.domain.ArrayBalancer;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
public class DataTracker {
ConcurrentMap<Long, AtomicLong> totalCountMap = new ConcurrentHashMap<Long, AtomicLong>();
ConcurrentMap<Long, AtomicLong> liveCountMap = new ConcurrentHashMap<Long, AtomicLong>();
ConcurrentMap<Long, AtomicLong> totalSizeMap = new ConcurrentHashMap<Long, AtomicLong>();
ConcurrentMap<Long, AtomicLong> liveSizeMap = new ConcurrentHashMap<Long, AtomicLong>();
ConcurrentMap<Integer, AtomicLong> deletesPerFFCountMap = new ConcurrentHashMap<Integer, AtomicLong>();
ConcurrentMap<Integer, AtomicLong> deletesPerFFSizeMap = new ConcurrentHashMap<Integer, AtomicLong>();
// Total number of blobs
AtomicLong totalCount = new AtomicLong(0);
// Number of non-deleted blobs
AtomicLong liveCount = new AtomicLong(0);
// Number of FULL fat files
AtomicLong fullFatFileCount = new AtomicLong(0);
// number of BLANK fat files
AtomicLong blankFatFileCount = new AtomicLong(0);
AtomicLong fatFileCount = new AtomicLong(0);
// Total size of all blobs stored in (deleted + live)
AtomicLong totalSizeInBytes = new AtomicLong(0);
// Size of non-deleted blobs
AtomicLong liveSizeInBytes = new AtomicLong(0);
// Total size of full fat files
AtomicLong fullFatFileSizeInBytes = new AtomicLong(0);
AtomicLong allocatedSizeInBytes = new AtomicLong(0);
AtomicLong deletesCount = new AtomicLong(0);
AtomicLong deletesSizeInBytes = new AtomicLong(0);
private ArrayBalancer dht; // TODO: share instance by making it static
public DataTracker(int vBuckets) {
dht = new ArrayBalancer(vBuckets);
}
public void count(FatFileIndex index) {
for (FatFileIndex.Entry entry : index.getEntries()) {
count(entry);
}
}
public void count(FatFileIndex.Entry entry) {
count(entry.key, entry.length, entry.isLive());
}
public void count(Blob.Header header) {
count(header.key, header.length, header.isLive());
}
public long getTotalBlobs() {
return totalCount.get();
}
public long getLiveBlobs() {
return liveCount.get();
}
public long getTotalSizeInBytes() {
return totalSizeInBytes.get();
}
public long getLiveSizeInBytes() {
return liveSizeInBytes.get();
}
public long getAllocatedSizeInBytes() {
return allocatedSizeInBytes.get();
}
public long getDeletesSizeInBytes() {
return deletesSizeInBytes.get();
}
public long getDeletesSizeInBytes(int ff) {
AtomicLong ref = deletesPerFFSizeMap.get(ff);
if (null == ref)
return 0;
return ref.get();
}
public long getDeletesCount() {
return deletesCount.get();
}
public long getDeletesCount(int ff) {
AtomicLong ref = deletesPerFFCountMap.get(ff);
if (null == ref)
return 0;
return ref.get();
}
public Long getVBucket(byte[] key) {
return dht.getToken(key).longValue();
}
public void count(byte[] keyBytes, long size, boolean live) {
Long vBucket = dht.getToken(keyBytes).longValue();
initCounters(vBucket);
totalCountMap.get(vBucket).incrementAndGet();
totalSizeMap.get(vBucket).addAndGet(size);
totalCount.incrementAndGet();
totalSizeInBytes.addAndGet(size);
if (live) {
liveCountMap.get(vBucket).incrementAndGet();
liveSizeMap.get(vBucket).addAndGet(size);
liveCount.incrementAndGet();
liveSizeInBytes.addAndGet(size);
}
}
private void initCounters(long vBucket) {
totalCountMap.putIfAbsent(vBucket, new AtomicLong(0));
totalSizeMap.putIfAbsent(vBucket, new AtomicLong(0));
liveCountMap.putIfAbsent(vBucket, new AtomicLong(0));
liveSizeMap.putIfAbsent(vBucket, new AtomicLong(0));
}
public void discount(byte[] keyBytes, long size, int ff) {
Long vBucket = dht.getToken(keyBytes).longValue();
initCounters(vBucket);
liveCountMap.get(vBucket).decrementAndGet();
liveSizeMap.get(vBucket).addAndGet(-size);
liveCount.decrementAndGet();
liveSizeInBytes.addAndGet(-size);
deletesPerFFCountMap.putIfAbsent(ff, new AtomicLong(0));
deletesPerFFSizeMap.putIfAbsent(ff, new AtomicLong(0));
deletesPerFFCountMap.get(ff).incrementAndGet();
deletesPerFFSizeMap.get(ff).addAndGet(size);
deletesCount.incrementAndGet();
deletesSizeInBytes.addAndGet(size);
}
public void remove(byte[] keyBytes, long size) {
Long vBucket = dht.getToken(keyBytes).longValue();
initCounters(vBucket);
totalCountMap.get(vBucket).decrementAndGet();
totalSizeMap.get(vBucket).addAndGet(-size);
totalCount.decrementAndGet();
totalSizeInBytes.addAndGet(-size);
liveCountMap.get(vBucket).decrementAndGet();
liveSizeMap.get(vBucket).addAndGet(-size);
liveCount.decrementAndGet();
liveSizeInBytes.addAndGet(-size);
}
public void removeDeletes(byte[] keyBytes, long size, int ff) {
Long vBucket = dht.getToken(keyBytes).longValue();
initCounters(vBucket);
deletesPerFFCountMap.putIfAbsent(ff, new AtomicLong(0));
deletesPerFFSizeMap.putIfAbsent(ff, new AtomicLong(0));
deletesPerFFCountMap.get(ff).decrementAndGet();
deletesPerFFSizeMap.get(ff).addAndGet(-size);
deletesCount.decrementAndGet();
deletesSizeInBytes.addAndGet(-size);
}
public void incFullFatFiles(long size) {
fullFatFileCount.incrementAndGet();
fullFatFileSizeInBytes.addAndGet(size);
fatFileCount.incrementAndGet();
allocatedSizeInBytes.addAndGet(size);
}
public void incBlankFatFiles(long size) {
fatFileCount.incrementAndGet();
blankFatFileCount.incrementAndGet();
allocatedSizeInBytes.addAndGet(size);
}
public void turnIntoBlank(long size) {
fullFatFileCount.decrementAndGet();
fullFatFileSizeInBytes.addAndGet(-size);
blankFatFileCount.incrementAndGet();
}
public void turnIntoFull(long size) {
fullFatFileCount.incrementAndGet();
fullFatFileSizeInBytes.addAndGet(size);
blankFatFileCount.decrementAndGet();
}
public void turnIntoActive() {
blankFatFileCount.decrementAndGet();
}
public void setActiveFatFile(long size) {
fatFileCount.incrementAndGet();
allocatedSizeInBytes.addAndGet(size);
}
public long getBlankFatFileCount() {
return blankFatFileCount.get();
}
public long getFullFatFileCount() {
return fullFatFileCount.get();
}
public long getFatFileCount() {
return fatFileCount.get();
}
public long getLiveBucketSize(long vBucket) {
AtomicLong atomic = liveSizeMap.get(vBucket);
if (null == atomic)
return 0;
return atomic.get();
}
}