Adjust checkstyle rules. Make checkstyle fail the build when violations are found. Correct all current checkstyle violations.
This commit is contained in:
@ -21,7 +21,7 @@ package com.iluwatar.caching;
|
||||
* application data. The cache itself is implemented as an internal (Java) data structure. It adopts
|
||||
* a Least-Recently-Used (LRU) strategy for evicting data from itself when its full. The three
|
||||
* strategies are individually tested. The testing of the cache is restricted towards saving and
|
||||
* querying of user accounts from the underlying data store ( {@link DBManager}). The main class (
|
||||
* querying of user accounts from the underlying data store ( {@link DbManager}). The main class (
|
||||
* {@link App} is not aware of the underlying mechanics of the application (i.e. save and query) and
|
||||
* whether the data is coming from the cache or the DB (i.e. separation of concern). The AppManager
|
||||
* ({@link AppManager}) handles the transaction of data to-and-from the underlying data store
|
||||
@ -43,7 +43,7 @@ public class App {
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
AppManager.initDB(false); // VirtualDB (instead of MongoDB) was used in running the JUnit tests
|
||||
AppManager.initDb(false); // VirtualDB (instead of MongoDB) was used in running the JUnit tests
|
||||
// and the App class to avoid Maven compilation errors. Set flag to
|
||||
// true to run the tests with MongoDB (provided that MongoDB is
|
||||
// installed and socket connection is open).
|
||||
|
@ -21,18 +21,21 @@ public class AppManager {
|
||||
* data storage or a simple Java data structure to (temporarily) store the data/objects during
|
||||
* runtime.
|
||||
*/
|
||||
public static void initDB(boolean useMongoDB) {
|
||||
if (useMongoDB) {
|
||||
public static void initDb(boolean useMongoDb) {
|
||||
if (useMongoDb) {
|
||||
try {
|
||||
DBManager.connect();
|
||||
DbManager.connect();
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
DBManager.createVirtualDB();
|
||||
DbManager.createVirtualDb();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize caching policy
|
||||
*/
|
||||
public static void initCachingPolicy(CachingPolicy policy) {
|
||||
cachingPolicy = policy;
|
||||
if (cachingPolicy == CachingPolicy.BEHIND) {
|
||||
@ -50,15 +53,21 @@ public class AppManager {
|
||||
CacheStore.initCapacity(capacity);
|
||||
}
|
||||
|
||||
public static UserAccount find(String userID) {
|
||||
/**
|
||||
* Find user account
|
||||
*/
|
||||
public static UserAccount find(String userId) {
|
||||
if (cachingPolicy == CachingPolicy.THROUGH || cachingPolicy == CachingPolicy.AROUND) {
|
||||
return CacheStore.readThrough(userID);
|
||||
return CacheStore.readThrough(userId);
|
||||
} else if (cachingPolicy == CachingPolicy.BEHIND) {
|
||||
return CacheStore.readThroughWithWriteBackPolicy(userID);
|
||||
return CacheStore.readThroughWithWriteBackPolicy(userId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save user account
|
||||
*/
|
||||
public static void save(UserAccount userAccount) {
|
||||
if (cachingPolicy == CachingPolicy.THROUGH) {
|
||||
CacheStore.writeThrough(userAccount);
|
||||
|
@ -9,73 +9,96 @@ import java.util.ArrayList;
|
||||
*/
|
||||
public class CacheStore {
|
||||
|
||||
static LRUCache cache = null;
|
||||
static LruCache cache = null;
|
||||
|
||||
/**
|
||||
* Init cache capacity
|
||||
*/
|
||||
public static void initCapacity(int capacity) {
|
||||
if (null == cache)
|
||||
cache = new LRUCache(capacity);
|
||||
else
|
||||
if (null == cache) {
|
||||
cache = new LruCache(capacity);
|
||||
} else {
|
||||
cache.setCapacity(capacity);
|
||||
}
|
||||
}
|
||||
|
||||
public static UserAccount readThrough(String userID) {
|
||||
if (cache.contains(userID)) {
|
||||
/**
|
||||
* Get user account using read-through cache
|
||||
*/
|
||||
public static UserAccount readThrough(String userId) {
|
||||
if (cache.contains(userId)) {
|
||||
System.out.println("# Cache Hit!");
|
||||
return cache.get(userID);
|
||||
return cache.get(userId);
|
||||
}
|
||||
System.out.println("# Cache Miss!");
|
||||
UserAccount userAccount = DBManager.readFromDB(userID);
|
||||
cache.set(userID, userAccount);
|
||||
UserAccount userAccount = DbManager.readFromDb(userId);
|
||||
cache.set(userId, userAccount);
|
||||
return userAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user account using write-through cache
|
||||
*/
|
||||
public static void writeThrough(UserAccount userAccount) {
|
||||
if (cache.contains(userAccount.getUserID())) {
|
||||
DBManager.updateDB(userAccount);
|
||||
if (cache.contains(userAccount.getUserId())) {
|
||||
DbManager.updateDb(userAccount);
|
||||
} else {
|
||||
DBManager.writeToDB(userAccount);
|
||||
DbManager.writeToDb(userAccount);
|
||||
}
|
||||
cache.set(userAccount.getUserID(), userAccount);
|
||||
cache.set(userAccount.getUserId(), userAccount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user account using write-around cache
|
||||
*/
|
||||
public static void writeAround(UserAccount userAccount) {
|
||||
if (cache.contains(userAccount.getUserID())) {
|
||||
DBManager.updateDB(userAccount);
|
||||
cache.invalidate(userAccount.getUserID()); // Cache data has been updated -- remove older
|
||||
if (cache.contains(userAccount.getUserId())) {
|
||||
DbManager.updateDb(userAccount);
|
||||
cache.invalidate(userAccount.getUserId()); // Cache data has been updated -- remove older
|
||||
// version from cache.
|
||||
} else {
|
||||
DBManager.writeToDB(userAccount);
|
||||
DbManager.writeToDb(userAccount);
|
||||
}
|
||||
}
|
||||
|
||||
public static UserAccount readThroughWithWriteBackPolicy(String userID) {
|
||||
if (cache.contains(userID)) {
|
||||
/**
|
||||
* Get user account using read-through cache with write-back policy
|
||||
*/
|
||||
public static UserAccount readThroughWithWriteBackPolicy(String userId) {
|
||||
if (cache.contains(userId)) {
|
||||
System.out.println("# Cache Hit!");
|
||||
return cache.get(userID);
|
||||
return cache.get(userId);
|
||||
}
|
||||
System.out.println("# Cache Miss!");
|
||||
UserAccount userAccount = DBManager.readFromDB(userID);
|
||||
UserAccount userAccount = DbManager.readFromDb(userId);
|
||||
if (cache.isFull()) {
|
||||
System.out.println("# Cache is FULL! Writing LRU data to DB...");
|
||||
UserAccount toBeWrittenToDB = cache.getLRUData();
|
||||
DBManager.upsertDB(toBeWrittenToDB);
|
||||
UserAccount toBeWrittenToDb = cache.getLruData();
|
||||
DbManager.upsertDb(toBeWrittenToDb);
|
||||
}
|
||||
cache.set(userID, userAccount);
|
||||
cache.set(userId, userAccount);
|
||||
return userAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user account
|
||||
*/
|
||||
public static void writeBehind(UserAccount userAccount) {
|
||||
if (cache.isFull() && !cache.contains(userAccount.getUserID())) {
|
||||
if (cache.isFull() && !cache.contains(userAccount.getUserId())) {
|
||||
System.out.println("# Cache is FULL! Writing LRU data to DB...");
|
||||
UserAccount toBeWrittenToDB = cache.getLRUData();
|
||||
DBManager.upsertDB(toBeWrittenToDB);
|
||||
UserAccount toBeWrittenToDb = cache.getLruData();
|
||||
DbManager.upsertDb(toBeWrittenToDb);
|
||||
}
|
||||
cache.set(userAccount.getUserID(), userAccount);
|
||||
cache.set(userAccount.getUserId(), userAccount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears cache
|
||||
*/
|
||||
public static void clearCache() {
|
||||
if (null != cache)
|
||||
if (null != cache) {
|
||||
cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -83,14 +106,18 @@ public class CacheStore {
|
||||
*/
|
||||
public static void flushCache() {
|
||||
System.out.println("# flushCache...");
|
||||
if (null == cache)
|
||||
if (null == cache) {
|
||||
return;
|
||||
}
|
||||
ArrayList<UserAccount> listOfUserAccounts = cache.getCacheDataInListForm();
|
||||
for (UserAccount userAccount : listOfUserAccounts) {
|
||||
DBManager.upsertDB(userAccount);
|
||||
DbManager.upsertDb(userAccount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print user accounts
|
||||
*/
|
||||
public static String print() {
|
||||
ArrayList<UserAccount> listOfUserAccounts = cache.getCacheDataInListForm();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
@ -21,7 +21,7 @@ import com.mongodb.client.model.UpdateOptions;
|
||||
* during runtime (createVirtualDB()).</p>
|
||||
*
|
||||
*/
|
||||
public class DBManager {
|
||||
public class DbManager {
|
||||
|
||||
private static MongoClient mongoClient;
|
||||
private static MongoDatabase db;
|
||||
@ -29,21 +29,31 @@ public class DBManager {
|
||||
|
||||
private static HashMap<String, UserAccount> virtualDB;
|
||||
|
||||
public static void createVirtualDB() {
|
||||
/**
|
||||
* Create DB
|
||||
*/
|
||||
public static void createVirtualDb() {
|
||||
useMongoDB = false;
|
||||
virtualDB = new HashMap<String, UserAccount>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to DB
|
||||
*/
|
||||
public static void connect() throws ParseException {
|
||||
useMongoDB = true;
|
||||
mongoClient = new MongoClient();
|
||||
db = mongoClient.getDatabase("test");
|
||||
}
|
||||
|
||||
public static UserAccount readFromDB(String userID) {
|
||||
/**
|
||||
* Read user account from DB
|
||||
*/
|
||||
public static UserAccount readFromDb(String userId) {
|
||||
if (!useMongoDB) {
|
||||
if (virtualDB.containsKey(userID))
|
||||
return virtualDB.get(userID);
|
||||
if (virtualDB.containsKey(userId)) {
|
||||
return virtualDB.get(userId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (null == db) {
|
||||
@ -54,18 +64,22 @@ public class DBManager {
|
||||
}
|
||||
}
|
||||
FindIterable<Document> iterable =
|
||||
db.getCollection("user_accounts").find(new Document("userID", userID));
|
||||
if (iterable == null)
|
||||
db.getCollection("user_accounts").find(new Document("userID", userId));
|
||||
if (iterable == null) {
|
||||
return null;
|
||||
}
|
||||
Document doc = iterable.first();
|
||||
UserAccount userAccount =
|
||||
new UserAccount(userID, doc.getString("userName"), doc.getString("additionalInfo"));
|
||||
new UserAccount(userId, doc.getString("userName"), doc.getString("additionalInfo"));
|
||||
return userAccount;
|
||||
}
|
||||
|
||||
public static void writeToDB(UserAccount userAccount) {
|
||||
/**
|
||||
* Write user account to DB
|
||||
*/
|
||||
public static void writeToDb(UserAccount userAccount) {
|
||||
if (!useMongoDB) {
|
||||
virtualDB.put(userAccount.getUserID(), userAccount);
|
||||
virtualDB.put(userAccount.getUserId(), userAccount);
|
||||
return;
|
||||
}
|
||||
if (null == db) {
|
||||
@ -76,13 +90,16 @@ public class DBManager {
|
||||
}
|
||||
}
|
||||
db.getCollection("user_accounts").insertOne(
|
||||
new Document("userID", userAccount.getUserID()).append("userName",
|
||||
new Document("userID", userAccount.getUserId()).append("userName",
|
||||
userAccount.getUserName()).append("additionalInfo", userAccount.getAdditionalInfo()));
|
||||
}
|
||||
|
||||
public static void updateDB(UserAccount userAccount) {
|
||||
/**
|
||||
* Update DB
|
||||
*/
|
||||
public static void updateDb(UserAccount userAccount) {
|
||||
if (!useMongoDB) {
|
||||
virtualDB.put(userAccount.getUserID(), userAccount);
|
||||
virtualDB.put(userAccount.getUserId(), userAccount);
|
||||
return;
|
||||
}
|
||||
if (null == db) {
|
||||
@ -93,7 +110,7 @@ public class DBManager {
|
||||
}
|
||||
}
|
||||
db.getCollection("user_accounts").updateOne(
|
||||
new Document("userID", userAccount.getUserID()),
|
||||
new Document("userID", userAccount.getUserId()),
|
||||
new Document("$set", new Document("userName", userAccount.getUserName()).append(
|
||||
"additionalInfo", userAccount.getAdditionalInfo())));
|
||||
}
|
||||
@ -102,9 +119,9 @@ public class DBManager {
|
||||
*
|
||||
* Insert data into DB if it does not exist. Else, update it.
|
||||
*/
|
||||
public static void upsertDB(UserAccount userAccount) {
|
||||
public static void upsertDb(UserAccount userAccount) {
|
||||
if (!useMongoDB) {
|
||||
virtualDB.put(userAccount.getUserID(), userAccount);
|
||||
virtualDB.put(userAccount.getUserId(), userAccount);
|
||||
return;
|
||||
}
|
||||
if (null == db) {
|
||||
@ -115,8 +132,8 @@ public class DBManager {
|
||||
}
|
||||
}
|
||||
db.getCollection("user_accounts").updateOne(
|
||||
new Document("userID", userAccount.getUserID()),
|
||||
new Document("$set", new Document("userID", userAccount.getUserID()).append("userName",
|
||||
new Document("userID", userAccount.getUserId()),
|
||||
new Document("$set", new Document("userID", userAccount.getUserId()).append("userName",
|
||||
userAccount.getUserName()).append("additionalInfo", userAccount.getAdditionalInfo())),
|
||||
new UpdateOptions().upsert(true));
|
||||
}
|
@ -12,16 +12,16 @@ import java.util.HashMap;
|
||||
* LRU data is always at the end of the list.
|
||||
*
|
||||
*/
|
||||
public class LRUCache {
|
||||
public class LruCache {
|
||||
|
||||
class Node {
|
||||
String userID;
|
||||
String userId;
|
||||
UserAccount userAccount;
|
||||
Node previous;
|
||||
Node next;
|
||||
|
||||
public Node(String userID, UserAccount userAccount) {
|
||||
this.userID = userID;
|
||||
public Node(String userId, UserAccount userAccount) {
|
||||
this.userId = userId;
|
||||
this.userAccount = userAccount;
|
||||
}
|
||||
}
|
||||
@ -31,13 +31,16 @@ public class LRUCache {
|
||||
Node head = null;
|
||||
Node end = null;
|
||||
|
||||
public LRUCache(int capacity) {
|
||||
public LruCache(int capacity) {
|
||||
this.capacity = capacity;
|
||||
}
|
||||
|
||||
public UserAccount get(String userID) {
|
||||
if (cache.containsKey(userID)) {
|
||||
Node node = cache.get(userID);
|
||||
/**
|
||||
* Get user account
|
||||
*/
|
||||
public UserAccount get(String userId) {
|
||||
if (cache.containsKey(userId)) {
|
||||
Node node = cache.get(userId);
|
||||
remove(node);
|
||||
setHead(node);
|
||||
return node.userAccount;
|
||||
@ -69,52 +72,63 @@ public class LRUCache {
|
||||
public void setHead(Node node) {
|
||||
node.next = head;
|
||||
node.previous = null;
|
||||
if (head != null)
|
||||
if (head != null) {
|
||||
head.previous = node;
|
||||
}
|
||||
head = node;
|
||||
if (end == null)
|
||||
if (end == null) {
|
||||
end = head;
|
||||
}
|
||||
}
|
||||
|
||||
public void set(String userID, UserAccount userAccount) {
|
||||
if (cache.containsKey(userID)) {
|
||||
Node old = cache.get(userID);
|
||||
/**
|
||||
* Set user account
|
||||
*/
|
||||
public void set(String userId, UserAccount userAccount) {
|
||||
if (cache.containsKey(userId)) {
|
||||
Node old = cache.get(userId);
|
||||
old.userAccount = userAccount;
|
||||
remove(old);
|
||||
setHead(old);
|
||||
} else {
|
||||
Node newNode = new Node(userID, userAccount);
|
||||
Node newNode = new Node(userId, userAccount);
|
||||
if (cache.size() >= capacity) {
|
||||
System.out.println("# Cache is FULL! Removing " + end.userID + " from cache...");
|
||||
cache.remove(end.userID); // remove LRU data from cache.
|
||||
System.out.println("# Cache is FULL! Removing " + end.userId + " from cache...");
|
||||
cache.remove(end.userId); // remove LRU data from cache.
|
||||
remove(end);
|
||||
setHead(newNode);
|
||||
} else {
|
||||
setHead(newNode);
|
||||
}
|
||||
cache.put(userID, newNode);
|
||||
cache.put(userId, newNode);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean contains(String userID) {
|
||||
return cache.containsKey(userID);
|
||||
public boolean contains(String userId) {
|
||||
return cache.containsKey(userId);
|
||||
}
|
||||
|
||||
public void invalidate(String userID) {
|
||||
System.out.println("# " + userID + " has been updated! Removing older version from cache...");
|
||||
Node toBeRemoved = cache.get(userID);
|
||||
/**
|
||||
* Invalidate cache for user
|
||||
*/
|
||||
public void invalidate(String userId) {
|
||||
System.out.println("# " + userId + " has been updated! Removing older version from cache...");
|
||||
Node toBeRemoved = cache.get(userId);
|
||||
remove(toBeRemoved);
|
||||
cache.remove(userID);
|
||||
cache.remove(userId);
|
||||
}
|
||||
|
||||
public boolean isFull() {
|
||||
return cache.size() >= capacity;
|
||||
}
|
||||
|
||||
public UserAccount getLRUData() {
|
||||
public UserAccount getLruData() {
|
||||
return end.userAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear cache
|
||||
*/
|
||||
public void clear() {
|
||||
head = null;
|
||||
end = null;
|
||||
@ -135,6 +149,9 @@ public class LRUCache {
|
||||
return listOfCacheData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cache capacity
|
||||
*/
|
||||
public void setCapacity(int newCapacity) {
|
||||
if (capacity > newCapacity) {
|
||||
clear(); // Behavior can be modified to accommodate for decrease in cache size. For now, we'll
|
@ -6,22 +6,25 @@ package com.iluwatar.caching;
|
||||
*
|
||||
*/
|
||||
public class UserAccount {
|
||||
private String userID;
|
||||
private String userId;
|
||||
private String userName;
|
||||
private String additionalInfo;
|
||||
|
||||
public UserAccount(String userID, String userName, String additionalInfo) {
|
||||
this.userID = userID;
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public UserAccount(String userId, String userName, String additionalInfo) {
|
||||
this.userId = userId;
|
||||
this.userName = userName;
|
||||
this.additionalInfo = additionalInfo;
|
||||
}
|
||||
|
||||
public String getUserID() {
|
||||
return userID;
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserID(String userID) {
|
||||
this.userID = userID;
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
@ -42,6 +45,6 @@ public class UserAccount {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return userID + ", " + userName + ", " + additionalInfo;
|
||||
return userId + ", " + userName + ", " + additionalInfo;
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ public class AppTest {
|
||||
*/
|
||||
@Before
|
||||
public void setUp() {
|
||||
AppManager.initDB(false); // VirtualDB (instead of MongoDB) was used in running the JUnit tests
|
||||
AppManager.initDb(false); // VirtualDB (instead of MongoDB) was used in running the JUnit tests
|
||||
// to avoid Maven compilation errors. Set flag to true to run the
|
||||
// tests with MongoDB (provided that MongoDB is installed and socket
|
||||
// connection is open).
|
||||
|
Reference in New Issue
Block a user