summaryrefslogtreecommitdiff
path: root/java/demo/Manual/evictor/EvictorBase.java
blob: c309bd2866a05102e0bb8b4579c16cde8ee1055a (plain)
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package Evictor;

public abstract class EvictorBase implements Ice.ServantLocator
{
    public
    EvictorBase()
    {
        _size = 1000;
    }

    public
    EvictorBase(int size)
    {
        _size = size < 0 ? 1000 : size;
    }

    public abstract Ice.Object
    add(Ice.Current c, Ice.LocalObjectHolder cookie);

    public abstract void
    evict(Ice.Object servant, java.lang.Object cookie);

    synchronized public final Ice.Object
    locate(Ice.Current c, Ice.LocalObjectHolder cookie)
    {
        //
        // Check if we have a servant in the map already.
        //
        EvictorEntry entry = _map.get(c.id);
        if(entry != null)
        {
            //
            // Got an entry already, dequeue the entry from its current position.
            //
            entry.queuePos.remove();
        }
        else
        {
            //
            // We do not have entry. Ask the derived class to
            // instantiate a servant and add a new entry to the map.
            //
            entry = new EvictorEntry();
            Ice.LocalObjectHolder cookieHolder = new Ice.LocalObjectHolder();
            entry.servant = add(c, cookieHolder); // Down-call
            if(entry.servant == null)
            {
                return null;
            }
            entry.userCookie = cookieHolder.value;
            entry.useCount = 0;
            _map.put(c.id, entry);
        }

        //
        // Increment the use count of the servant and enqueue
        // the entry at the front, so we get LRU order.
        //
        ++(entry.useCount);
        _queue.addFirst(c.id);
        entry.queuePos = _queue.iterator();
        entry.queuePos.next(); // Position the iterator on the element.

        cookie.value = entry;

        return entry.servant;
    }

    synchronized public final void
    finished(Ice.Current c, Ice.Object o, java.lang.Object cookie)
    {
        EvictorEntry entry = (EvictorEntry)cookie;

        //
        // Decrement use count and check if
        // there is something to evict.
        //
        --(entry.useCount);
        evictServants();
    }

    synchronized public final void
    deactivate(String category)
    {
        _size = 0;
        evictServants();
    }

    private class EvictorEntry
    {
        Ice.Object servant;
        java.lang.Object userCookie;
        java.util.Iterator<Ice.Identity> queuePos;
        int useCount;
    }

    private void evictServants()
    {
        //
        // If the evictor queue has grown larger than the limit,
        // look at the excess elements to see whether any of them
        // can be evicted.
        //
        java.util.Iterator<Ice.Identity> p = _queue.riterator();
        int excessEntries = _map.size() - _size;
        for(int i = 0; i < excessEntries; ++i)
        {
            Ice.Identity id = p.next();
            EvictorEntry e = _map.get(id);
            if(e.useCount == 0)
            {
                evict(e.servant, e.userCookie); // Down-call
                e.queuePos.remove();
                _map.remove(id);
            }
        }
    }

    private java.util.Map<Ice.Identity, EvictorEntry> _map =
        new java.util.HashMap<Ice.Identity, EvictorEntry>();
    private Evictor.LinkedList<Ice.Identity> _queue =
        new Evictor.LinkedList<Ice.Identity>();
    private int _size;
}