/**
* Copyright (c) Codice Foundation
* <p/>
* This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or any later version.
* <p/>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. A copy of the GNU Lesser General Public License
* is distributed along with this program and can be found at
* <http://www.gnu.org/licenses/lgpl.html>.
*/
package org.codice.ddf.persistence.attributes.internal;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.commons.lang.StringUtils;
import org.codice.ddf.persistence.PersistenceException;
import org.codice.ddf.persistence.PersistentItem;
import org.codice.ddf.persistence.PersistentStore;
import org.codice.ddf.persistence.attributes.AttributesStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AttributesStoreImpl implements AttributesStore {
private static final Logger LOGGER = LoggerFactory.getLogger(AttributesStoreImpl.class);
private PersistentStore persistentStore;
private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private static final String EMPTY_USERNAME_ERROR = "Empty username specified";
private static final long NO_DATA_LIMIT = -1L;
public AttributesStoreImpl(PersistentStore persistentStore) {
this.persistentStore = persistentStore;
}
@Override
public long getCurrentDataUsageByUser(final String username) throws PersistenceException {
long currentDataUsage = 0L;
if (StringUtils.isEmpty(username)) {
throw new PersistenceException(EMPTY_USERNAME_ERROR);
}
try {
readWriteLock.readLock()
.lock();
currentDataUsage = getCurrentDataUsageByUserNoLock(username);
} finally {
readWriteLock.readLock()
.unlock();
}
return currentDataUsage;
}
@Override
public long getDataLimitByUser(final String username) throws PersistenceException {
long dataLimit = NO_DATA_LIMIT;
if (StringUtils.isEmpty(username)) {
throw new PersistenceException(EMPTY_USERNAME_ERROR);
}
try {
readWriteLock.readLock()
.lock();
dataLimit = getDataLimitByUserNoLock(username);
} finally {
readWriteLock.readLock()
.unlock();
}
return dataLimit;
}
@Override
public void updateUserDataUsage(final String username, final long newDataUsage)
throws PersistenceException {
if (StringUtils.isEmpty(username)) {
throw new PersistenceException(EMPTY_USERNAME_ERROR);
}
if (newDataUsage > 0) {
try {
readWriteLock.writeLock()
.lock();
long dataUsage = getCurrentDataUsageByUserNoLock(username);
dataUsage += newDataUsage;
LOGGER.debug("Updating user {} data usage to {}", username, dataUsage);
persistentStore.add(PersistentStore.USER_ATTRIBUTE_TYPE, toPersistentItem(username,
dataUsage,
getDataLimitByUser(username)));
} finally {
readWriteLock.writeLock()
.unlock();
}
}
}
@Override
public void setDataUsage(final String username, final long dataUsage)
throws PersistenceException {
if (StringUtils.isEmpty(username)) {
throw new PersistenceException(EMPTY_USERNAME_ERROR);
}
if (dataUsage >= 0) {
try {
readWriteLock.writeLock()
.lock();
LOGGER.debug("Updating user {} data usage to {}", username, dataUsage);
persistentStore.add(PersistentStore.USER_ATTRIBUTE_TYPE,
toPersistentItem(username, dataUsage, NO_DATA_LIMIT));
} finally {
readWriteLock.writeLock()
.unlock();
}
}
}
@Override
public void setDataLimit(final String username, final long dataLimit)
throws PersistenceException {
if (StringUtils.isEmpty(username)) {
throw new PersistenceException(EMPTY_USERNAME_ERROR);
}
if (dataLimit >= NO_DATA_LIMIT) {
try {
readWriteLock.writeLock()
.lock();
LOGGER.debug("Updating user {} data limit to {}", username, dataLimit);
persistentStore.add(PersistentStore.USER_ATTRIBUTE_TYPE,
toPersistentItem(username, getCurrentDataUsageByUser(username), dataLimit));
} finally {
readWriteLock.writeLock()
.unlock();
}
}
}
@Override
public List<Map<String, Object>> getAllUsers() throws PersistenceException {
List<Map<String, Object>> userMap;
try {
readWriteLock.readLock()
.lock();
userMap = persistentStore.get(PersistentStore.USER_ATTRIBUTE_TYPE);
} finally {
readWriteLock.readLock()
.unlock();
}
return userMap;
}
@Override
public void resetUserDataUsages() throws PersistenceException {
List<Map<String, Object>> users = getAllUsers();
for (Map<String, Object> user : users) {
String username = (String) user.get(AttributesStore.USER_KEY + "_txt");
long dataLimit = (long) user.get(AttributesStore.DATA_USAGE_LIMIT_KEY + "_lng");
try {
readWriteLock.writeLock()
.lock();
LOGGER.debug("Resetting Data usage for user : {}", username);
persistentStore.add(PersistentStore.USER_ATTRIBUTE_TYPE,
toPersistentItem(username, 0L, dataLimit));
} finally {
readWriteLock.writeLock()
.unlock();
}
}
}
private PersistentItem toPersistentItem(final String username, final long dataUsage,
final long dataLimit) throws PersistenceException {
// add to usage and store
PersistentItem item = new PersistentItem();
item.addIdProperty(username);
item.addProperty(USER_KEY, username);
item.addProperty(DATA_USAGE_KEY, dataUsage);
item.addProperty(DATA_USAGE_LIMIT_KEY, dataLimit);
LOGGER.debug("Created PersistentItem : User {} Usage {} Limit {}",
username,
dataUsage,
dataLimit);
return item;
}
private long getCurrentDataUsageByUserNoLock(final String username)
throws PersistenceException {
long currentDataUsage = 0L;
List<Map<String, Object>> attributesList;
attributesList = persistentStore.get(PersistentStore.USER_ATTRIBUTE_TYPE, String.format(
"%s = '%s'",
USER_KEY,
username));
if (attributesList != null && attributesList.size() == 1) {
Map<String, Object> attributes = PersistentItem.stripSuffixes(attributesList.get(0));
currentDataUsage = (long) attributes.get(DATA_USAGE_KEY);
LOGGER.debug("User {} data usage {} ", username, String.valueOf(currentDataUsage));
}
return currentDataUsage;
}
private long getDataLimitByUserNoLock(final String username) throws PersistenceException {
long dataLimit = NO_DATA_LIMIT;
List<Map<String, Object>> attributesList;
attributesList = persistentStore.get(PersistentStore.USER_ATTRIBUTE_TYPE,
String.format("%s = '%s'", USER_KEY, username));
if (attributesList != null && attributesList.size() == 1) {
Map<String, Object> attributes = PersistentItem.stripSuffixes(attributesList.get(0));
dataLimit = (long) attributes.get(DATA_USAGE_LIMIT_KEY);
LOGGER.debug("User {} data limit {} ", username, String.valueOf(dataLimit));
}
return dataLimit;
}
}