001    /** 
002     * 
003     * Copyright 2004 Protique Ltd
004     * 
005     * Licensed under the Apache License, Version 2.0 (the "License"); 
006     * you may not use this file except in compliance with the License. 
007     * You may obtain a copy of the License at 
008     * 
009     * http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS, 
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
014     * See the License for the specific language governing permissions and 
015     * limitations under the License. 
016     * 
017     **/
018    
019    package org.activemq.util;
020    import java.util.LinkedList;
021    
022    /**
023     * Holder for many bitArrays - used for message audit
024     * 
025     * @version $Revision: 1.1.1.1 $
026     */
027    public class BitArrayBin {
028        private LinkedList list;
029        private int maxNumberOfArrays;
030        private int firstIndex = -1;
031        private int firstBin = -1;
032    
033        /**
034         * Create a BitArrayBin to a certain window size (number of messages to keep)
035         * 
036         * @param windowSize
037         */
038        public BitArrayBin(int windowSize) {
039            maxNumberOfArrays = ((windowSize + 1) / BitArray.LONG_SIZE) + 1;
040            maxNumberOfArrays = Math.max(maxNumberOfArrays, 1);
041            list = new LinkedList();
042            for (int i = 0;i < maxNumberOfArrays;i++) {
043                list.add(new BitArray());
044            }
045        }
046    
047        /**
048         * Set a bit
049         * 
050         * @param index
051         * @param value
052         * @return
053         */
054        public boolean setBit(long index, boolean value) {
055            boolean answer = true;
056            BitArray ba = getBitArray(index);
057            if (ba != null) {
058                int offset = getOffset(index);
059                if (offset >= 0) {
060                    answer = ba.set(offset, value);
061                }
062            }
063            return answer;
064        }
065    
066        /**
067         * Get the boolean value at the index
068         * 
069         * @param index
070         * @return true/false
071         */
072        public boolean getBit(long index) {
073            boolean answer = index >= firstIndex;
074            BitArray ba = getBitArray(index);
075            if (ba != null) {
076                int offset = getOffset(index);
077                if (offset >= 0) {
078                    answer = ba.get(offset);
079                    return answer;
080                }
081            }
082            else {
083                //gone passed range for previous bins so assume set
084                answer = true;
085            }
086            return answer;
087        }
088    
089        /**
090         * Get the BitArray for the index
091         * 
092         * @param index
093         * @return
094         */
095        private BitArray getBitArray(long index) {
096            int bin = getBin(index);
097            BitArray answer = null;
098            if (bin >= 0) {
099                if (firstIndex < 0) {
100                    firstIndex = 0;
101                }
102                if (bin >= list.size()) {
103                    list.removeFirst();
104                    firstIndex += BitArray.LONG_SIZE;
105                    list.add(new BitArray());
106                    bin = list.size() - 1;
107                }
108                answer = (BitArray) list.get(bin);
109            }
110            return answer;
111        }
112    
113        /**
114         * Get the index of the bin from the total index
115         * 
116         * @param index
117         * @return the index of the bin
118         */
119        private int getBin(long index) {
120            int answer = 0;
121            if (firstBin < 0) {
122                firstBin = 0;
123            }
124            else if (firstIndex >= 0) {
125                answer = (int) ((index - firstIndex) / BitArray.LONG_SIZE);
126            }
127            return answer;
128        }
129    
130        /**
131         * Get the offset into a bin from the total index
132         * 
133         * @param index
134         * @return the relative offset into a bin
135         */
136        private int getOffset(long index) {
137            int answer = 0;
138            if (firstIndex >= 0) {
139                //System.out.println("getOffset(" + index + ") firstIndex = " + firstIndex + " bin = " + getBin(index));
140                answer = (int) ((index - firstIndex) - (BitArray.LONG_SIZE * getBin(index)));
141            }
142            return answer;
143        }
144    }