/*
* Copyright 2011 Future Systems, 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.krakenapps.confdb.file;
import java.lang.ref.WeakReference;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.krakenapps.confdb.Config;
import org.krakenapps.confdb.ConfigCache;
public class FileConfigCache implements ConfigCache {
// collection name to id maping cache
private ConcurrentMap<String, Integer> nameMap;
// collection id to config cache map
private ConcurrentMap<Integer, WeakReference<ConcurrentMap<ConfigKey, Config>>> cache;
private FileConfigDatabase db;
public FileConfigCache(FileConfigDatabase db) {
this.db = db;
this.nameMap = new ConcurrentHashMap<String, Integer>();
this.cache = new ConcurrentHashMap<Integer, WeakReference<ConcurrentMap<ConfigKey, Config>>>();
}
/**
* CAUTION: you should NOT MODIFY config object. mutable for iterator
* performance
*/
@Override
public Config findEntry(String colName, int manifestId, int docId, long rev) {
Integer colId = getCollectionId(colName);
if (colId == null)
return null;
WeakReference<ConcurrentMap<ConfigKey, Config>> ref = cache.get(colId);
if (ref == null)
return null;
ConcurrentMap<ConfigKey, Config> map = ref.get();
if (map == null)
return null;
Config c = map.get(new ConfigKey(manifestId, docId, rev));
if (c != null) {
return c;
}
return null;
}
@Override
public void putEntry(String colName, int manifestId, Config c) {
Integer colId = getCollectionId(colName);
if (colId == null)
return;
WeakReference<ConcurrentMap<ConfigKey, Config>> ref = cache.get(colId);
ConcurrentMap<ConfigKey, Config> configCache = null;
if (ref == null) {
configCache = createCollectionCache(colId);
} else {
configCache = ref.get();
if (configCache == null)
configCache = createCollectionCache(colId);
}
configCache.put(new ConfigKey(manifestId, c.getId(), c.getRevision()), c);
}
private Integer getCollectionId(String colName) {
Integer colId = nameMap.get(colName);
if (colId == null) {
colId = db.getCollectionId(colName);
if (colId != null)
nameMap.put(colName, colId);
}
return colId;
}
private ConcurrentMap<ConfigKey, Config> createCollectionCache(int colId) {
ConcurrentMap<ConfigKey, Config> configCache = new ConcurrentHashMap<FileConfigCache.ConfigKey, Config>();
WeakReference<ConcurrentMap<ConfigKey, Config>> ref = new WeakReference<ConcurrentMap<ConfigKey, Config>>(configCache);
cache.put(colId, ref);
return configCache;
}
private static class ConfigKey {
private int manifestId;
private int id;
private long rev;
public ConfigKey(int manifestId, int id, long rev) {
this.manifestId = manifestId;
this.id = id;
this.rev = rev;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + manifestId;
result = prime * result + (int) (rev ^ (rev >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ConfigKey other = (ConfigKey) obj;
if (id != other.id)
return false;
if (manifestId != other.manifestId)
return false;
if (rev != other.rev)
return false;
return true;
}
}
}