Github user eribeiro commented on a diff in the pull request:

    https://github.com/apache/zookeeper/pull/632#discussion_r224206681
  
    --- Diff: 
zookeeper-server/src/main/java/org/apache/zookeeper/server/DataTree.java ---
    @@ -1521,4 +1566,179 @@ public boolean removeWatch(String path, WatcherType 
type, Watcher watcher) {
         public ReferenceCountedACLCache getReferenceCountedAclCache() {
             return aclCache;
         }
    +
    +    /**
    +     * Add the digest to the historical list, and update the latest zxid 
digest.
    +     */
    +    private void logZxidDigest(long zxid, long digest) {
    +        ZxidDigest zxidDigest = new ZxidDigest(zxid, 
DigestCalculator.DIGEST_VERSION, digest);
    +        lastProcessedZxidDigest = zxidDigest;
    +        if (zxidDigest.zxid % DIGEST_LOG_INTERVAL == 0) {
    +            synchronized (digestLog) {
    +                digestLog.add(zxidDigest);
    +                if (digestLog.size() > DIGEST_LOG_LIMIT) {
    +                    digestLog.poll();
    +                }
    +            }
    +        }
    +    }
    +
    +    /**
    +     * Serializing the digest to snapshot, this is done after the data 
tree 
    +     * is being serialized, so when we replay the txns and it hits this 
zxid 
    +     * we know we should be in a non-fuzzy state, and have the same 
digest. 
    +     *
    +     * @param oa the output stream to write to 
    +     * @return true if the digest is serialized successfully
    +     */
    +    public boolean serializeZxidDigest(OutputArchive oa) throws 
IOException {
    +        if (!DigestCalculator.digestEnabled()) {
    +            return false;
    +        }
    +
    +        ZxidDigest zxidDigest = lastProcessedZxidDigest;
    +        if (zxidDigest == null) {
    +            // write an empty digest
    +            zxidDigest = new ZxidDigest();
    +        }
    +        zxidDigest.serialize(oa);
    +        return true;
    +    }
    +
    +    /**
    +     * Deserializing the zxid digest from the input stream and update the 
    +     * digestFromLoadedSnapshot.
    +     *
    +     * @param ia the input stream to read from
    +     * @return the true if it deserialized successfully
    +     */
    +    public boolean deserializeZxidDigest(InputArchive ia) throws 
IOException {
    +        if (!DigestCalculator.digestEnabled()) {
    +            return false;
    +        }
    +
    +        try  {
    +            ZxidDigest zxidDigest = new ZxidDigest();
    +            zxidDigest.deserialize(ia);
    +            if (zxidDigest.zxid > 0) {
    +                digestFromLoadedSnapshot = zxidDigest;
    +            }
    +            return true;
    +        } catch (EOFException e) {
    +            LOG.warn("Got EOF exception while reading the digest, " +
    +                    "likely due to the reading an older snapshot.");
    +            return false;
    +        }
    +    }
    +
    +    /**
    +     * Compares the actual tree's digest with that in the snapshot. 
    +     * Resets digestFromLoadedSnapshot after comparision.
    +     *
    +     * @param zxid zxid
    +     */
    +    public void compareSnapshotDigests(long zxid) {
    +        if (zxid == digestFromLoadedSnapshot.zxid) {
    +            if (DigestCalculator.DIGEST_VERSION != 
digestFromLoadedSnapshot.digestVersion) {
    +                LOG.info("Digest version changed, local: {}, new: {}, " + 
    +                        "skip comparing digest now.", 
    +                        digestFromLoadedSnapshot.digestVersion, 
DigestCalculator.DIGEST_VERSION);
    +                digestFromLoadedSnapshot = null;
    +                return;
    +            }
    +            if (getTreeDigest() != digestFromLoadedSnapshot.getDigest()) {
    +                reportDigestMismatch(zxid);
    +            }
    +            digestFromLoadedSnapshot = null;
    +        } else if (digestFromLoadedSnapshot.zxid != 0 && zxid > 
digestFromLoadedSnapshot.zxid) {
    +            LOG.error("Watching for zxid 0x{} during snapshot recovery, " +
    +                    "but it wasn't found.", 
    +                    Long.toHexString(digestFromLoadedSnapshot.zxid));
    +        }
    +    }
    +
    +    /**
    +     * Reports any mismatch in the transaction digest.
    +     * @param zxid zxid for which the error is being reported.
    +     */
    +    public void reportDigestMismatch(long zxid) {
    +        ServerMetrics.DIGEST_MISMATCHES_COUNT.add(1);
    +        RATE_LOGGER.rateLimitLog("Digests are not matching. Value is 
Zxid.", 
    +                String.valueOf(zxid));
    +
    +        for (DigestWatcher watcher: digestWatchers) {
    +            watcher.process(zxid);
    +        }
    +    }
    +
    +    public long getTreeDigest() {
    +        return nodes.getDigest();
    +    }
    +
    +    public ZxidDigest getDigestFromLoadedSnapshot() {
    +        return digestFromLoadedSnapshot;
    +    }
    +
    +    /**
    +     * Add digest mismatch event handler.
    +     *
    +     * @param digestWatcher the handler to add
    +     */
    +    public void addDigestWatcher(DigestWatcher digestWatcher) {
    +        digestWatchers.add(digestWatcher);
    +    }
    +
    +    /**
    +     * Return all the digests in the historical digest list.
    +     */
    +    public LinkedList<ZxidDigest> getDigestLog() {
    +        synchronized (digestLog) {
    +            return new LinkedList<ZxidDigest>(digestLog);
    --- End diff --
    
    Maybe wrap in `Collections.unmodifiableList()`?


---

Reply via email to