protected void logDebugSequencingConnected() { Vector[] sequenceVectors = new Vector[NUMBER_OF_STATES]; Iterator itConnectedSequences = connectedSequences.iterator(); while (itConnectedSequences.hasNext()) { Sequence sequence = (Sequence) itConnectedSequences.next(); int stateId = getStateId(sequence.shouldUsePreallocation(), sequence.shouldUseTransaction()); Vector v = sequenceVectors[stateId]; if (v == null) { v = new Vector(); sequenceVectors[stateId] = v; } v.addElement(sequence); } for (int i = 0; i < NUMBER_OF_STATES; i++) { Vector v = sequenceVectors[i]; if (v != null) { getOwnerSession() .log(SessionLog.FINEST, SessionLog.SEQUENCING, "sequencing_connected", states[i]); for (int j = 0; j < v.size(); j++) { Sequence sequence = (Sequence) v.elementAt(j); Object[] args = { sequence.getName(), Integer.toString(sequence.getPreallocationSize()), Integer.toString(sequence.getInitialValue()) }; getOwnerSession() .log(SessionLog.FINEST, SessionLog.SEQUENCING, "sequence_without_state", args); } } } }
/** * PUBLIC: Connect to the database using the predefined login. This connects all of the child * sessions and expects that they are in a valid state to be connected. */ public void login(String userName, String password) throws DatabaseException { // Bug#3440544 Check if logged in already to stop the attempt to login more than once if (isLoggedIn) { throw ValidationException.alreadyLoggedIn(this.getName()); } else { if (this.eventManager != null) { this.eventManager.preLogin(this); } // Bug 3848021 - ensure the external transaction controller is initialized if (!isConnected()) { getServerPlatform().initializeExternalTransactionController(); } // Connection all sessions and initialize for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) { DatabaseSessionImpl session = (DatabaseSessionImpl) sessionEnum.next(); if (session.hasEventManager()) { session.getEventManager().preLogin(session); } session.getDatasourceLogin().setUserName(userName); session.getDatasourceLogin().setPassword(password); if (!session.isConnected()) { session.connect(); } } initializeDescriptors(); this.isLoggedIn = true; } }
/** * PUBLIC: Return a session broker that behaves as a client session broker. An acquire session * broker is done under the covers on each session inside the session broker, and a new broker is * returned. * * <p>NOTE: when finished with the client broker, it should be releases. See * releaseClientSessionBroker. */ public SessionBroker acquireClientSessionBroker() { log(SessionLog.FINER, SessionLog.CONNECTION, "acquire_client_session_broker"); SessionBroker clientBroker = copySessionBroker(); clientBroker.parent = this; clientBroker .getIdentityMapAccessorInstance() .setIdentityMapManager(getIdentityMapAccessorInstance().getIdentityMapManager()); clientBroker.commitManager = getCommitManager(); clientBroker.commandManager = getCommandManager(); clientBroker.externalTransactionController = getExternalTransactionController(); clientBroker.setServerPlatform(getServerPlatform()); String sessionName; AbstractSession serverSession; Iterator names = this.getSessionsByName().keySet().iterator(); while (names.hasNext()) { sessionName = (String) names.next(); serverSession = getSessionForName(sessionName); if (serverSession instanceof org.eclipse.persistence.sessions.server.ServerSession) { if (serverSession.getProject().hasIsolatedClasses()) { throw ValidationException.isolatedDataNotSupportedInSessionBroker(sessionName); } clientBroker.internalRegisterSession( sessionName, ((org.eclipse.persistence.sessions.server.ServerSession) serverSession) .acquireClientSession()); } else { throw ValidationException.cannotAcquireClientSessionFromSession(); } } clientBroker.initializeSequencing(); return clientBroker; }
/** Release any locally allocated sequence back to the global sequence pool. */ void afterCommitInternal(Map localSequences, Accessor accessor) { Iterator it = localSequences.entrySet().iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); String seqName = (String) entry.getKey(); Vector localSequenceForName = (Vector) entry.getValue(); if (!localSequenceForName.isEmpty()) { getPreallocationHandler().setPreallocated(seqName, localSequenceForName); // clear all localSequencesForName localSequenceForName.clear(); } } if (accessor != null) { getOwnerSession() .log( SessionLog.FINEST, SessionLog.SEQUENCING, "sequencing_afterTransactionCommitted", null, accessor); } else { getOwnerSession() .log( SessionLog.FINEST, SessionLog.SEQUENCING, "sequencing_afterTransactionCommitted", null); } }
/** * PUBLIC: set the integrityChecker. IntegrityChecker holds all the ClassDescriptor Exceptions. */ public void setIntegrityChecker(IntegrityChecker integrityChecker) { super.setIntegrityChecker(integrityChecker); for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) { AbstractSession session = (AbstractSession) sessionEnum.next(); session.setIntegrityChecker(integrityChecker); } }
/** * PUBLIC: Set the message log. * * @see #logMessages() */ public void setLog(Writer log) { super.setLog(log); for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) { AbstractSession session = (AbstractSession) sessionEnum.next(); session.setLog(log); } }
/** * PUBLIC: Set the profiler for the session. This allows for performance operations to be * profiled. */ public void setProfiler(SessionProfiler profiler) { super.setProfiler(profiler); for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) { AbstractSession session = (AbstractSession) sessionEnum.next(); session.setProfiler(profiler); } }
/** * INTERNAL: Set isSynchronized flag to indicate that members of session broker are synchronized. * This method should only be called by setSynchronized method of UnitOfWork obtained from either * DatabaseSession Broker or ClientSession Broker. */ public void setSynchronized(boolean synched) { if (!isServerSessionBroker()) { super.setSynchronized(synched); Iterator itSessions = getSessionsByName().values().iterator(); while (itSessions.hasNext()) { ((AbstractSession) itSessions.next()).setSynchronized(synched); } } }
/** PUBLIC: Return if this session is a server session broker. */ public boolean isServerSessionBroker() { for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) { AbstractSession session = (AbstractSession) sessionEnum.next(); if (session.isServerSession()) { return true; } } return false; }
/** * PUBLIC: Release the session. This does nothing by default, but allows for other sessions such * as the ClientSession to do something. */ public void release() { if (isClientSessionBroker()) { log(SessionLog.FINER, SessionLog.CONNECTION, "releasing_client_session_broker"); } AbstractSession session; for (Iterator enumtr = getSessionsByName().values().iterator(); enumtr.hasNext(); ) { session = (AbstractSession) enumtr.next(); session.release(); } super.release(); }
protected void initializeStates() { states = new State[NUMBER_OF_STATES]; Iterator itConnectedSequences = connectedSequences.iterator(); while (itConnectedSequences.hasNext()) { Sequence sequence = (Sequence) itConnectedSequences.next(); State state = getState(sequence.shouldUsePreallocation(), sequence.shouldUseTransaction()); if (state == null) { createState(sequence.shouldUsePreallocation(), sequence.shouldUseTransaction()); } } }
/** * PUBLIC: Disconnect from all databases. * * @exception EclipseLinkException if a transaction is active, you must rollback any active * transaction before logout. * @exception DatabaseException the database will also raise an error if their is an active * transaction, or a general error occurs. */ public void logout() throws DatabaseException { for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) { DatabaseSessionImpl session = (DatabaseSessionImpl) sessionEnum.next(); session.logout(); } if (!isClientSessionBroker()) { if (hasExternalTransactionController()) { getExternalTransactionController().clearSequencingListeners(); } } sequencing = null; isLoggedIn = false; }
/** INTERNAL: Rollback the transaction on all child sessions. */ protected void basicRollbackTransaction() throws DatabaseException { DatabaseException globalException = null; for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) { AbstractSession session = (AbstractSession) sessionEnum.next(); try { session.rollbackTransaction(); } catch (DatabaseException exception) { globalException = exception; } } if (globalException != null) { throw globalException; } }
/** PUBLIC: Return if all sessions are still connected to the database. */ public boolean isConnected() { if ((getSessionsByName() == null) || (getSessionsByName().isEmpty())) { return false; } for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) { AbstractSession session = (AbstractSession) sessionEnum.next(); if (!session.isConnected()) { return false; } } return true; }
/** * INTERNAL: Returns a number of member sessions that require sequencing callback. Always returns * 0 if sequencing is not connected. */ public int howManySequencingCallbacks() { if (this.isClientSessionBroker()) { return getParent().howManySequencingCallbacks(); } else { int nCallbacks = 0; Iterator itSessions = getSessionsByName().values().iterator(); while (itSessions.hasNext()) { if (((DatabaseSessionImpl) itSessions.next()).isSequencingCallbackRequired()) { nCallbacks++; } } return nCallbacks; } }
/** * PUBLIC: Register the session under its name. All of the session's descriptors must have already * been registered. The session should not be connected and descriptors should not be initialized. */ public void registerSession(String name, AbstractSession session) { session.setIsInBroker(true); getSessionsByName().put(name, session); session.setBroker(this); session.setName(name); // The keys/classes must also be used as some descriptors may be under multiple classes. Iterator descriptors = session.getDescriptors().values().iterator(); Iterator classes = session.getDescriptors().keySet().iterator(); while (descriptors.hasNext()) { ClassDescriptor descriptor = (ClassDescriptor) descriptors.next(); Class descriptorClass = (Class) classes.next(); getSessionNamesByClass().put(descriptorClass, name); getDescriptors().put(descriptorClass, descriptor); } }
/** INTERNAL: Acquires a special historical session for reading objects as of a past time. */ public org.eclipse.persistence.sessions.Session acquireHistoricalSession(AsOfClause clause) throws ValidationException { if (isServerSessionBroker()) { throw ValidationException.cannotAcquireHistoricalSession(); } // ? logMessage("acquire_client_session_broker", (Object[])null); SessionBroker historicalBroker = copySessionBroker(); String sessionName; AbstractSession session; Iterator names = this.getSessionsByName().keySet().iterator(); while (names.hasNext()) { sessionName = (String) names.next(); session = getSessionForName(sessionName); historicalBroker.registerSession(sessionName, session.acquireHistoricalSession(clause)); } return historicalBroker; }
/** PUBLIC: Return true if the pre-defined query is defined on the session. */ public boolean containsQuery(String queryName) { boolean containsQuery = getQueries().containsKey(queryName); if (isClientSessionBroker() && (containsQuery == false)) { String sessionName = null; AbstractSession ssession = null; Iterator names = this.getSessionsByName().keySet().iterator(); while (names.hasNext()) { sessionName = (String) names.next(); ssession = getSessionForName(sessionName); if (ssession instanceof org.eclipse.persistence.sessions.server.ClientSession) { if (((ClientSession) ssession).getParent().getBroker().containsQuery(queryName)) { return true; } } } } return containsQuery; }
// Bug#3551263 Override getQuery(String name, Vector arguments) in Session search through // the server session broker as well public DatabaseQuery getQuery(String name, Vector arguments) { DatabaseQuery query = super.getQuery(name, arguments); if (isClientSessionBroker() && (query == null)) { String sessionName = null; AbstractSession ssession = null; Iterator names = this.getSessionsByName().keySet().iterator(); while (names.hasNext()) { sessionName = (String) names.next(); ssession = getSessionForName(sessionName); if (ssession instanceof org.eclipse.persistence.sessions.server.ClientSession) { query = ((ClientSession) ssession).getParent().getBroker().getQuery(name, arguments); if (query != null) { return query; } } } } return query; }
/** * PUBLIC: Return the query from the session pre-defined queries with the given name. This allows * for common queries to be pre-defined, reused and executed by name. */ public DatabaseQuery getQuery(String name) { // Bug#3473441 Should always call super first to ensure any change in Session will be reflected // here. DatabaseQuery query = super.getQuery(name); if (isClientSessionBroker() && (query == null)) { String sessionName = null; AbstractSession ssession = null; Iterator names = this.getSessionsByName().keySet().iterator(); while (names.hasNext()) { sessionName = (String) names.next(); ssession = getSessionForName(sessionName); if (ssession instanceof org.eclipse.persistence.sessions.server.ClientSession) { query = ((ClientSession) ssession).getParent().getBroker().getQuery(name); if (query != null) { return query; } } } } return query; }
/** * INTERNAL: This method notifies the accessor that a particular sets of writes has completed. * This notification can be used for such thing as flushing the batch mechanism */ public void writesCompleted() { for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) { AbstractSession session = (AbstractSession) sessionEnum.next(); if (!session.isConnected()) { throw DatabaseException.databaseAccessorNotConnected(); } } for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) { AbstractSession session = (AbstractSession) sessionEnum.next(); session.writesCompleted(); } }
/** * INTERNAL: Commit the transaction on all child sessions. This assumes that the commit of the * transaction will not fail because all of the modification has already taken place and no errors * would have occurred. */ protected void basicCommitTransaction() throws DatabaseException { // Do one last check it make sure that all sessions are still connected. for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) { AbstractSession session = (AbstractSession) sessionEnum.next(); if (!session.isConnected()) { throw DatabaseException.databaseAccessorNotConnected(); } } for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) { AbstractSession session = (AbstractSession) sessionEnum.next(); session.commitTransaction(); } }
/** * INTERNAL: Allow each descriptor to initialize any dependencies on this session. This is done in * two passes to allow the inheritance to be resolved first. Normally the descriptors are added * before login, then initialized on login. */ public void initializeDescriptors() { // ClientSession initializes sequencing during construction, // however DatabaseSession and ServerSession normally call initializeSequencing() // in initializeDescriptors method. // Because initializeDescriptors() is not called for a session-member of a SessionBroker, // initializeSequencing() for the sessions should be called here. if (!isClientSessionBroker()) { for (Iterator enumtr = getSessionsByName().values().iterator(); enumtr.hasNext(); ) { DatabaseSessionImpl databaseSession = (DatabaseSessionImpl) enumtr.next(); databaseSession.initializeSequencing(); } if (hasExternalTransactionController()) { getExternalTransactionController().initializeSequencingListeners(); } } super.initializeDescriptors(); // Must reset project options to session broker project, as initialization occurs // with local projects. for (Iterator enumtr = getSessionsByName().values().iterator(); enumtr.hasNext(); ) { DatabaseSessionImpl databaseSession = (DatabaseSessionImpl) enumtr.next(); if (databaseSession.getProject().hasGenericHistorySupport()) { getProject().setHasGenericHistorySupport(true); } if (databaseSession.getProject().hasIsolatedClasses()) { getProject().setHasIsolatedClasses(true); } if (databaseSession.getProject().hasNonIsolatedUOWClasses()) { getProject().setHasNonIsolatedUOWClasses(true); } getProject() .getDefaultReadOnlyClasses() .addAll(databaseSession.getProject().getDefaultReadOnlyClasses()); } // ServerSessionBroker doesn't need sequencing. // Sequencing should be obtained either from the ClientSessionBroker or directly // from the ClientSession. if (isServerSessionBroker()) { sequencing = null; } }
/** INTERNAL: Conform the result if specified. */ protected Object conformResult( Object result, UnitOfWorkImpl unitOfWork, AbstractRecord arguments, boolean buildDirectlyFromRows) { if (getSelectionCriteria() != null) { ExpressionBuilder builder = getSelectionCriteria().getBuilder(); builder.setSession(unitOfWork.getRootSession(null)); builder.setQueryClass(getReferenceClass()); } // If the query is redirected then the collection returned might no longer // correspond to the original container policy. CR#2342-S.M. ContainerPolicy cp; if (getRedirector() != null) { cp = ContainerPolicy.buildPolicyFor(result.getClass()); } else { cp = getContainerPolicy(); } // This code is now a great deal different... For one, registration is done // as part of conforming. Also, this should only be called if one actually // is conforming. // First scan the UnitOfWork for conforming instances. // This will walk through the entire cache of registered objects. // Let p be objects from result not in the cache. // Let c be objects from cache. // Presently p intersect c = empty set, but later p subset c. // By checking cache now doesConform will be called p fewer times. Map indexedInterimResult = unitOfWork.scanForConformingInstances( getSelectionCriteria(), getReferenceClass(), arguments, this); Cursor cursor = null; // In the case of cursors just conform/register the initially read collection. if (cp.isCursorPolicy()) { cursor = (Cursor) result; cp = ContainerPolicy.buildPolicyFor(ClassConstants.Vector_class); // In nested UnitOfWork session might have been session of the parent. cursor.setSession(unitOfWork); result = cursor.getObjectCollection(); // for later incremental conforming... cursor.setInitiallyConformingIndex(indexedInterimResult); cursor.setSelectionCriteriaClone(getSelectionCriteria()); cursor.setTranslationRow(arguments); } // Now conform the result from the database. // Remove any deleted or changed objects that no longer conform. // Deletes will only work for simple queries, queries with or's or anyof's may not return // correct results when untriggered indirection is in the model. Vector fromDatabase = null; // When building directly from rows, one of the performance benefits // is that we no longer have to wrap and then unwrap the originals. // result is just a vector, not a container of wrapped originals. if (buildDirectlyFromRows) { Vector rows = (Vector) result; fromDatabase = new Vector(rows.size()); for (int i = 0; i < rows.size(); i++) { Object object = rows.elementAt(i); // null is placed in the row collection for 1-m joining to filter duplicate rows. if (object != null) { Object clone = conformIndividualResult( object, unitOfWork, arguments, getSelectionCriteria(), indexedInterimResult, buildDirectlyFromRows); if (clone != null) { fromDatabase.addElement(clone); } } } } else { fromDatabase = new Vector(cp.sizeFor(result)); AbstractSession sessionToUse = unitOfWork.getParent(); for (Object iter = cp.iteratorFor(result); cp.hasNext(iter); ) { Object object = cp.next(iter, sessionToUse); Object clone = conformIndividualResult( object, unitOfWork, arguments, getSelectionCriteria(), indexedInterimResult, buildDirectlyFromRows); if (clone != null) { fromDatabase.addElement(clone); } } } // Now add the unwrapped conforming instances into an appropriate container. // Wrapping is done automatically. // Make sure a vector of exactly the right size is returned. Object conformedResult = cp.containerInstance(indexedInterimResult.size() + fromDatabase.size()); Object eachClone; for (Iterator enumtr = indexedInterimResult.values().iterator(); enumtr.hasNext(); ) { eachClone = enumtr.next(); cp.addInto(eachClone, conformedResult, unitOfWork); } for (Enumeration enumtr = fromDatabase.elements(); enumtr.hasMoreElements(); ) { eachClone = enumtr.nextElement(); cp.addInto(eachClone, conformedResult, unitOfWork); } if (cursor != null) { cursor.setObjectCollection((Vector) conformedResult); // For nested UOW must copy all in object collection to // initiallyConformingIndex, as some of these could have been from // the parent UnitOfWork. if (unitOfWork.isNestedUnitOfWork()) { for (Enumeration enumtr = cursor.getObjectCollection().elements(); enumtr.hasMoreElements(); ) { Object clone = enumtr.nextElement(); indexedInterimResult.put(clone, clone); } } return cursor; } else { return conformedResult; } }
/** * INTERNAL: Called in the end of beforeCompletion of external transaction sychronization * listener. Close the managed sql connection corresponding to the external transaction, if * applicable releases accessor. */ public void releaseJTSConnection() { for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) { AbstractSession session = (AbstractSession) sessionEnum.next(); session.releaseJTSConnection(); } }
/** INTERNAL: Begin the transaction on all child sessions. */ protected void basicBeginTransaction() throws DatabaseException { for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) { AbstractSession session = (AbstractSession) sessionEnum.next(); session.beginTransaction(); } }
/** * ADVANCED: Answers the past time this session is as of. Only meaningfull for special historical * sessions. * * @return An immutable object representation of the past time. <code>null</code> if no clause * set, or this a regular session. * @see org.eclipse.persistence.expressions.AsOfClause * @see #acquireSessionAsOf(java.lang.Number) * @see #acquireSessionAsOf(java.util.Date) * @see #hasAsOfClause */ public AsOfClause getAsOfClause() { for (Iterator enumtr = getSessionsByName().values().iterator(); enumtr.hasNext(); ) { return ((AbstractSession) enumtr.next()).getAsOfClause(); } return null; }
protected void onConnectAllSequences() { connectedSequences = new Vector(); boolean shouldUseTransaction = false; boolean shouldUsePreallocation = false; boolean shouldAcquireValueAfterInsert = false; Iterator descriptors = getOwnerSession().getDescriptors().values().iterator(); while (descriptors.hasNext()) { ClassDescriptor descriptor = (ClassDescriptor) descriptors.next(); // Find root sequence, because inheritance needs to be resolved here. // TODO: The way we initialize sequencing needs to be in line with descriptor init. ClassDescriptor parentDescriptor = descriptor; while (!parentDescriptor.usesSequenceNumbers() && parentDescriptor.isChildDescriptor()) { ClassDescriptor newDescriptor = getOwnerSession() .getDescriptor(parentDescriptor.getInheritancePolicy().getParentClass()); // Avoid issue with error cases of self parent, or null parent. if ((newDescriptor == null) || (newDescriptor == parentDescriptor)) { break; } parentDescriptor = newDescriptor; } if (!parentDescriptor.usesSequenceNumbers()) { continue; } String seqName = parentDescriptor.getSequenceNumberName(); Sequence sequence = getSequence(seqName); if (sequence == null) { sequence = new DefaultSequence(seqName); getOwnerSession().getDatasourcePlatform().addSequence(sequence); } // PERF: Initialize the sequence, this avoid having to look it up every time. descriptor.setSequence(sequence); if (connectedSequences.contains(sequence)) { continue; } try { if (sequence instanceof DefaultSequence && !connectedSequences.contains(getDefaultSequence())) { getDefaultSequence().onConnect(getOwnerSession().getDatasourcePlatform()); connectedSequences.add(0, getDefaultSequence()); shouldUseTransaction |= getDefaultSequence().shouldUseTransaction(); shouldUsePreallocation |= getDefaultSequence().shouldUsePreallocation(); shouldAcquireValueAfterInsert |= getDefaultSequence().shouldAcquireValueAfterInsert(); } sequence.onConnect(getOwnerSession().getDatasourcePlatform()); connectedSequences.addElement(sequence); shouldUseTransaction |= sequence.shouldUseTransaction(); shouldUsePreallocation |= sequence.shouldUsePreallocation(); shouldAcquireValueAfterInsert |= sequence.shouldAcquireValueAfterInsert(); } catch (RuntimeException ex) { // defaultSequence has to disconnect the last for (int i = connectedSequences.size() - 1; i >= 0; i--) { try { Sequence sequenceToDisconnect = (Sequence) connectedSequences.elementAt(i); sequenceToDisconnect.onDisconnect(getOwnerSession().getDatasourcePlatform()); } catch (RuntimeException ex2) { // ignore } } connectedSequences = null; throw ex; } } if (shouldAcquireValueAfterInsert && !shouldUsePreallocation) { whenShouldAcquireValueForAll = AFTER_INSERT; } else if (!shouldAcquireValueAfterInsert && shouldUsePreallocation) { whenShouldAcquireValueForAll = BEFORE_INSERT; } atLeastOneSequenceShouldUseTransaction = shouldUseTransaction; atLeastOneSequenceShouldUsePreallocation = shouldUsePreallocation; }