Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / cacheinvalidation / src / java / com / google / ipc / invalidation / ticl / AckCache.java
1 /*
2  * Copyright 2011 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.google.ipc.invalidation.ticl;
17
18 import com.google.ipc.invalidation.ticl.proto.ClientProtocol.InvalidationP;
19 import com.google.ipc.invalidation.ticl.proto.ClientProtocol.ObjectIdP;
20 import com.google.ipc.invalidation.util.TypedUtil;
21
22 import java.util.HashMap;
23 import java.util.Map;
24
25 /**
26  * An ack "cache" that allows the TICL to avoid unnecessary delivery of a
27  * known-version invalidation when the client has aleady acked a known-version,
28  * restarted invalidation with the same or a greater version number.
29  * <p>
30  * This helps invalidation clients avoid unnecessary syncs against their backend
31  * when invalidations for an object are redelivered or reordered, as can occur
32  * frequently during a PCR or (to a lesser degree) as a result of internal
33  * failures and channel flakiness.
34  * <p>
35  * This optimization is especially useful for applications that want to use
36  * the TI Pubsub API to deliver invalidations, because version numbers are not
37  * a concept in the API itself. While the client could include version numbers
38  * in the payload, truncation messages do not include a payload.
39  * <p>
40  * The  cache invalidation API does expose version numbers, so client
41  * applications could implement the same logic themselves, but many
42  * do not, so it is a useful convenience to implement this for them in the TICL.
43  * <p>
44  * Note this class currently only records acks for restarted, known-version
45  * invalidations. While we might add ack tracking for continous invalidations at
46  * some time in the future, tracking continuous invalidations has less of a
47  * payoff than tracking restarted invalidations, because such an ack does not
48  * implicitly ack earlier invalidations for that object, and greater complexity,
49  * because of the potentially unbounded number of acks that need to be tracked
50  * for each object.
51  */
52 class AckCache {
53
54   /**
55    * A map from object id to the (long) version number of the highest
56    * <em>restarted, known version</em> invalidation for that object that has
57    * been acked by the client.
58    */
59   private Map<ObjectIdP, Long> highestAckedVersionMap = new HashMap<ObjectIdP, Long>();
60
61   /** Records the fact that the client has acknowledged the given invalidation. */
62   void recordAck(InvalidationP inv) {
63     if (!inv.getIsTrickleRestart() || !inv.getIsKnownVersion()) {
64       return;
65     }
66
67     // If the invalidation version is newer than the highest acked version in the
68     // map, then update the map.
69     ObjectIdP objectId = inv.getObjectId();
70     long version = inv.getVersion();
71     if (version > getHighestAckedVersion(objectId)) {
72       highestAckedVersionMap.put(objectId, version);
73     }
74   }
75
76   /**
77    * Returns true if the client has already acked a restarted invalidation with
78    * a version number greater than or equal to that in {@code inv} and the same
79    * object id, and {@code inv} is a known version invalidation. Unknown version
80    * invalidations are never considered already acked.
81    */
82   boolean isAcked(InvalidationP inv) {
83     return inv.getIsKnownVersion()
84         && this.getHighestAckedVersion(inv.getObjectId()) >= inv.getVersion();
85   }
86
87
88   /**
89    * Returns the highest acked version for the object id with the given key, or
90    * -1 if no versions have been acked.
91    */
92   private long getHighestAckedVersion(ObjectIdP objectId) {
93     Long version = TypedUtil.mapGet(highestAckedVersionMap, objectId);
94     return (version != null) ? version : -1L;
95   }
96 }