Skip to content

Cache

Configure Memory Cache with System Eviction Policy

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Employee {
    String id;
    String name;
    Employee(String id, String name) {
        this.id = id;
        this.name = name;
    }
}
Employee value = null;
int maxSize = 5;//Max number of entries
MemoryCache<String, Employee>  cache = new MemoryCache<>(context, maxSize);
cache.clearOnMemoryError().build();

cache.put("001", new Employee("001", "Peggy Smith"));
cache.put("002", new Employee("002", "James Cole"));
cache.put("003", new Employee("003", "John King"));
cache.put("004", new Employee("004", "Jim Kelly"));
cache.put("005", new Employee("005", "Mary Sheep"));

// Cache full at this point since max entries limit reached
value = cache.get("005");//updates entry use time, LRU policy
assertNotNull(value);
value = cache.get("001");//updates entry use time, LRU policy
assertNotNull(value);

// Adding this entry should result in eviction of one LRU item
cache.put("006", new Employee("006", "Mona Lew"));
value = cache.get("006");
assertNotNull(value);

// Now "002" should have been evicted but not "001" since it was used once
value = cache.get("002");
assertNull(value);
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
internal inner class Employee(var id: String, var name: String)

var value: Employee? = null
val maxSize = 5//Max number of entries
val cache = MemoryCache<String, Employee>(context, maxSize)
cache.clearOnMemoryError().build()

cache.put("001", Employee("001", "Peggy Smith"))
cache.put("002", Employee("002", "James Cole"))
cache.put("003", Employee("003", "John King"))
cache.put("004", Employee("004", "Jim Kelly"))
cache.put("005", Employee("005", "Mary Sheep"))

// Cache full at this point since max entries limit reached
value = cache.get("005")//updates entry use time, LRU policy
assertNotNull(value)
value = cache.get("001")//updates entry use time, LRU policy
assertNotNull(value)

// Adding this entry should result in eviction of one LRU item
cache.put("006", Employee("006", "Mona Lew"))
value = cache.get("006")
assertNotNull(value)

// Now "002" should have been evicted but not "001" since it was used once
value = cache.get("002")
assertNull(value)

Configure Memory Cache with Cost Factor Based Eviction Policy

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
class Employee {
    String id;
    String name;
    Employee(String id, String name) {
        this.id = id;
        this.name = name;
    }
}
int maxSize = 5;//total cache capacity by size is 5
MemoryCache<String, Employee> cache = new MemoryCache<>(context, maxSize);
cache.maxCost(35d);//total cache capacity by cost of entries
cache.clearOnMemoryError().addCostFactor(new CacheCostFactor<String>() {
    public List<String> onExceedMaxCost(List<String> existingKeys) {
        ArrayList<String> removeList = new ArrayList<>();
        int size = existingKeys.size();
        // existingKeys entries are sorted by cost in an ascending order so
        // costliest entry is at the end
        int i = 1;
        while (i <= 3) { //remove at most 3 entries
            if ((size -i) >= 0) {
                removeList.add(existingKeys.get(size - i));
            }
            i++;
        }
        return removeList;

    }}).build();

cache.put("001", new Employee("001", "James Kelly"), 7d);
cache.put("002", new Employee("002", "Jimmy Buffet"), 10d);
cache.put("003", new Employee("003", "Nat Cole"), 5d);
cache.put("004", new Employee("004", "Tom Petty"), 9d);
// Total cost of entries up to this point is 31d

Employee value = cache.get("004");
assertNotNull(value);
value = cache.get("001");
assertNotNull(value);

// Adding an entry will trigger cache clean up though number of entries is less than max size
// and clean up will remove the 3 most costly items per cost factor function

cache.put("005", new Employee("005", "Etta James"), 7d);

// Note: Above put could fail when the cost of the new entry cost is high enough but
// the memory freed is not enough. Another attempt to insert would succeed if sufficient
// entries are cleaned-up by previous put().

// These entries should have been cleaned-up
value = cache.get("001");
assertNull(value);
value = cache.get("002");
assertNull(value);
value = cache.get("004");
assertNull(value);

// This entry should still be there
value = cache.get("003");
assertNotNull(value);
value = cache.get("005");
assertNotNull(value);

//Another out, should not clean-up any other entry
cache.put("006", new Employee("006", "Justin Who"), 7d);
value = cache.get("006");
assertNotNull(value);
value = cache.get("005");
assertNotNull(value);
value = cache.get("003");
assertNotNull(value);
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
internal inner class Employee(var id: String, var name: String)

val maxSize = 5//total cache capacity by size is 5
val cache = MemoryCache<String, Employee>(context, maxSize)
cache.maxCost(35.0)//total cache capacity by cost of entries
cache.clearOnMemoryError().addCostFactor(CacheCostFactor<String> { existingKeys ->
    val removeList = ArrayList<String>()
    val size = existingKeys.size
    // existingKeys entries are sorted by cost in an ascending order so
    // costliest entry is at the end
    var i = 1
    while (i <= 3) { //remove at most 3 entries
        if (size - i >= 0) {
            removeList.add(existingKeys[size - i])
        }
        i++
    }
    removeList
}).build()

cache.put("001", Employee("001", "James Kelly"), 7.0)
cache.put("002", Employee("002", "Jimmy Buffet"), 10.0)
cache.put("003", Employee("003", "Nat Cole"), 5.0)
cache.put("004", Employee("004", "Tom Petty"), 9.0)
// Total cost of entries up to this point is 31d

var value = cache.get("004")
assertNotNull(value)
value = cache.get("001")
assertNotNull(value)

// Adding an entry will trigger cache clean up though number of entries is less than max size
// and clean up will remove the 3 most costly items per cost factor function
cache.put("005", Employee("005", "Etta James"), 7.0)

// Note: Above put could fail when the cost of the new entry cost is high enough but
// the memory freed is not enough. Another attempt to insert would succeed if sufficient
// entries are cleaned-up by previous put().

// These entries should have been cleaned-up
value = cache.get("001")
assertNull(value)
value = cache.get("002")
assertNull(value)
value = cache.get("004")
assertNull(value)

// This entry should still be there
value = cache.get("003")
assertNotNull(value)
value = cache.get("005")
assertNotNull(value)

//Another out, should not clean-up any other entry
cache.put("006", Employee("006", "Justin Who"), 7.0)
value = cache.get("006")
assertNotNull(value)
value = cache.get("005")
assertNotNull(value)
value = cache.get("003")
assertNotNull(value)

Set Up Persistent Cache Using Secure Store

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Employee implements Serializable{
    String id;
    String name;
}

SecureStoreCache<Employee> cache = new SecureStoreCache<>(context, 100, "mySecureCache");

try {
    cache.open(null);//Uses internally generated encryption key
} catch (OpenFailureException ex) {
    logger.error("Failed to open secure store cache", ex);
}

// Use cache
// ...

// Close when done
cache.close();
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
internal inner class Employee(var id: String, var name: String) : Serializable

val cache = SecureStoreCache<Employee>(context!!, 100, "mySecureCache")
try {
    cache.open(null)//Uses internally generated encryption key
} catch (ex: OpenFailureException) {
    logger.error("Failed to open secure store cache", ex)
}

// Use cache
// ...

// Close when done
cache.close()

Set Up Composite Cache (Multi-Layer Cache)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Employee implements Serializable{
    String id;
    String name;
}

MemoryCache<String, Employee> cache1 = new MemoryCache<>(context, 16);
SecureStoreCache<Employee> cache2 = new SecureStoreCache<>(context, 100, "oneSecureCache");

try {
    cache2.open(null); //Uses built-in mechanism to generate an encryption key
} catch (OpenFailureException ex) {
    logger.error("Failed to open secure store cache", ex);
}

// cache2 is a persistent cache that implements the Cache interface.
CompositeCache<String, Employee> compositeCache = new CompositeCache<String,
    Employee>(context)
    .add(cache1)   // The first level cache-- MemoryCache.
    .add(cache2)   // The second level cache-- a backing store.
    .build();

// When done, make sure to close the persistent cache
cache2.close();
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
internal inner class Employee(var id: String, var name: String) : Serializable

val cache1 = MemoryCache<String, Employee>(context, 16)
val cache2 = SecureStoreCache<Employee>(context!!, 100, "oneSecureCache")

try {
    cache2.open(null) //Uses built-in mechanism to generate an encryption key
} catch (ex: OpenFailureException) {
    logger.error("Failed to open secure store cache", ex)
}

// cache2 is a persistent cache that implements the Cache interface.
val compositeCache = CompositeCache<String, Employee>(context)
        .add(cache1)   // The first level cache-- MemoryCache.
        .add(cache2)   // The second level cache-- a backing store.
        .build()

// When done, make sure to close the persistent cache
cache2.close()