KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > sql > depend > BasicDependencyManager


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.depend.BasicDependencyManager
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.sql.depend;
23
24 import org.apache.derby.catalog.Dependable;
25 import org.apache.derby.catalog.DependableFinder;
26
27 import org.apache.derby.iapi.services.context.ContextManager;
28 import org.apache.derby.iapi.services.context.ContextService;
29
30 import org.apache.derby.iapi.services.monitor.Monitor;
31
32 import org.apache.derby.iapi.services.sanity.SanityManager;
33
34 import org.apache.derby.iapi.sql.compile.CompilerContext;
35 import org.apache.derby.iapi.sql.compile.Parser;
36 import org.apache.derby.impl.sql.compile.CreateViewNode;
37
38 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
39 import org.apache.derby.iapi.sql.conn.LanguageConnectionFactory;
40 import org.apache.derby.iapi.sql.conn.StatementContext;
41
42 import org.apache.derby.iapi.sql.depend.DependencyManager;
43 import org.apache.derby.iapi.sql.depend.Dependency;
44 import org.apache.derby.iapi.sql.depend.Dependent;
45 import org.apache.derby.iapi.sql.depend.Provider;
46 import org.apache.derby.iapi.sql.depend.ProviderInfo;
47 import org.apache.derby.iapi.sql.depend.ProviderList;
48
49 import org.apache.derby.iapi.sql.dictionary.DataDescriptorGenerator;
50 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
51 import org.apache.derby.iapi.sql.dictionary.DataDictionaryContext;
52 import org.apache.derby.iapi.sql.dictionary.DependencyDescriptor;
53 import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
54 import org.apache.derby.iapi.sql.dictionary.ViewDescriptor;
55 import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
56
57 import org.apache.derby.impl.sql.catalog.DDColumnDependableFinder;
58 import org.apache.derby.iapi.store.access.TransactionController;
59
60 import org.apache.derby.catalog.UUID;
61 import org.apache.derby.iapi.reference.SQLState;
62 import org.apache.derby.iapi.services.io.FormatableBitSet;
63
64 import org.apache.derby.iapi.reference.MessageId;
65
66 import org.apache.derby.iapi.error.StandardException;
67
68 import java.util.Hashtable JavaDoc;
69 import java.util.Enumeration JavaDoc;
70 import java.util.ListIterator JavaDoc;
71 import java.util.List JavaDoc;
72
73 /**
74     The dependency manager tracks needs that dependents have of providers.
75  */

76
77 public class BasicDependencyManager implements DependencyManager {
78
79     //
80
// DependencyManager interface
81
//
82

83     /**
84         adds a dependency from the dependent on the provider.
85         This will be considered to be the default type of
86         dependency, when dependency types show up.
87         <p>
88         Implementations of addDependency should be fast --
89         performing alot of extra actions to add a dependency would
90         be a detriment.
91
92         @param d the dependent
93         @param p the provider
94
95         @exception StandardException thrown if something goes wrong
96      */

97     public void addDependency(Dependent d, Provider p, ContextManager cm)
98         throws StandardException {
99         addDependency(d, p, cm, null);
100     }
101     
102     private void addDependency(Dependent d, Provider p, ContextManager cm,
103             TransactionController tc) throws StandardException {
104
105         synchronized(this)
106         {
107             Dependency dy = new BasicDependency(d, p);
108
109             /* Dependencies are either in-memory or stored, but not both */
110             if (! d.isPersistent() || ! p.isPersistent())
111             {
112                 /* Duplicate dependencies are not added to the lists.
113                  * If we find that the dependency we are trying to add in
114                  * one list is a duplicate, then it should be a duplicate in the
115                  * other list.
116                  */

117                 boolean addedToDeps = false;
118                 boolean addedToProvs = false;
119                 
120                 addedToDeps = addDependencyToTable(dependents, d.getObjectID(), dy);
121                 if (addedToDeps)
122                 {
123                     addedToProvs = addDependencyToTable(providers, p.getObjectID(), dy);
124                 }
125                 else if (SanityManager.DEBUG)
126                 {
127                     addedToProvs = addDependencyToTable(providers, p.getObjectID(), dy);
128                 }
129
130                 /* Dependency should have been added to both or neither */
131                 if (SanityManager.DEBUG)
132                 {
133                     if (addedToDeps != addedToProvs)
134                     {
135                         SanityManager.THROWASSERT(
136                             "addedToDeps (" + addedToDeps +
137                             ") and addedToProvs (" +
138                             addedToProvs + ") are expected to agree");
139                     }
140                 }
141
142                 /* Add the dependency to the StatementContext, so that
143                 * it can be cleared on a pre-execution error.
144                 */

145                 StatementContext sc = (StatementContext) cm.getContext(org.apache.derby.iapi.reference.ContextId.LANG_STATEMENT);
146                 sc.addDependency(dy);
147             }
148             else
149             {
150                 /* Add a stored dependency */
151                 LanguageConnectionContext lcc = getLanguageConnectionContext(cm);
152                 DataDictionary dd = getDataDictionary();
153                 DependencyDescriptor dependencyDescriptor;
154                 boolean wait = (tc == null);
155             
156                 dependencyDescriptor = new DependencyDescriptor(d, p);
157
158                 /* We can finally call the DataDictionary to store the dependency */
159                 dd.addDescriptor(dependencyDescriptor, null,
160                                  DataDictionary.SYSDEPENDS_CATALOG_NUM, true,
161                                  ((wait)?lcc.getTransactionExecute():tc), wait);
162             }
163         }
164     }
165
166     /**
167         drops a single dependency
168
169         @param d the dependent
170         @param p the provider
171
172         @exception StandardException thrown if something goes wrong
173      */

174     private void dropDependency(LanguageConnectionContext lcc, Dependent d, Provider p) throws StandardException
175     {
176         if (SanityManager.DEBUG) {
177             // right now, this routine isn't called for in-memory dependencies
178
if (! d.isPersistent() || ! p.isPersistent())
179             {
180                 SanityManager.NOTREACHED();
181             }
182         }
183
184         DataDictionary dd = getDataDictionary();
185         
186         DependencyDescriptor dependencyDescriptor = new DependencyDescriptor(d, p);
187
188         dd.dropStoredDependency( dependencyDescriptor,
189                                  lcc.getTransactionExecute() );
190     }
191
192
193     /**
194         mark all dependencies on the named provider as invalid.
195         When invalidation types show up, this will use the default
196         invalidation type. The dependencies will still exist once
197         they are marked invalid; clearDependencies should be used
198         to remove dependencies that a dependent has or provider gives.
199         <p>
200         Implementations of this can take a little time, but are not
201         really expected to recompile things against any changes
202         made to the provider that caused the invalidation. The
203         dependency system makes no guarantees about the state of
204         the provider -- implementations can call this before or
205         after actually changing the provider to its new state.
206         <p>
207         Implementations should throw StandardException
208         if the invalidation should be disallowed.
209
210         @param p the provider
211         @param action The action causing the invalidate
212
213         @exception StandardException thrown if unable to make it invalid
214      */

215     public void invalidateFor(Provider p, int action,
216                   LanguageConnectionContext lcc)
217          throws StandardException
218     {
219         /*
220         ** Non-persistent dependencies are stored in memory, and need to
221         ** use "synchronized" to ensure their lists don't change while
222         ** the invalidation is taking place. Persistent dependencies are
223         ** stored in the data dictionary, and we should *not* do anything
224         ** transactional (like reading from a system table) from within
225         ** a synchronized method, as it could cause deadlock.
226         **
227         ** Presumably, the transactional locking in the data dictionary
228         ** is enough to protect us, so that we don't have to put any
229         ** synchronization in the DependencyManager.
230         */

231         if (p.isPersistent())
232             coreInvalidateFor(p, action, lcc);
233         else {
234             synchronized (this) {
235                 coreInvalidateFor(p, action, lcc);
236             }
237         }
238     }
239
240     /**
241      * A version of invalidateFor that does not provide synchronization among
242      * invalidators. If parameter "forSync" is true, it also provides
243      * synchronization on the dependents. Currently, this means synchronizing
244      * on the prepared statements, which might be being executed on other
245      * threads.
246      * @param p provider
247      * @param action The action causing the invalidate
248      * @param lcc Language connection context
249      *
250      * @exception StandardException Thrown on error.
251      */

252     private void coreInvalidateFor(Provider p, int action, LanguageConnectionContext lcc)
253         throws StandardException
254     {
255         List list = getDependents(p);
256         if (list == null)
257         {
258             return;
259         }
260
261
262         // affectedCols is passed in from table descriptor provider to indicate
263
// which columns it cares; subsetCols is affectedCols' intersection
264
// with column bit map found in the provider of SYSDEPENDS line to
265
// find out which columns really matter. If SYSDEPENDS line's
266
// dependent is view (or maybe others), provider is table, yet it
267
// doesn't have column bit map because the view was created in a
268
// previous version of server which doesn't support column dependency,
269
// and we really want it to have (such as in drop column), in any case
270
// if we passed in table descriptor to this function with a bit map,
271
// we really need this, we generate the bitmaps on the fly and update
272
// SYSDEPENDS
273

274         FormatableBitSet affectedCols = null, subsetCols = null;
275         if (p instanceof TableDescriptor)
276         {
277             affectedCols = ((TableDescriptor) p).getReferencedColumnMap();
278             if (affectedCols != null)
279                 subsetCols = new FormatableBitSet(affectedCols.getLength());
280         }
281
282         {
283             StandardException noInvalidate = null;
284             // We cannot use an iterator here as the invalidations can remove
285
// entries from this list.
286
for (int ei = list.size() - 1; ei >= 0; ei--)
287             {
288                 if (ei >= list.size())
289                     continue;
290                 Dependency dependency = (Dependency) list.get(ei);
291
292                 Dependent dep = dependency.getDependent();
293
294                 if (affectedCols != null)
295                 {
296                     TableDescriptor td = (TableDescriptor) dependency.getProvider();
297                     FormatableBitSet providingCols = td.getReferencedColumnMap();
298                     if (providingCols == null)
299                     {
300                         if (dep instanceof ViewDescriptor)
301                         {
302                             ViewDescriptor vd = (ViewDescriptor) dep;
303                             DataDictionary dd = getDataDictionary();
304                             SchemaDescriptor compSchema;
305                             compSchema = dd.getSchemaDescriptor(vd.getCompSchemaId(), null);
306                             CompilerContext newCC = lcc.pushCompilerContext(compSchema);
307                             Parser pa = newCC.getParser();
308                             LanguageConnectionFactory lcf = lcc.getLanguageConnectionFactory();
309
310                             // Since this is always nested inside another SQL
311
// statement, so topLevel flag should be false
312
CreateViewNode cvn = (CreateViewNode)pa.parseStatement(
313                                                 vd.getViewText());
314
315                             // need a current dependent for bind
316
newCC.setCurrentDependent(dep);
317                             cvn = (CreateViewNode) cvn.bind();
318                             ProviderInfo[] providerInfos = cvn.getProviderInfo();
319                             lcc.popCompilerContext(newCC);
320
321                             boolean interferent = false;
322                             for (int i = 0; i < providerInfos.length; i++)
323                             {
324                                 Provider provider = null;
325                                 try
326                                 {
327                                     provider = (Provider) providerInfos[i].
328                                                     getDependableFinder().
329                                                     getDependable(
330                                                     providerInfos[i].getObjectId());
331                                 }
332                                 catch(java.sql.SQLException JavaDoc te)
333                                 {
334                                     if (SanityManager.DEBUG)
335                                     {
336                                         SanityManager.THROWASSERT("unexpected java.sql.SQLException - " + te);
337                                     }
338                                 }
339                                 if (provider instanceof TableDescriptor)
340                                 {
341                                     TableDescriptor tab = (TableDescriptor)provider;
342                                     FormatableBitSet colMap = tab.getReferencedColumnMap();
343                                     if (colMap == null)
344                                         continue;
345                                     // if later on an error is raised such as in
346
// case of interference, this dependency line
347
// upgrade will not happen due to rollback
348
tab.setReferencedColumnMap(null);
349                                     dropDependency(lcc, vd, tab);
350                                     tab.setReferencedColumnMap(colMap);
351                                     addDependency(vd, tab, lcc.getContextManager());
352
353                                     if (tab.getObjectID().equals(td.getObjectID()))
354                                     {
355                                         System.arraycopy(affectedCols.getByteArray(), 0,
356                                             subsetCols.getByteArray(), 0,
357                                             affectedCols.getLengthInBytes());
358                                         subsetCols.and(colMap);
359                                         if (subsetCols.anySetBit() != -1)
360                                         {
361                                             interferent = true;
362                                             ((TableDescriptor) p).setReferencedColumnMap(subsetCols);
363                                         }
364                                     }
365                                 } // if provider instanceof TableDescriptor
366
} // for providerInfos
367
if (! interferent)
368                                 continue;
369                         } // if dep instanceof ViewDescriptor
370
else
371                             ((TableDescriptor) p).setReferencedColumnMap(null);
372                     } // if providingCols == null
373
else
374                     {
375                         System.arraycopy(affectedCols.getByteArray(), 0, subsetCols.getByteArray(), 0, affectedCols.getLengthInBytes());
376                         subsetCols.and(providingCols);
377                         if (subsetCols.anySetBit() == -1)
378                             continue;
379                         ((TableDescriptor) p).setReferencedColumnMap(subsetCols);
380                     }
381                 }
382
383                 // generate a list of invalidations that fail.
384
try {
385                     dep.prepareToInvalidate(p, action, lcc);
386                 } catch (StandardException sqle) {
387
388                     if (noInvalidate != null)
389                         sqle.setNestedException(noInvalidate);
390
391                     noInvalidate = sqle;
392                 }
393                 if (noInvalidate == null) {
394
395                     if (affectedCols != null)
396                         ((TableDescriptor) p).setReferencedColumnMap(affectedCols);
397
398                     // REVISIT: future impl will want to mark the individual
399
// dependency as invalid as well as the dependent...
400
dep.makeInvalid(action, lcc);
401                 }
402             }
403
404             if (noInvalidate != null)
405                 throw noInvalidate;
406         }
407     }
408
409     /**
410         Erases all of the dependencies the dependent has, be they
411         valid or invalid, of any dependency type. This action is
412         usually performed as the first step in revalidating a
413         dependent; it first erases all the old dependencies, then
414         revalidates itself generating a list of new dependencies,
415         and then marks itself valid if all its new dependencies are
416         valid.
417         <p>
418         There might be a future want to clear all dependencies for
419         a particular provider, e.g. when destroying the provider.
420         However, at present, they are assumed to stick around and
421         it is the responsibility of the dependent to erase them when
422         revalidating against the new version of the provider.
423         <p>
424         clearDependencies will delete dependencies if they are
425         stored; the delete is finalized at the next commit.
426
427         @param d the dependent
428      *
429      * @exception StandardException Thrown on failure
430      */

431     public void clearDependencies(LanguageConnectionContext lcc, Dependent d) throws StandardException {
432         clearDependencies(lcc, d, null);
433     }
434
435     /**
436      * @inheritDoc
437      */

438     public void clearDependencies(LanguageConnectionContext lcc,
439                                     Dependent d, TransactionController tc) throws StandardException {
440         List deps = (List) dependents.get(d.getObjectID());
441
442         synchronized(this)
443         {
444             /* Remove all the stored dependencies */
445             if (d.isPersistent())
446             {
447                 DataDictionary dd = getDataDictionary();
448                 boolean wait = (tc == null);
449                 
450                 dd.dropDependentsStoredDependencies(d.getObjectID(),
451                                 ((wait)?lcc.getTransactionExecute():tc),
452                                 wait);
453             }
454
455             /* Now remove the in-memory dependencies */
456
457             if (deps == null) return; // already removed
458

459             // go through the list notifying providers to remove
460
// the dependency from their lists
461
for (ListIterator JavaDoc depsIterator = deps.listIterator();
462                 depsIterator.hasNext(); ) {
463
464                 Dependency dy = (Dependency)depsIterator.next();
465                 clearProviderDependency(dy.getProviderKey(), dy);
466             }
467
468             dependents.remove(d.getObjectID());
469         }
470     }
471
472     /**
473      * Clear the specified in memory dependency.
474      * This is useful for clean-up when an exception occurs.
475      * (We clear all in-memory dependencies added in the current
476      * StatementContext.)
477      */

478     public void clearInMemoryDependency(Dependency dy)
479     {
480         synchronized(this)
481         {
482             List deps =
483                 (List) dependents.get(dy.getDependent().getObjectID());
484
485             // NOTE - this is a NEGATIVE Sanity mode check, in sane mode we continue
486
// to ensure the dependency manager is consistent.
487
if (!SanityManager.DEBUG) {
488                 // dependency has already been removed
489
if (deps == null)
490                     return;
491             }
492
493             List provs =
494                 (List) providers.get(dy.getProvider().getObjectID());
495
496             if (SanityManager.DEBUG)
497             {
498                 // if both are null then everything is OK
499
if ((deps != null) || (provs != null)) {
500
501                     // ensure that the Dependency dy is either
502
// in both lists or in neither. Even if dy
503
// is out of the list we can have non-null
504
// deps and provs here because other dependencies
505
// with the the same providers or dependents can exist
506

507                     //
508
int depCount = 0;
509                     if (deps != null) {
510                         for (int ci = 0; ci < deps.size(); ci++) {
511                             if (dy.equals(deps.get(ci)))
512                                 depCount++;
513                         }
514                     }
515
516                     int provCount = 0;
517                     if (provs != null) {
518                         for (int ci = 0; ci < provs.size(); ci++) {
519                             if (dy.equals(provs.get(ci)))
520                                 provCount++;
521                         }
522                     }
523
524                     if (depCount != provCount) {
525                         SanityManager.THROWASSERT("Dependency count mismatch count in deps: " + depCount +
526                             ", count in provs " + provCount +
527                             ", dy.getDependent().getObjectID() = " + dy.getDependent().getObjectID() +
528                             ", dy.getProvider().getObjectID() = " + dy.getProvider().getObjectID());
529                     }
530                 }
531
532                 // dependency has already been removed,
533
// matches code that is protected by !DEBUG above
534
if (deps == null)
535                     return;
536             }
537
538             // dependency has already been removed
539
if (provs == null)
540                 return;
541
542
543             deps.remove(dy);
544             if (deps.size() == 0)
545                 dependents.remove(dy.getDependent().getObjectID());
546             provs.remove(dy);
547             if (provs.size() == 0)
548                 providers.remove(dy.getProvider().getObjectID());
549         }
550     }
551
552
553     /**
554      * @see DependencyManager#getAllProviders
555      *
556      * @exception StandardException Thrown on error
557      */

558 // public SList getAllProviders(Dependent dependent)
559
// throws StandardException
560
// {
561
// synchronized(this)
562
// {
563
// SList list = getProviders(dependent);
564
// return list;
565
// }
566
// }
567

568     /**
569      * @see DependencyManager#getAllProviderInfos
570      *
571      * @exception StandardException Thrown on error
572      */

573 /* public ProviderInfo[] getAllProviderInfos(Dependent dependent)
574                             throws StandardException
575     {
576         synchronized(this)
577         {
578             ProviderInfo[] retval;
579             SList list = getProviders(dependent);
580             retval = new ProviderInfo[list.size()];
581             if (list == null)
582             {
583                 return retval;
584             }
585             
586             int piCtr = 0;
587
588             Enumeration enum = list.elements();
589             while (enum != null && enum.hasMoreElements())
590             {
591                 Dependency dep = (Dependency) enum.nextElement();
592
593                 retval[piCtr++] = new BasicProviderInfo(
594                                         dep.getProvider().getObjectID(),
595                                         dep.getProvider().getDependableFinder(),
596                                         dep.getProvider().getObjectName()
597                                         );
598             }
599
600             return retval;
601         }
602     }
603 */

604
605     /**
606      * @see DependencyManager#getPersistentProviderInfos
607      *
608      * @exception StandardException Thrown on error
609      */

610     public synchronized ProviderInfo[] getPersistentProviderInfos(Dependent dependent)
611                             throws StandardException
612     {
613         List list = getProviders(dependent);
614         if (list == null)
615         {
616             return EMPTY_PROVIDER_INFO;
617         }
618
619         java.util.ArrayList JavaDoc pih = new java.util.ArrayList JavaDoc();
620
621         for (ListIterator JavaDoc depsIterator = list.listIterator();
622                     depsIterator.hasNext(); )
623         {
624             Dependency dep = (Dependency) depsIterator.next();
625
626             if (dep.getProvider().isPersistent())
627             {
628                 pih.add(new BasicProviderInfo(
629                                     dep.getProvider().getObjectID(),
630                                     dep.getProvider().getDependableFinder(),
631                                     dep.getProvider().getObjectName()
632                                     ));
633             }
634         }
635
636
637         return (ProviderInfo[]) pih.toArray(EMPTY_PROVIDER_INFO);
638     }
639
640     private static final ProviderInfo[] EMPTY_PROVIDER_INFO = new ProviderInfo[0];
641
642     /**
643      * @see DependencyManager#getPersistentProviderInfos
644      *
645      * @exception StandardException Thrown on error
646      */

647     public ProviderInfo[] getPersistentProviderInfos(ProviderList pl)
648                             throws StandardException
649     {
650         Enumeration JavaDoc e = pl.elements();
651         int numProviders = 0;
652         ProviderInfo[] retval;
653
654         /*
655         ** We make 2 passes - the first to count the number of persistent
656         ** providers and the second to populate the array of ProviderInfos.
657         */

658         while (e != null && e.hasMoreElements())
659         {
660             Provider prov = (Provider) e.nextElement();
661
662             if (prov.isPersistent())
663             {
664                 numProviders++;
665             }
666         }
667
668         e = pl.elements();
669         retval = new ProviderInfo[numProviders];
670         int piCtr = 0;
671         while (e != null && e.hasMoreElements())
672         {
673             Provider prov = (Provider) e.nextElement();
674
675             if (prov.isPersistent())
676             {
677                 retval[piCtr++] = new BasicProviderInfo(
678                                     prov.getObjectID(),
679                                     prov.getDependableFinder(),
680                                     prov.getObjectName()
681                                     );
682             }
683         }
684
685         return retval;
686     }
687
688     /**
689      * @see DependencyManager#clearColumnInfoInProviders
690      *
691      * @param pl provider list
692      *
693      * @exception StandardException Thrown on error
694      */

695     public void clearColumnInfoInProviders(ProviderList pl)
696                     throws StandardException
697     {
698         Enumeration JavaDoc e = pl.elements();
699         while (e.hasMoreElements())
700         {
701             Provider pro = (Provider) e.nextElement();
702             if (pro instanceof TableDescriptor)
703                 ((TableDescriptor) pro).setReferencedColumnMap(null);
704         }
705     }
706
707     /**
708      * Copy dependencies from one dependent to another.
709      *
710      * @param copy_From the dependent to copy from
711      * @param copyTo the dependent to copy to
712      * @param persistentOnly only copy persistent dependencies
713      * @param cm Current ContextManager
714      *
715      * @exception StandardException Thrown on error.
716      */

717     public void copyDependencies(Dependent copy_From,
718                                 Dependent copyTo,
719                                 boolean persistentOnly,
720                                 ContextManager cm) throws StandardException
721     {
722         copyDependencies(copy_From, copyTo, persistentOnly, cm, null);
723     }
724     
725     /**
726      * @inheritDoc
727      */

728     public synchronized void copyDependencies(
729                                     Dependent copy_From,
730                                     Dependent copyTo,
731                                     boolean persistentOnly,
732                                     ContextManager cm,
733                                     TransactionController tc)
734         throws StandardException
735     {
736
737         List list = getProviders(copy_From);
738         if (list == null)
739             return;
740
741         for (ListIterator JavaDoc depsIterator = list.listIterator(); depsIterator.hasNext(); )
742         {
743             Provider provider = ((Dependency) depsIterator.next()).getProvider();
744                 
745             if (!persistentOnly || provider.isPersistent())
746             {
747                 this.addDependency(copyTo, provider, cm, tc);
748             }
749         }
750     }
751
752                     
753     /**
754      * Returns a string representation of the SQL action, hence no
755      * need to internationalize, which is causing the invokation
756      * of the Dependency Manager.
757      *
758      * @param action The action
759      *
760      * @return String The String representation
761      */

762     public String JavaDoc getActionString(int action)
763     {
764         switch (action)
765         {
766             case ALTER_TABLE:
767                 return "ALTER TABLE";
768
769             case RENAME: //for rename table and column
770
return "RENAME";
771
772             case RENAME_INDEX:
773                 return "RENAME INDEX";
774
775             case COMPILE_FAILED:
776                 return "COMPILE FAILED";
777
778             case DROP_TABLE:
779                 return "DROP TABLE";
780
781             case DROP_INDEX:
782                 return "DROP INDEX";
783
784             case DROP_VIEW:
785                 return "DROP VIEW";
786
787             case CREATE_INDEX:
788                 return "CREATE INDEX";
789
790             case ROLLBACK:
791                 return "ROLLBACK";
792
793             case CHANGED_CURSOR:
794                 return "CHANGED CURSOR";
795
796             case CREATE_CONSTRAINT:
797                 return "CREATE CONSTRAINT";
798
799             case DROP_CONSTRAINT:
800                 return "DROP CONSTRAINT";
801
802             case DROP_METHOD_ALIAS:
803                 return "DROP ROUTINE";
804
805             case PREPARED_STATEMENT_RELEASE:
806                 return "PREPARED STATEMENT RELEASE";
807
808             case DROP_SPS:
809                 return "DROP STORED PREPARED STATEMENT";
810
811             case USER_RECOMPILE_REQUEST:
812                 return "USER REQUESTED INVALIDATION";
813
814             case BULK_INSERT:
815                 return "BULK INSERT";
816
817             case CREATE_VIEW:
818                 return "CREATE_VIEW";
819  
820             case DROP_JAR:
821                 return "DROP_JAR";
822
823             case REPLACE_JAR:
824                 return "REPLACE_JAR";
825
826             case SET_CONSTRAINTS_ENABLE:
827                 return "SET_CONSTRAINTS_ENABLE";
828
829             case SET_CONSTRAINTS_DISABLE:
830                 return "SET_CONSTRAINTS_DISABLE";
831
832             case INTERNAL_RECOMPILE_REQUEST:
833                 return "INTERNAL RECOMPILE REQUEST";
834
835             case CREATE_TRIGGER:
836                 return "CREATE TRIGGER";
837
838             case DROP_TRIGGER:
839                 return "DROP TRIGGER";
840
841             case SET_TRIGGERS_ENABLE:
842                 return "SET TRIGGERS ENABLED";
843
844             case SET_TRIGGERS_DISABLE:
845                 return "SET TRIGGERS DISABLED";
846
847             case MODIFY_COLUMN_DEFAULT:
848                 return "MODIFY COLUMN DEFAULT";
849
850             case COMPRESS_TABLE:
851                 return "COMPRESS TABLE";
852
853             case DROP_COLUMN:
854                 return "DROP COLUMN";
855
856             case DROP_STATISTICS:
857                 return "DROP STATISTICS";
858
859             case UPDATE_STATISTICS:
860                 return "UPDATE STATISTICS";
861
862             case TRUNCATE_TABLE:
863                 return "TRUNCATE TABLE";
864
865             case DROP_SYNONYM:
866                 return "DROP SYNONYM";
867
868             case REVOKE_PRIVILEGE:
869                 return "REVOKE PRIVILEGE";
870
871             case REVOKE_PRIVILEGE_RESTRICT:
872                 return "REVOKE PRIVILEGE RESTRICT";
873                                
874             default:
875                 if (SanityManager.DEBUG)
876                 {
877                     SanityManager.THROWASSERT("getActionString() passed an invalid value (" + action + ")");
878                 }
879                 // NOTE: This is not internationalized because we should never
880
// reach here.
881
return "UNKNOWN";
882         }
883     }
884
885     /**
886      * Count the number of active dependencies, both stored and in memory,
887      * in the system.
888      *
889      * @return int The number of active dependencies in the system.
890
891         @exception StandardException thrown if something goes wrong
892      */

893     public int countDependencies()
894         throws StandardException
895     {
896         synchronized(this)
897         {
898             int numDependencies = 0;
899             Enumeration JavaDoc deps = dependents.elements();
900             Enumeration JavaDoc provs = providers.elements();
901             List storedDeps = getDataDictionary().
902                                     getAllDependencyDescriptorsList();
903
904             /* Count the in memory dependencies */
905             while (deps.hasMoreElements())
906             {
907                 numDependencies += ((List) deps.nextElement()).size();
908             }
909
910             while (provs.hasMoreElements())
911             {
912                 numDependencies += ((List) provs.nextElement()).size();
913             }
914
915             /* Add in the stored dependencies */
916             numDependencies += storedDeps.size();
917
918             return numDependencies;
919         }
920     }
921
922     /**
923      * Dump out debugging info on all of the dependencies currently
924      * within the system.
925      *
926      * @return String Debugging info on the dependencies.
927      * (null if SanityManger.DEBUG is false)
928
929      * @exception StandardException thrown if something goes wrong
930      * @exception java.sql.SQLException thrown if something goes wrong
931      */

932     public String JavaDoc dumpDependencies() throws StandardException, java.sql.SQLException JavaDoc
933     {
934         synchronized(this)
935         {
936             boolean foundInMemory = false;
937             boolean foundStored = false;
938             StringBuffer JavaDoc debugBuf = new StringBuffer JavaDoc();
939
940             if (SanityManager.DEBUG)
941             {
942                 Enumeration JavaDoc deps = dependents.keys();
943                 UUID[] depKeys = new UUID[dependents.size()];
944
945                 /* Record the in memory dependencies */
946                 for (int i = 0; deps.hasMoreElements(); i++)
947                 {
948                     /*
949                     ** Get all the keys and sort them, so that they will always
950                     ** be printed in the same order (we have tests that canonize
951                     ** the order of printing the dependencies, and since the key
952                     ** is a UUID, the order they are returned from
953                     ** hasMoreElements() changes from run to run).
954                     */

955                     depKeys[i] = (UUID) deps.nextElement();
956                 }
957
958                 /* Do a bubble sort - there aren't likely to be many elements */
959                 bubbleSort(depKeys);
960
961                 /* Iterate through the sorted keys */
962                 for (int i = 0; i < depKeys.length; i++)
963                 {
964                     List depsSList = (List) dependents.get(depKeys[i]);
965
966                     for (ListIterator JavaDoc depsIterator = depsSList.listIterator();
967                         depsIterator.hasNext(); )
968                     {
969                         Dependency dy = (Dependency)depsIterator.next();
970
971                         if (! foundInMemory)
972                         {
973                             debugBuf.append("In Memory Dependencies:\n");
974                             foundInMemory = true;
975                         }
976
977                         debugBuf.append(dy.getDependent().toString() +
978                                         ", type " +
979                                         dy.getDependent().getClassType() +
980                                         ", " +
981                                         " is dependent on " +
982                                         dy.getProvider().getObjectName() +
983                                         ", type " +
984                                         dy.getProvider().getClassType() +
985                                         "\n");
986                     }
987                 }
988
989                 /* Record the in memory dependencies */
990                 Enumeration JavaDoc provs = providers.keys();
991                 UUID[] provKeys = new UUID[providers.size()];
992                 for (int i = 0; provs.hasMoreElements(); i++)
993                 {
994                     /*
995                     ** Get all the keys and sort them, so that they will always
996                     ** be printed in the same order (we have tests that canonize
997                     ** the order of printing the dependencies, and since the key
998                     ** is a UUID, the order they are returned from
999                     ** hasMoreElements() changes from run to run).
1000                    */

1001                    provKeys[i] = (UUID) provs.nextElement();
1002                }
1003
1004                /* Do a bubble sort - there aren't likely to be many elements */
1005                bubbleSort(provKeys);
1006
1007                /* Iterate through the sorted keys */
1008                for (int i = 0; i < provKeys.length; i++)
1009                {
1010                    List depsSList = (List) providers.get(provKeys[i]);
1011
1012                    for (ListIterator JavaDoc depsIterator = depsSList.listIterator();
1013                        depsIterator.hasNext(); )
1014                    {
1015
1016                        Dependency dy = (Dependency)depsIterator.next();
1017
1018                        if (! foundInMemory)
1019                        {
1020                            debugBuf.append("In Memory Dependencies:\n");
1021                            foundInMemory = true;
1022                        }
1023
1024                        debugBuf.append(
1025                                        dy.getProvider().toString() +
1026                                        ", type " +
1027                                        dy.getProvider().getClassType() +
1028                                        ", provides for " +
1029                                        dy.getDependent().getObjectName() +
1030                                        ", type " +
1031                                        dy.getDependent().getClassType() +
1032                                        "\n");
1033                    }
1034                }
1035                /* Record the stored dependencies in sorted order to avoid
1036                   ordering problems in canons. Also the dependencyDescriptor.getUUID()
1037                   in this list is not unique, hence the sort on the output string values instead
1038                */

1039                List storedDeps =
1040                            getDataDictionary().getAllDependencyDescriptorsList();
1041
1042                String JavaDoc[] dependStr = new String JavaDoc[storedDeps.size()];
1043
1044                int i = 0;
1045                for (ListIterator JavaDoc depsIterator = storedDeps.listIterator();
1046                     depsIterator.hasNext(); )
1047                {
1048                    DependencyDescriptor dd = (DependencyDescriptor)depsIterator.next();
1049
1050                    if (! foundStored)
1051                    {
1052                        debugBuf.append("Stored Dependencies:\n");
1053                        foundStored = true;
1054                    }
1055
1056                    dependStr[i++] = new String JavaDoc(
1057                                    dd.getProviderFinder().getSQLObjectName(
1058                                        dd.getProviderID().toString()) +
1059                                    ", type " +
1060                                    dd.getProviderFinder().getSQLObjectType() +
1061                                    ", provides for " +
1062                                    dd.getDependentFinder().getSQLObjectName(
1063                                        dd.getUUID().toString()) +
1064                                    ", type " +
1065                                    dd.getDependentFinder().getSQLObjectType() +
1066                                    "\n");
1067                }
1068
1069                // sort stored dependencies; dependStr
1070
for (i = 0; i < dependStr.length; i++)
1071                {
1072                    for (int j = i + 1; j < dependStr.length; j++)
1073                    {
1074                        if (dependStr[i].compareTo(dependStr[j]) > 0)
1075                        {
1076                            String JavaDoc save = dependStr[i];
1077                            dependStr[i] = dependStr[j];
1078                            dependStr[j] = save;
1079                        }
1080                    }
1081                }
1082
1083                for(i=0; i < dependStr.length; i++)
1084                        debugBuf.append(dependStr[i]);
1085
1086
1087            }
1088
1089            return debugBuf.toString();
1090        }
1091    }
1092
1093    //
1094
// class interface
1095
//
1096
public BasicDependencyManager() {
1097    }
1098
1099    //
1100
// class implementation
1101
//
1102

1103    /**
1104     * Add a new dependency to the specified table if it does not
1105     * already exist in that table.
1106     *
1107     * @return boolean Whether or not the dependency get added.
1108     */

1109    private boolean addDependencyToTable(Hashtable JavaDoc table,
1110        Object JavaDoc key, Dependency dy) {
1111
1112        List deps = (List) table.get(key);
1113        if (deps == null) {
1114            deps = newSList();
1115            deps.add(dy);
1116            table.put(key, deps);
1117        }
1118        else {
1119            /* Make sure that we're not adding a duplicate dependency */
1120            UUID provKey = dy.getProvider().getObjectID();
1121            UUID depKey = dy.getDependent().getObjectID();
1122
1123            for (ListIterator JavaDoc depsIT = deps.listIterator(); depsIT.hasNext(); )
1124            {
1125                Dependency curDY = (Dependency)depsIT.next();
1126                if (curDY.getProvider().getObjectID().equals(provKey) &&
1127                    curDY.getDependent().getObjectID().equals(depKey))
1128                {
1129                    return false;
1130                }
1131            }
1132
1133            deps.add(dy);
1134        }
1135
1136        if (SanityManager.DEBUG) {
1137
1138            if (SanityManager.DEBUG_ON("memoryLeakTrace")) {
1139
1140                if (table.size() > 100)
1141                    System.out.println("memoryLeakTrace:BasicDependencyManager:table " + table.size());
1142                if (deps.size() > 50)
1143                    System.out.println("memoryLeakTrace:BasicDependencyManager:deps " + deps.size());
1144            }
1145        }
1146
1147        return true;
1148    }
1149
1150    /**
1151     * removes a dependency for a given provider. assumes
1152     * that the dependent removal is being dealt with elsewhere.
1153     * Won't assume that the dependent only appears once in the list.
1154     */

1155    protected void clearProviderDependency(UUID p, Dependency d) {
1156        List deps = (List) providers.get(p);
1157
1158        if (deps == null)
1159            return;
1160
1161        deps.remove(d);
1162
1163        if (deps.size() == 0)
1164            providers.remove(p);
1165    }
1166
1167    /**
1168     * Replace the DependencyDescriptors in an List with Dependencys.
1169     *
1170     * @param storedList The List of DependencyDescriptors representing
1171     * stored dependencies.
1172     * @param providerForList The provider if this list is being created
1173     * for a list of dependents. Null otherwise.
1174     *
1175     * @return List The converted List
1176     *
1177     * @exception StandardException thrown if something goes wrong
1178     */

1179    private List getDependencyDescriptorList(List storedList,
1180            Provider providerForList)
1181        throws StandardException
1182    {
1183        if (storedList.size() != 0)
1184        {
1185            /* For each DependencyDescriptor, we need to instantiate
1186             * object descriptors of the appropriate type for both
1187             * the dependent and provider, create a Dependency with
1188             * that Dependent and Provider and substitute the Dependency
1189             * back into the same place in the List
1190             * so that the call gets an enumerations of Dependencys.
1191             */

1192            for (ListIterator JavaDoc depsIterator = storedList.listIterator();
1193                 depsIterator.hasNext(); )
1194            {
1195                Dependent tempD;
1196                Provider tempP;
1197                DependableFinder finder = null;
1198
1199                DependencyDescriptor depDesc = (DependencyDescriptor) depsIterator.next();
1200
1201                try {
1202                    finder = depDesc.getDependentFinder();
1203                    tempD = (Dependent) finder.getDependable( depDesc.getUUID() );
1204
1205                    if (providerForList != null)
1206                    {
1207                        // Use the provider being passed in.
1208
tempP = providerForList;
1209                        
1210                        // Sanity check the object identifiers match.
1211
if (SanityManager.DEBUG) {
1212                            if (!tempP.getObjectID().equals(depDesc.getProviderID()))
1213                            {
1214                                SanityManager.THROWASSERT("mismatch providers");
1215                            }
1216                        }
1217                    }
1218                    else
1219                    {
1220                        finder = depDesc.getProviderFinder();
1221                        tempP = (Provider) finder.getDependable( depDesc.getProviderID() );
1222                        
1223                    }
1224
1225                } catch (java.sql.SQLException JavaDoc te) {
1226                    throw StandardException.newException(SQLState.DEP_UNABLE_TO_RESTORE, finder.getClass().getName(), te.getMessage());
1227
1228                }
1229
1230                depsIterator.set(new BasicDependency(tempD, tempP));
1231            }
1232        }
1233
1234        return storedList;
1235    }
1236
1237    /**
1238     * Returns the DataDictionary to use.
1239     *
1240     * @return DataDictionary The DataDictionary to use.
1241     */

1242    private DataDictionary getDataDictionary()
1243    {
1244        if (dataDictionary == null)
1245        {
1246            DataDictionaryContext ddc;
1247            
1248            ddc = (DataDictionaryContext)
1249                        (ContextService.getContext(DataDictionaryContext.CONTEXT_ID));
1250
1251
1252            dataDictionary = ddc.getDataDictionary();
1253        }
1254
1255        return dataDictionary;
1256    }
1257
1258    /**
1259     * Returns the LanguageConnectionContext to use.
1260     *
1261     * @return LanguageConnectionContext The LanguageConnectionContext to use.
1262     */

1263    private LanguageConnectionContext getLanguageConnectionContext()
1264    {
1265        // find the language context.
1266
return (LanguageConnectionContext)
1267                ContextService.getContext(LanguageConnectionContext.CONTEXT_ID);
1268    }
1269
1270    /**
1271     * Returns the LanguageConnectionContext to use.
1272     *
1273     * @param cm Current ContextManager
1274     *
1275     * @return LanguageConnectionContext The LanguageConnectionContext to use.
1276     */

1277    private LanguageConnectionContext getLanguageConnectionContext(ContextManager cm)
1278    {
1279        // find the language context.
1280
return (LanguageConnectionContext) cm.getContext(LanguageConnectionContext.CONTEXT_ID);
1281    }
1282
1283    /**
1284     * Do a bubble sort on the given array of UUIDs. This sorts by the
1285     * String values of the UUIDs. It's slow, but it doesn't matter
1286     * because this is only for testing and debugging. Sorting by
1287     * UUID.toString() always gives the same order because, within a
1288     * single boot of the system, UUIDs are distinguished only by a
1289     * sequence number.
1290     *
1291     * @param uuids The array of UUIDs to sort.
1292     */

1293    private void bubbleSort(UUID[] uuids)
1294    {
1295        if (SanityManager.DEBUG)
1296        {
1297            for (int i = 0; i < uuids.length; i++)
1298            {
1299                for (int j = i + 1; j < uuids.length; j++)
1300                {
1301                    if (uuids[i].toString().compareTo(uuids[j].toString()) > 0)
1302                    {
1303                        UUID save = uuids[i];
1304                        uuids[i] = uuids[j];
1305                        uuids[j] = save;
1306                    }
1307                }
1308            }
1309        }
1310    }
1311
1312    /**
1313        Returns an enumeration of all dependencies that this
1314        dependent has with any provider (even
1315        invalid ones). Includes all dependency types.
1316
1317        @param d the dependent
1318
1319        @exception StandardException thrown if something goes wrong
1320     */

1321    private List getProviders (Dependent d) throws StandardException {
1322
1323        List deps = (List) dependents.get(d.getObjectID());
1324
1325        /* If the Dependent is not persistent, then we only have to
1326        * worry about in-memory dependencies. Otherwise, we have to
1327        * integrate the 2.
1328        */

1329        if (! d.isPersistent())
1330        {
1331            return (deps == null? null : deps);
1332        }
1333        else
1334        {
1335            if (deps == null)
1336            {
1337                deps = newSList();
1338            }
1339            else
1340            {
1341                deps = newSList(deps);
1342            }
1343
1344            /* Now we need to add any persistent dependencies to the
1345            * list before returning
1346            */

1347            List storedList = getDependencyDescriptorList(
1348                            getDataDictionary().
1349                                getDependentsDescriptorList(
1350                                                d.getObjectID().toString()
1351                                                            ),
1352                                (Provider) null
1353                                                    );
1354
1355            if (storedList.size() > 0)
1356            {
1357                deps.addAll(0, storedList);
1358            }
1359
1360            return deps;
1361        }
1362    }
1363
1364    /**
1365        Returns an enumeration of all dependencies that this
1366        provider is supporting for any dependent at all (even
1367        invalid ones). Includes all dependency types.
1368
1369        @param p the provider
1370
1371        @exception StandardException thrown if something goes wrong
1372     */

1373    private List getDependents (Provider p)
1374            throws StandardException {
1375
1376        List deps = (List) providers.get(p.getObjectID());
1377
1378        /* If the Provider is not persistent, then we only have to
1379        * worry about in-memory dependencies. Otherwise, we have to
1380        * integrate the 2.
1381        */

1382        if (! p.isPersistent())
1383        {
1384            return deps;
1385        }
1386        else
1387        {
1388            if (deps == null)
1389            {
1390                deps = newSList();
1391            }
1392            else
1393            {
1394                deps = newSList(deps);
1395            }
1396
1397            /* Now we need to add any persistent dependencies to the
1398            * list before returning
1399            */

1400            List storedList = getDependencyDescriptorList(
1401                            getDataDictionary().
1402                                getProvidersDescriptorList(
1403                                                p.getObjectID().toString()
1404                                                            ),
1405                            p
1406                                                    );
1407            if (storedList.size() > 0)
1408            {
1409                deps.addAll(0, storedList);
1410            }
1411
1412            return deps;
1413        }
1414    }
1415
1416    private static List newSList() {
1417        return java.util.Collections.synchronizedList(new java.util.LinkedList JavaDoc());
1418    }
1419    private static List newSList(List list) {
1420        return java.util.Collections.synchronizedList(new java.util.LinkedList JavaDoc(list));
1421    }
1422
1423    private DataDictionary dataDictionary = null;
1424    protected Hashtable JavaDoc dependents = new Hashtable JavaDoc();
1425    protected Hashtable JavaDoc providers = new Hashtable JavaDoc();
1426}
1427
Popular Tags