/*
 * Derby - class org.apache.derby.impl.drda.ConsistencyToken
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License.
 *
 */

package org.apache.derby.impl.drda;

/**
 * Class which represents an RDB Package Consistency Token.
 */
final class ConsistencyToken {
    /** Byte array representation of the token. */
    private final byte[] bytes;
    /** Cached hash code. */
    private int hash = 0;

    /**
     * Create a new <code>ConsistencyToken</code> instance.
     *
     * @param bytes byte array representing the token
     */
    ConsistencyToken(byte[] bytes) {
        this.bytes = bytes;
    }

    /**
     * Get the byte array representation of the consistency token.
     *
     * @return a <code>byte[]</code> value
     */
    public byte[] getBytes() {
        return bytes;
    }

    /**
     * Check whether this object is equal to another object.
     *
     * @param o another object
     * @return true if the objects are equal
     */
    public boolean equals(Object o) {
        if (!(o instanceof ConsistencyToken)) return false;
        ConsistencyToken ct = (ConsistencyToken) o;
        int len = bytes.length;
        if (len != ct.bytes.length) return false;
        for (int i = 0; i < len; ++i) {
            if (bytes[i] != ct.bytes[i]) return false;
        }
        return true;
    }

    /**
     * Calculate the hash code.
     *
     * @return hash code
     */
    public int hashCode() {
        if (hash == 0) {
            int len = bytes.length;
            for (int i = 0; i < len; ++i) {
                hash ^= bytes[i];
            }
        }
        return hash;
    }

    /**
     * Return a string representation of the consistency token by
     * converting it to a <code>BigInteger</code> value. (For
     * debugging only.)
     *
     * @return a <code>String</code> value
     */
    public String toString() {
        return new java.math.BigInteger(bytes).toString();
    }
}

@@ -2183,24 +2183,604 @@
     
-if (hash == 0) %7B
+// ConsistencyToken objects might be kept for a long time and are%0A        // frequently used as keys in hash tables. Therefore, it is a good idea%0A        // to cache their hash codes.%0A        int h = hash;%0A        if (h == 0) %7B%0A            // The hash code has not been calculated yet (or perhaps the hash%0A            // code actually is 0). Calculate a new one and cache it. No%0A            // synchronization is needed since reads and writes of 32-bit%0A            // primitive values are guaranteed to be atomic. See The%0A            // %22Double-Checked Locking is Broken%22 Declaration for details.
 %0A   
@@ -2873,19 +2873,16 @@
        h
-ash
  %5E= byte
@@ -2893,32 +2893,54 @@
 ;%0A            %7D%0A
+            hash = h;%0A
         %7D%0A      
@@ -2948,19 +2948,16 @@
  return 
-has
 h;%0A    %7D

ConsistencyToken.hashCode() is not thread safe