KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > services > locks > Timeout


1 /*
2
3    Derby - Class org.apache.derby.impl.services.locks.Timeout
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.impl.services.locks;
23
24 import org.apache.derby.impl.services.locks.TableNameInfo;
25
26 import org.apache.derby.iapi.services.context.ContextService;
27
28 import org.apache.derby.iapi.reference.SQLState;
29
30 import org.apache.derby.iapi.services.locks.Latch;
31 import org.apache.derby.iapi.services.locks.Lockable;
32 import org.apache.derby.iapi.services.locks.VirtualLockTable;
33 import org.apache.derby.iapi.services.sanity.SanityManager;
34
35 import org.apache.derby.iapi.error.StandardException;
36 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
37 import org.apache.derby.iapi.store.access.TransactionController;
38
39 import org.apache.derby.iapi.util.CheapDateFormatter;
40
41 import java.util.Enumeration JavaDoc;
42 import java.util.Hashtable JavaDoc;
43
44 /**
45  * Code to support Timeout error output.
46  * @author gavin
47  */

48
49 public final class Timeout
50 {
51     public static final int TABLE_AND_ROWLOCK = VirtualLockTable.TABLE_AND_ROWLOCK;
52     public static final int ALL = VirtualLockTable.ALL;
53
54     public static final String JavaDoc newline = "\n";
55     //FIXME: The newline might not be truely platform independent.
56
// We do not want to use a system call because of security reasons.
57
// LINE_SEPARATOR returns ^M for some reason, not ^M<nl>.
58
//public static final String newline = String.valueOf( (char)(new Byte(Character.LINE_SEPARATOR)).intValue() );
59
//public static final String newline = System.getProperty( "line.separator" );
60

61     private TransactionController tc;
62     private TableNameInfo tabInfo;
63
64     /* the current Latch to extract info out of */
65     private Latch currentLock;
66     /* the current row output of the lockTable */
67     private char[] outputRow;
68     /* the entire lockTable as a buffer */
69     private StringBuffer JavaDoc sb;
70     /* the hashtable information of the current lock */
71     private Hashtable JavaDoc currentRow;
72     /* the time when the exception was thrown */
73     private final long currentTime;
74     /* the snapshot of the lockTable that timeout */
75     private final Enumeration JavaDoc lockTable;
76     
77     // column1: XID varchar(10) not null
78
// column2: TYPE varchar(13) not null
79
// column3: MODE varchar(4) not null
80
// column4: LOCKCOUNT varchar(9) not null
81
// column5: LOCKNAME varchar(80) not null
82
// column6: STATE varchar(5) not null
83
// column7: TABLETYPE varchar(38) not null / LOCKOBJ varchar(38)
84
// column8: INDEXNAME varchar(50) nullable as String "NULL" / CONTAINER_ID / MODE (latch only) varchar(50)
85
// column9: TABLENAME varchar(38) not null / CONGLOM_ID varchar(38)
86
// Total length of this string is 10+1+13+1+6+1+9+1+80+1+5+1+38+1+48+1+38=256
87
private final static String JavaDoc[] column = new String JavaDoc[9];
88     private final static int LENGTHOFTABLE;
89     static
90     {
91         column[0] = "XID ";
92         column[1] = "TYPE ";
93         column[2] = "MODE";
94         column[3] = "LOCKCOUNT";
95         column[4] = "LOCKNAME ";
96         column[5] = "STATE";
97         column[6] = "TABLETYPE / LOCKOBJ ";
98         column[7] = "INDEXNAME / CONTAINER_ID / (MODE for LATCH only) ";
99         column[8] = "TABLENAME / CONGLOM_ID ";
100
101         int length = 0;
102         for( int i = 0 ; i < column.length; i++ )
103         {
104             length += column[i].length();
105         }
106         length += column.length; // for the separator
107
if( SanityManager.DEBUG )
108         { // 256 is a good number, can be expanded or contracted if necessary
109
SanityManager.ASSERT( length == 256, "TIMEOUT_MONITOR: length of the row is not 256" );
110         }
111         LENGTHOFTABLE = length;
112     }
113     private final static char LINE = '-';
114     private final static char SEPARATOR = '|';
115
116     /**
117      * Constructor
118      * @param myTimeoutLock The Latch that the timeout happened on
119      * @param myLockTable
120      * @param time The time when the lockTable was cloned.
121      */

122     private Timeout( Latch myTimeoutLock, Enumeration JavaDoc myLockTable, long time )
123     {
124         currentLock = myTimeoutLock;
125         lockTable = myLockTable;
126         currentTime = time;
127
128         if( SanityManager.DEBUG )
129         {
130             SanityManager.ASSERT( currentTime > 0, "TIMEOUT_MONITOR: currentTime is not set correctly" );
131         }
132     }
133     
134     /**
135      * createException creates a StandardException based on:
136      * currentLock
137      * a snapshot of the lockTable
138      * @return StandardException The exception with the lockTable snapshot in it
139      */

140     private StandardException createException()
141     {
142         try
143         {
144             buildLockTableString();
145         }
146         catch( StandardException se )
147         {
148             return se;
149         }
150
151         StandardException se = StandardException.newException( SQLState.LOCK_TIMEOUT_LOG, sb.toString() );
152         se.setReport( StandardException.REPORT_ALWAYS );
153         return se;
154     }
155
156     /**
157      * buildLockTableString creates a LockTable info String
158      */

159     private String JavaDoc buildLockTableString() throws StandardException
160     {
161         sb = new StringBuffer JavaDoc(8192);
162         outputRow = new char[ LENGTHOFTABLE ];
163         int i; // counter
164

165         // need language here to print out tablenames
166
LanguageConnectionContext lcc = (LanguageConnectionContext)
167             ContextService.getContext(LanguageConnectionContext.CONTEXT_ID);
168         if( lcc != null )
169             tc = lcc.getTransactionExecute();
170
171         try
172         {
173             tabInfo = new TableNameInfo( lcc, true );
174         }
175         catch (Exception JavaDoc se)
176         { //just don't do anything
177
}
178
179         sb.append( newline );
180         sb.append(CheapDateFormatter.formatDate(currentTime));
181         sb.append( newline );
182         for( i = 0; i < column.length; i++ )
183         {
184             sb.append( column[i] );
185             sb.append( SEPARATOR );
186         }
187         sb.append( newline );
188
189         for( i = 0; i < LENGTHOFTABLE; i++ )
190             sb.append( LINE );
191
192         sb.append( newline );
193
194         // get the timeout lock info
195
if( currentLock != null )
196         {
197             dumpLock( );
198             if( timeoutInfoHash() )
199             {
200                 sb.append( "*** The following row is the victim ***" );
201                 sb.append( newline );
202                 sb.append( outputRow );
203                 sb.append( newline );
204                 sb.append( "*** The above row is the victim ***" );
205                 sb.append( newline );
206             }
207             else
208             {
209                 sb.append( "*** A victim was chosen, but it cannot be printed because the lockable object, " + currentLock + ", does not want to participate ***" );
210                 sb.append( newline );
211             }
212         }
213
214         // get lock info from the rest of the table
215
if( lockTable != null )
216         {
217             while( lockTable.hasMoreElements() )
218             {
219                 currentLock = (Latch)lockTable.nextElement();
220                 dumpLock( );
221                 if( timeoutInfoHash() )
222                 {
223                     sb.append( outputRow );
224                     sb.append( newline );
225                 }
226                 else
227                 {
228                     sb.append( "*** A latch/lock, " + currentLock + ", exist in the lockTable that cannot be printed ***" );
229                     sb.append( newline );
230                 }
231             }
232             for( i = 0; i < LENGTHOFTABLE; i++ )
233                 sb.append( LINE );
234
235             sb.append( newline );
236         }
237         return sb.toString();
238     }
239
240     /**
241      * The static entry way to get the LockTable in the system.
242      * @param timeoutLock The Latch that the timeout happened on
243      * @param table The lockTable
244      * @param time The time when the lockTable was cloned
245      * @return StandardException The exception with the lockTable snapshot in it
246      */

247     static StandardException buildException( Latch timeoutLock, Enumeration JavaDoc table, long time )
248     {
249         Timeout myTimeout = new Timeout( timeoutLock, table, time );
250         return myTimeout.createException();
251     }
252
253     /*
254      * A static entry way to get the LockTable in the system.
255      * For track 3311
256      */

257     public static String JavaDoc buildString( Enumeration JavaDoc table, long time ) throws StandardException
258     {
259         Timeout myTimeout = new Timeout( null, table, time);
260         return myTimeout.buildLockTableString();
261     }
262
263     /**
264      * dumpLock puts information about currentLock into currentRow for output later.
265      * @throws StandardException
266      */

267     private void dumpLock() throws StandardException
268     {
269         Hashtable JavaDoc attributes = new Hashtable JavaDoc(17);
270         Object JavaDoc lock_type = currentLock.getQualifier();
271
272         // want containerId, segmentId, pageNum, recId from locktable
273
Lockable lockable = currentLock.getLockable();
274
275         // See if the lockable object wants to participate
276
if( !lockable.lockAttributes(ALL, attributes) )
277         {
278             currentRow = null;
279             return;
280         }
281
282         // if it does, the lockable object must have filled in the following
283
// fields
284
if( SanityManager.DEBUG )
285         {
286             SanityManager.ASSERT(attributes.get(VirtualLockTable.LOCKNAME) != null, "lock table can only represent locks that have a LOCKNAME" );
287             SanityManager.ASSERT(attributes.get(VirtualLockTable.LOCKTYPE) != null, "lock table can only represent locks that have a LOCKTYPE" );
288             if( attributes.get(VirtualLockTable.CONTAINERID ) == null &&
289                 attributes.get(VirtualLockTable.CONGLOMID ) == null )
290                 SanityManager.THROWASSERT("lock table can only represent locks that are associated with a container or conglomerate");
291         }
292
293         Long JavaDoc conglomId = (Long JavaDoc) attributes.get(VirtualLockTable.CONGLOMID);
294         
295         if( conglomId == null )
296         {
297             if( attributes.get(VirtualLockTable.CONTAINERID) != null && tc != null )
298             {
299                 Long JavaDoc value = (Long JavaDoc)attributes.get(VirtualLockTable.CONTAINERID);
300                 conglomId = new Long JavaDoc( tc.findConglomid( value.longValue() ) );
301                 attributes.put( VirtualLockTable.CONGLOMID, conglomId );
302             }
303         }
304
305         Long JavaDoc containerId = (Long JavaDoc) attributes.get(VirtualLockTable.CONTAINERID);
306
307         if( containerId == null )
308         {
309             if( conglomId != null && tc != null )
310             {
311                 try
312                 {
313                     containerId = new Long JavaDoc( tc.findContainerid( conglomId.longValue() ) );
314                     attributes.put( VirtualLockTable.CONTAINERID, containerId );
315                 }
316                 catch( Exception JavaDoc e )
317                 {
318                     // just don't do anything
319
}
320             }
321         }
322         
323         attributes.put( VirtualLockTable.LOCKOBJ, currentLock );
324         attributes.put( VirtualLockTable.XACTID, currentLock.getCompatabilitySpace().toString() );
325         attributes.put( VirtualLockTable.LOCKMODE, lock_type.toString() );
326         attributes.put( VirtualLockTable.LOCKCOUNT, Integer.toString( currentLock.getCount() ) );
327         attributes.put( VirtualLockTable.STATE, (currentLock.getCount() != 0 ) ? "GRANT" : "WAIT" );
328         
329         if( tabInfo != null && conglomId != null )
330         {
331             try{
332                 String JavaDoc tableName = tabInfo.getTableName( conglomId );
333                 attributes.put( VirtualLockTable.TABLENAME, tableName );
334             }
335             catch( NullPointerException JavaDoc e )
336             {
337                 attributes.put( VirtualLockTable.TABLENAME, conglomId );
338             }
339         
340             try
341             {
342                 String JavaDoc indexName = tabInfo.getIndexName( conglomId );
343                 if( indexName != null )
344                     attributes.put( VirtualLockTable.INDEXNAME, indexName );
345                 else
346                 {
347                     if( attributes.get(VirtualLockTable.LOCKTYPE).equals("LATCH") )
348                     { // because MODE field is way to short to display this,
349
// just put it in the indexname field for LATCH only.
350
attributes.put( VirtualLockTable.INDEXNAME, attributes.get(VirtualLockTable.LOCKMODE) );
351                     }
352                     else
353                         attributes.put( VirtualLockTable.INDEXNAME, "NULL" );
354                 }
355             }catch( Exception JavaDoc e )
356             { // we are here because tabInfo.indexCache is null
357
if( VirtualLockTable.CONTAINERID != null )
358                     attributes.put( VirtualLockTable.INDEXNAME, VirtualLockTable.CONTAINERID );
359                 else
360                     attributes.put( VirtualLockTable.INDEXNAME, "NULL" );
361             }
362
363             String JavaDoc tableType = tabInfo.getTableType( conglomId );
364             attributes.put( VirtualLockTable.TABLETYPE, tableType );
365         }
366         else
367         {
368             if( conglomId != null )
369                 attributes.put( VirtualLockTable.TABLENAME, VirtualLockTable.CONGLOMID );
370             else
371                 attributes.put( VirtualLockTable.TABLENAME, "NULL" );
372
373             if( VirtualLockTable.CONTAINERID != null )
374                 attributes.put( VirtualLockTable.INDEXNAME, VirtualLockTable.CONTAINERID );
375             else
376                 attributes.put( VirtualLockTable.INDEXNAME, "NULL" );
377                 
378             attributes.put( VirtualLockTable.TABLETYPE, currentLock.toString() );
379         }
380         currentRow = attributes;
381     }
382
383     /**
384      * cpArray helps built the output string (outputRow).
385      * @param toCp the String to be copied into outputRow
386      * @param start the start place
387      * @param end the end place
388      */

389     private void cpArray( String JavaDoc toCp, int start, int end )
390     { // build a field in the output string
391
int i = 0;
392         int totalAllowWrite = end - start;
393
394         if( toCp != null )
395         {
396             for( ; i < toCp.length() ; i++ )
397             {
398                 if( (totalAllowWrite-i) == 0 )
399                     break;
400
401                 outputRow[ i + start ] = toCp.charAt(i);
402             }
403         }
404         for( ; i + start != end; i++ )
405             outputRow[ i + start ] = ' ';
406
407         outputRow[ end ] = SEPARATOR;
408     }
409     
410     /**
411      * Copies the needed information from currentRow into the StringBuffer for output
412      * @return true if successful
413      */

414     private boolean timeoutInfoHash( )
415     {
416         if( currentRow == null )
417             return false;
418
419         String JavaDoc[] myData = new String JavaDoc[9];
420         myData[0] = VirtualLockTable.XACTID;
421         myData[1] = VirtualLockTable.LOCKTYPE;
422         myData[2] = VirtualLockTable.LOCKMODE;
423         myData[3] = VirtualLockTable.LOCKCOUNT;
424         myData[4] = VirtualLockTable.LOCKNAME;
425         myData[5] = VirtualLockTable.STATE;
426         myData[6] = VirtualLockTable.TABLETYPE;
427         myData[7] = VirtualLockTable.INDEXNAME;
428         myData[8] = VirtualLockTable.TABLENAME;
429
430
431         int currentLength = 0;
432         for( int i = 0; i < myData.length; i++ )
433         {
434             cpArray( currentRow.get( myData[i] ).toString(), currentLength , currentLength + column[i].length() );
435             // the next beginning position
436
currentLength = currentLength + column[i].length() + 1;
437         }
438         return true;
439     }
440 }
441
442
Popular Tags