View Javadoc

1   /**
2    * Copyright (c) 2011, University of Konstanz, Distributed Systems Group
3    * All rights reserved.
4    * 
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions are met:
7    * * Redistributions of source code must retain the above copyright
8    * notice, this list of conditions and the following disclaimer.
9    * * Redistributions in binary form must reproduce the above copyright
10   * notice, this list of conditions and the following disclaimer in the
11   * documentation and/or other materials provided with the distribution.
12   * * Neither the name of the University of Konstanz nor the
13   * names of its contributors may be used to endorse or promote products
14   * derived from this software without specific prior written permission.
15   * 
16   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19   * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20   * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26   */
27  package org.treetank.bucket;
28  
29  import static com.google.common.base.Objects.toStringHelper;
30  
31  import java.io.DataOutput;
32  import java.io.IOException;
33  import java.util.Arrays;
34  
35  import org.treetank.access.conf.StandardSettings;
36  import org.treetank.api.IData;
37  import org.treetank.bucket.interfaces.IBucket;
38  import org.treetank.exception.TTIOException;
39  
40  import com.google.common.hash.Funnel;
41  import com.google.common.hash.HashCode;
42  import com.google.common.hash.Hasher;
43  import com.google.common.hash.PrimitiveSink;
44  
45  /**
46   * <h1>DataBucket</h1>
47   * 
48   * <p>
49   * A data bucket stores a set of datas.
50   * </p>
51   * 
52   * @author Sebastian Graf, University of Konstanz
53   * @author Marc Kramis, University of Konstanz
54   */
55  public final class DataBucket implements IBucket {
56  
57      /** Key of data bucket. This is the base key of all contained datas. */
58      private final long mBucketKey;
59  
60      /** Array of datas. This can have null datas that were removed. */
61      private final IData[] mDatas;
62  
63      /** Pointer to last data bucket representing the same amount of data. */
64      private final long mLastBucketKey;
65  
66      /**
67       * Create data bucket.
68       * 
69       * @param pBucketKey
70       *            Base key assigned to this data bucket.
71       */
72      public DataBucket(final long pBucketKey, final long pLastBucketKey) {
73          mBucketKey = pBucketKey;
74          mLastBucketKey = pLastBucketKey;
75          mDatas = new IData[IConstants.CONTENT_COUNT];
76      }
77  
78      /**
79       * {@inheritDoc}
80       */
81      @Override
82      public long getBucketKey() {
83          return mBucketKey;
84      }
85  
86      /**
87       * Getting the pointer to the former representation of the same data-bucket.
88       * 
89       * @return the pointer to the last bucket.
90       */
91      public long getLastBucketPointer() {
92          return mLastBucketKey;
93      }
94  
95      /**
96       * Get data at a given offset.
97       * 
98       * @param pOffset
99       *            Offset of data within local data bucket.
100      * @return data at given offset.
101      */
102     public IData getData(final int pOffset) {
103         return getDatas()[pOffset];
104     }
105 
106     /**
107      * Overwrite a single data at a given offset.
108      * 
109      * @param pOffset
110      *            Offset of data to overwrite in this data bucket.
111      * @param pData
112      *            Data to store at given dataofffset.
113      */
114     public void setData(final int pOffset, final IData pData) {
115         getDatas()[pOffset] = pData;
116     }
117 
118     /**
119      * Getter for datas
120      * 
121      * @return the mDatas
122      */
123     public IData[] getDatas() {
124         return mDatas;
125     }
126 
127     /**
128      * {@inheritDoc}
129      */
130     @Override
131     public void serialize(final DataOutput pOutput) throws TTIOException {
132         try {
133             pOutput.writeInt(IConstants.DATABUCKET);
134             pOutput.writeLong(mBucketKey);
135             pOutput.writeLong(mLastBucketKey);
136             for (final IData data : getDatas()) {
137                 if (data == null) {
138                     pOutput.writeInt(IConstants.NULLDATA);
139                 } else {
140                     if (data instanceof DeletedData) {
141                         pOutput.writeInt(IConstants.DELETEDDATA);
142                     } else {
143                         pOutput.writeInt(IConstants.INTERFACEDATA);
144                     }
145                     data.serialize(pOutput);
146                 }
147             }
148         } catch (final IOException exc) {
149             throw new TTIOException(exc);
150         }
151     }
152 
153     /**
154      * {@inheritDoc}
155      */
156     @Override
157     public String toString() {
158         return toStringHelper(this).add("mBucketKey", mBucketKey).add("mDatas", Arrays.toString(mDatas))
159             .toString();
160     }
161 
162     /**
163      * Static class to mark deleted entries within the bucket.
164      * 
165      * @author Sebastian Graf, University of Konstanz
166      * 
167      */
168     public static class DeletedData implements IData {
169         /**
170          * Enum for DeletedDataFunnel.
171          * 
172          * @author Sebastian Graf, University of Konstanz
173          * 
174          */
175         enum DeletedDataFunnel implements Funnel<IData> {
176             INSTANCE;
177             public void funnel(IData from, PrimitiveSink into) {
178                 into.putLong(from.getDataKey());
179             }
180         }
181 
182         /**
183          * Data key of the deleted data.
184          */
185         private long mDataKey;
186 
187         /**
188          * Constructor.
189          * 
190          * @param pDataKey
191          *            datakey to be replaced with a deleteddata
192          */
193         public DeletedData(final long pDataKey) {
194             mDataKey = pDataKey;
195         }
196 
197         /**
198          * {@inheritDoc}
199          */
200         @Override
201         public long getDataKey() {
202             return mDataKey;
203         }
204 
205         /**
206          * {@inheritDoc}
207          */
208         @Override
209         public void serialize(final DataOutput pOutput) throws TTIOException {
210             try {
211                 pOutput.writeLong(mDataKey);
212             } catch (final IOException exc) {
213                 throw new TTIOException(exc);
214             }
215         }
216 
217         /**
218          * {@inheritDoc}
219          */
220         @Override
221         public String toString() {
222             return toStringHelper(this).add("mDataKey", mDataKey).toString();
223         }
224 
225         /**
226          * {@inheritDoc}
227          */
228         @Override
229         public Funnel<IData> getFunnel() {
230             return (Funnel<IData>)DeletedDataFunnel.INSTANCE;
231 
232         }
233     }
234 
235     /**
236      * {@inheritDoc}
237      */
238     @Override
239     public HashCode secureHash() {
240         final Hasher code = StandardSettings.HASHFUNC.newHasher().putLong(mBucketKey).putLong(mLastBucketKey);
241         for (int i = 0; i < mDatas.length; i++) {
242             if (mDatas[i] != null) {
243                 code.putObject(mDatas[i], mDatas[i].getFunnel());
244             }
245         }
246         return code.hash();
247     }
248 
249     /**
250      * {@inheritDoc}
251      */
252     @Override
253     public int hashCode() {
254         final int prime = 26267;
255         int result = 1;
256         result = prime * result + (int)(mLastBucketKey ^ (mLastBucketKey >>> 32));
257         result = prime * result + Arrays.deepHashCode(mDatas);
258         result = prime * result + (int)(mBucketKey ^ (mBucketKey >>> 32));
259         return result;
260     }
261 
262     /**
263      * {@inheritDoc}
264      */
265     @Override
266     public boolean equals(Object obj) {
267         return obj.hashCode() == this.hashCode();
268     }
269 
270 }