KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xquark > mapper > metadata > UOIDManager


1 /*
2  * This file belongs to the XQuark distribution.
3  * Copyright (C) 2003 Universite de Versailles Saint-Quentin.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307.
18  * You can also get it at http://www.gnu.org/licenses/lgpl.html
19  *
20  * For more information on this software, see http://www.xquark.org.
21  */

22
23 /*
24  * UserTableManager.java
25  *
26  * Created on 29 août 2002, 14:55
27  */

28
29 package org.xquark.mapper.metadata;
30
31 import java.sql.*;
32 import java.util.ArrayList JavaDoc;
33 import java.util.Iterator JavaDoc;
34 import java.util.List JavaDoc;
35
36 import org.xquark.mapper.RepositoryException;
37 import org.xquark.mapper.dbms.*;
38
39 /**
40  * Class that encapsulate UOID allocation and manipulation functions.
41  * This object manages concurrency using a sequence an locking the recycling
42  * table.
43  *
44  */

45 public class UOIDManager
46 {
47     private static final String JavaDoc RCSRevision = "$Revision: 1.1 $";
48     private static final String JavaDoc RCSName = "$Name: $";
49     
50     public static final String JavaDoc SEQ_YES = "Y";
51     
52     private CollectionMetadata collection;
53     private String JavaDoc deleteStmt;
54     private String JavaDoc selectStmt;
55     
56     private TableInfo freeDocOIDTable;
57     private Sequence docOIDSeq;
58     private long cid;
59     private byte cid_size;
60     private byte did_size;
61     private int did_shift;
62     private int cid_shift;
63     private long did_shift_mult;
64     private long nid_mask;
65     private long did_udid_mask;
66     private long did_uoid_mask;
67     private long max_node_oid;
68     private CollectionInfo collectionInfo; // must not change during collection life
69
private ArrayList JavaDoc freeDIDs;
70     
71     /** Creates a new instance of UserTableManager */
72     public UOIDManager(CollectionMetadata collection)
73     throws RepositoryException
74     {
75         this.collection = collection;
76         cid = (long)collection.getCollectionID();
77         cid_size = collection.getRepository().getInfo().getColIDSize();
78         did_size = collection.getInfo().getDocOIDSize();
79         collectionInfo = collection.getInfo(); //.getDocOIDPreallocationSize(),
80
freeDocOIDTable = collection.getTableInfo(TableSpec.TYPE_FREE_DOC);
81         docOIDSeq = new Sequence(collection.getTableInfo(TableSpec.TYPE_DOC_SEQ),
82         collectionInfo.getDocOIDPreallocationSize()
83         );
84         freeDIDs = new ArrayList JavaDoc(collectionInfo.getDocOIDPreallocationSize());
85         init();
86     }
87     
88     /** Creates a new instance of UserTableManager */
89     private void init()
90     {
91         did_shift = RepositoryConstants.UOID_SIZE - (cid_size + did_size);
92         cid_shift = RepositoryConstants.UOID_SIZE - cid_size;
93         nid_mask = ~(Long.MAX_VALUE << did_shift);
94         did_shift_mult = 1L << did_shift;
95         max_node_oid = did_shift_mult - 1L;
96         did_udid_mask = (1L << did_size) - 1L;
97 // did_uoid_mask = did_udid_mask << did_shift;
98
initStatements();
99     }
100     
101     private void initStatements()
102     {
103         StringBuffer JavaDoc sql = new StringBuffer JavaDoc();
104         sql.append("DELETE FROM ");
105         sql.append(freeDocOIDTable.getName());
106         sql.append(" WHERE ");
107         sql.append(freeDocOIDTable.getColumns()[0].getName());
108         sql.append("<=");
109         deleteStmt = sql.toString();
110         
111        selectStmt = collection.getMetadataConnection().getLockSelectStatement(
112             freeDocOIDTable, "ORDER BY FREE_DID");
113     }
114     
115     public synchronized long getNewDocOID() throws RepositoryException
116     {
117         Statement stmt = null;
118         ResultSet rs = null;
119         
120         if (freeDIDs.size() == 0) // no more cached OIDs
121
{
122             AbstractConnection metaConn = collection.getMetadataConnection();
123             synchronized(metaConn) // SHOULD add it to any use of metadata performing commit (reading?)
124
{
125                 // First, try to recycle
126
try
127                 {
128                     metaConn.start();
129                     stmt = metaConn.getConnection().createStatement();
130                     stmt.setFetchSize(collectionInfo.getDocOIDPreallocationSize());
131                     rs = stmt.executeQuery(selectStmt);
132                     // NOTE: if updatable cursor not portable, use an "order by" instead followed by a "delete where FREE_DID > x"
133
// For Oracle: must not use "select *" but error on deleteRow() : missing parenthesis !
134
while (rs.next() && (freeDIDs.size() < collectionInfo.getDocOIDPreallocationSize()))
135                     {
136                         freeDIDs.add(new Long JavaDoc(rs.getLong(1)));
137                     }
138                     rs.close();
139                     
140                     // delete selected rows (last must be the biggest)
141

142                     if (freeDIDs.size() > 0)
143                         stmt.executeUpdate(deleteStmt + freeDIDs.get(freeDIDs.size() - 1));
144                 }
145                 catch (SQLException e)
146                 {
147                     try
148                     {
149                         metaConn.rollback();
150                     }
151                     catch (SQLException s)
152                     {
153                         // no op
154
}
155                     freeDIDs.clear(); // were not recycled in fact
156
throw new RepositoryException(RepositoryException.DB_ERROR,
157                     "JDBC error while recycling a document OIDs.", e);
158                 }
159                 finally
160                 {
161                     metaConn.commit(); // release locks
162
try
163                     {
164                         if (stmt != null)
165                             stmt.close();
166                     }
167                     catch (SQLException e)
168                     {
169                         // no op
170
}
171                 }
172             }
173             
174             // Recycle was not profitable: allocate a new block of OIDs
175
if (freeDIDs.size() == 0) // no more cached OIDs
176
{
177                 long newOID = docOIDSeq.nextValue(metaConn); // values are reserved from newOID to new OID + prealloc - 1
178
for (long i = newOID + collectionInfo.getDocOIDPreallocationSize() - 1;
179                 i >= newOID; i--)
180                     freeDIDs.add(new Long JavaDoc(i)); // add lowest OID at the end because the end is consumed first for performance reasons (ArrayList)
181
}
182         }
183         
184         return ((Long JavaDoc)freeDIDs.remove(freeDIDs.size() - 1)).longValue();
185     }
186     
187     /** @param restoredDIDs List of Long objects containing DIDs (not UDIDs) */
188     public synchronized void freeDocOIDs(List JavaDoc restoredDIDs) throws RepositoryException
189     {
190         PreparedStatement pStmt = null;
191         try
192         {
193             pStmt = collection.getMetadataConnection().getConnection().prepareStatement(freeDocOIDTable.getInsertStatement());
194             Iterator JavaDoc it = restoredDIDs.iterator();
195             while (it.hasNext())
196             {
197                 pStmt.setLong(1, ((Long JavaDoc)it.next()).longValue());
198                 pStmt.addBatch();
199             }
200             pStmt.executeBatch();
201             restoredDIDs.clear();
202         }
203         catch (SQLException e)
204         {
205             throw new RepositoryException(RepositoryException.DB_ERROR,
206             "JDBC error while recycling document OIDs.", e);
207         }
208         finally
209         {
210             try
211             {
212                 if (pStmt != null)
213                     pStmt.close();
214             }
215             catch (SQLException e)
216             {
217                 // no op
218
}
219         }
220     }
221     
222     /** Saves unused OIDS */
223     private void clear() throws RepositoryException
224     {
225         if (freeDIDs.size() > 0)
226             freeDocOIDs(freeDIDs);
227     }
228     
229     public void close() throws RepositoryException
230     {
231         clear();
232         freeDIDs = null;
233     }
234     
235     public long buildUOID(long docOID, long nodeOID)
236     {
237         // return (cid << cid_shift) + (docOID << did_shift) + nodeOID;
238
return (cid << cid_shift) | (docOID << did_shift) | nodeOID;
239     }
240     
241     public long buildUDID(long docOID)
242     {
243         // return (cid << cid_shift) + (docOID << did_shift) + nodeOID;
244
return (cid << did_size) | docOID;
245     }
246     
247     public short getCID(long uoid)
248     {
249         return (short)(uoid >>> cid_shift);
250     }
251     
252     public long getUDID(long uoid)
253     {
254         return uoid >>> did_shift;
255     }
256     
257     public long getDID(long udid)
258     {
259         return udid & did_udid_mask;
260     }
261     
262     public long getNodeOID(long uoid)
263     {
264         return uoid & nid_mask;
265     }
266     
267     public long getDocMinUOID(long docOID)
268     {
269         return buildUOID(docOID, 0);
270     }
271     
272     public long getDocMaxUOID(long docOID)
273     {
274         return buildUOID(docOID, max_node_oid);
275     }
276     
277     public long getDocMaxConstant()
278     {
279         return max_node_oid;
280     }
281     
282     public long getDocMultiplier()
283     {
284         return did_shift_mult;
285     }
286     
287     public long getBucketDivisor()
288     {
289         return did_shift_mult;
290     }
291     
292     public int getDIDShift()
293     {
294         return did_shift;
295     }
296 }
297
Popular Tags