/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 1998, 2018 IBM Corporation and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
//     12/24/2012-2.5 Guy Pelletier
//       - 389090: JPA 2.1 DDL Generation Support
//     01/11/2013-2.5 Guy Pelletier
//       - 389090: JPA 2.1 DDL Generation Support
//     04/24/2017-2.6 Jody Grassel
//       - 515712: ServerSession numberOfNonPooledConnectionsUsed can become invalid when Exception is thrown connecting accessor
package org.eclipse.persistence.sessions.server;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.ConcurrencyException;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.databaseaccess.Accessor;
import org.eclipse.persistence.internal.databaseaccess.DatabaseCall;
import org.eclipse.persistence.internal.sequencing.SequencingServer;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.DatabaseSessionImpl;
import org.eclipse.persistence.internal.sessions.ExclusiveIsolatedClientSession;
import org.eclipse.persistence.internal.sessions.IsolatedClientSession;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.queries.Call;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.sessions.Login;
import org.eclipse.persistence.sessions.Project;

/**
 * Implementation of Server
 * INTERNAL:
 * The public interface should be used.
 * <p>
 * <b>Purpose</b>: A single session that supports multiple user/clients connection at the same time.
 * <p>
 * <b>Description</b>: This session supports a shared session that can be used by multiple users
 * or clients in a three-tiered application.  It brokers client sessions to allow read and write access
 * through a unified object cache.  The server session uses a single connection pool by default, but allows multiple connection
 * pools and separate read/write pools to be configured.  All changes to objects and the database must be done through
 * a unit of work acquired from the client session, this allows the changes to occur in a transactional object
 * space and under a exclusive database connection.
 * <p>
 * <b>Responsibilities</b>:
 *    <ul>
 *    <li> Connection pooling.
 *    <li> Reading objects and maintaining the object cache.
 *    <li> Brokering client sessions.
 *    <li> Requiring the UnitOfWork to be used for modification.
 *    </ul>
 *
 * @see Server
 * @see ClientSession
 * @see org.eclipse.persistence.sessions.UnitOfWork UnitOfWork
 */
public class ServerSession extends DatabaseSessionImpl implements Server {
    protected ConnectionPool readConnectionPool;
    protected Map<String, ConnectionPool> connectionPools;
    protected ConnectionPolicy defaultConnectionPolicy;
    protected int numberOfNonPooledConnectionsUsed;
    protected int maxNumberOfNonPooledConnections;

    public static final int NO_MAX = -1;
    public static final String DEFAULT_POOL = "default";
    public static final String NOT_POOLED = "not-pooled";

    /**
     * INTERNAL:
     * Create and return a new default server session.
     * @see Project#createServerSession()
     */
    public ServerSession() {
        super();
        this.connectionPools = new HashMap<>(10);
    }

    /**
     * INTERNAL:
     * Create and return a new server session.
     * @see Project#createServerSession()
     */
    public ServerSession(Login login) {
        this(new Project(login));
    }

    /**
     * INTERNAL:
     * Create and return a new server session.
     * @see Project#createServerSession(int, int)
     */
    public ServerSession(Login login, int minNumberOfPooledConnection, int maxNumberOfPooledConnection) {
        this(new Project(login), minNumberOfPooledConnection, maxNumberOfPooledConnection);
    }

    /**
     * INTERNAL:
     * Create and return a new default server session.
     * @see Project#createServerSession(ConnectionPolicy)
     */
    public ServerSession(Login login, ConnectionPolicy defaultConnectionPolicy) {
        this(new Project(login), defaultConnectionPolicy);
    }

    /**
     * INTERNAL:
     * Create and return a new server session.
     * @see Project#createServerSession()
     *
     * This is used by JPA, and SessionManager.
     */
    public ServerSession(Project project) {
        this(project, ConnectionPool.MIN_CONNECTIONS, ConnectionPool.MAX_CONNECTIONS);
    }

    /**
     * INTERNAL:
     * Create and return a new server session.
     * @see Project#createServerSession(int, int)
     */
    public ServerSession(Project project, int minNumberOfPooledConnection, int maxNumberOfPooledConnection) {
        this(project, ConnectionPool.INITIAL_CONNECTIONS, minNumberOfPooledConnection, maxNumberOfPooledConnection);
    }

    /**
     * INTERNAL:
     * Create and return a new server session.
     * @see Project#createServerSession(int, int, int)
     */
    public ServerSession(Project project, int initialNumberOfPooledConnection, int minNumberOfPooledConnection, int maxNumberOfPooledConnection) {
        this(project, new ConnectionPolicy(DEFAULT_POOL), initialNumberOfPooledConnection, minNumberOfPooledConnection, maxNumberOfPooledConnection, null, null);
    }

    /**
     * INTERNAL:
     * Create and return a new server session.
     * @see Project#createServerSession(int, int)
     *
     * @param project the project associated with this session
     * @param minNumberOfPooledConnection the minimum number of connections in the pool
     * @param maxNumberOfPooledConnection the maximum number of connections in the pool
     * @param readLogin the login used to create the read connection pool
     */
    public ServerSession(Project project, int minNumberOfPooledConnection, int maxNumberOfPooledConnection, Login readLogin) {
        this(project, minNumberOfPooledConnection, maxNumberOfPooledConnection, readLogin, null);
    }

    /**
     * INTERNAL:
     * Create and return a new server session.
     * @see Project#createServerSession(int, int)
     */
    public ServerSession(Project project, int minNumberOfPooledConnection, int maxNumberOfPooledConnection, Login readLogin, Login sequenceLogin) {
        this(project, new ConnectionPolicy(DEFAULT_POOL), ConnectionPool.INITIAL_CONNECTIONS, minNumberOfPooledConnection, maxNumberOfPooledConnection, readLogin, sequenceLogin);
    }

    /**
     * INTERNAL:
     * Create and return a new server session.
     * <p>
     * Configure the initial, min and max number of connections for the default pool.
     * <p>
     * Configure the default connection policy to be used.
     * This policy is used on the "acquireClientSession()" protocol.
     * <p>
     * Use the login from the project for the write pool. Use the passed
     * in login for the read pool, if specified, or the project login if not.
     * Use the sequenceLogin, if specified, for creating a connection pool
     * to be used by sequencing through SequencingConnectionHandler
     * sequenceLogin *MUST*:
     * <br>1. specify *NON-JTS* connections (such as NON_JTS driver or read-only datasource);
     * <br>2. sequenceLogin.shouldUseExternalTransactionController()==false
     *
     * @param project the project associated with this session
     * @param defaultConnectionPolicy the default connection policy to be used
     * @param initialNumberOfPooledConnections the minimum number of connections in the pool
     * @param minNumberOfPooledConnections the minimum number of connections in the pool
     * @param maxNumberOfPooledConnections the maximum number of connections in the pool
     * @param readLogin the login used to create the read connection pool
     * @param sequenceLogin the login used to create a connection pool for sequencing
     *
     * @see Project#createServerSession(int, int)
     */
    public ServerSession(Project project, ConnectionPolicy defaultConnectionPolicy, int initialNumberOfPooledConnections, int minNumberOfPooledConnections, int maxNumberOfPooledConnections, Login readLogin, Login sequenceLogin) {
        super(project);
        this.connectionPools = new HashMap(10);
        this.defaultConnectionPolicy = defaultConnectionPolicy;
        this.maxNumberOfNonPooledConnections = 50;
        this.numberOfNonPooledConnectionsUsed = 0;

        // Configure the default write connection pool.
        ConnectionPool pool = null;
        if (project.getDatasourceLogin().shouldUseExternalConnectionPooling()) {
            pool = new ExternalConnectionPool(DEFAULT_POOL, project.getDatasourceLogin(), this);
        } else {
            pool = new ConnectionPool(DEFAULT_POOL, project.getDatasourceLogin(), initialNumberOfPooledConnections, minNumberOfPooledConnections, maxNumberOfPooledConnections, this);
        }
        this.connectionPools.put(DEFAULT_POOL, pool);

        // If a read login was not used, then share the same connection pool for reading and writing.
        if (readLogin != null) {
            setReadConnectionPool(readLogin);
        } else {
            setReadConnectionPool(pool);
        }

        if (sequenceLogin != null) {
            // Even if getSequencingControl().setShouldUseSeparateConnection(true) is specified,
            // SequencingConnectionPool is NOT created unless the session has at least one Sequence object
            // that requires transaction.
            getSequencingControl().setShouldUseSeparateConnection(true);
            getSequencingControl().setLogin(sequenceLogin);
        }
    }

    /**
     * INTERNAL:
     * Create and return a new server session.
     * @see Project#createServerSession(ConnectionPolicy)
     */
    public ServerSession(Project project, ConnectionPolicy defaultConnectionPolicy) {
        this(project, defaultConnectionPolicy, null);
    }

    /**
     * INTERNAL:
     * Create and return a new server session.
     * @see Project#createServerSession(ConnectionPolicy)
     */
    public ServerSession(Project project, ConnectionPolicy defaultConnectionPolicy, Login readLogin) {
        this(project, defaultConnectionPolicy, readLogin, null);
    }

    /**
     * INTERNAL:
     * Create and return a new server session.
     * @see Project#createServerSession(ConnectionPolicy)
     */
    public ServerSession(Project project, ConnectionPolicy defaultConnectionPolicy, Login readLogin, Login sequenceLogin) {
        this(project, defaultConnectionPolicy, ConnectionPool.INITIAL_CONNECTIONS, ConnectionPool.MIN_CONNECTIONS, ConnectionPool.MAX_CONNECTIONS, readLogin, sequenceLogin);
    }

    /**
     * INTERNAL:
     * Allocate the client's connection resource.
     */
    public void acquireClientConnection(ClientSession clientSession) throws DatabaseException, ConcurrencyException {
        if (clientSession.getConnectionPolicy().isPooled()) {
            ConnectionPool pool = this.connectionPools.get(clientSession.getConnectionPolicy().getPoolName());
            Accessor accessor = pool.acquireConnection();
            clientSession.addWriteConnection(pool.getName(), accessor);
        } else {
            if (this.maxNumberOfNonPooledConnections != NO_MAX) {
                synchronized (this) {
                    while (this.numberOfNonPooledConnectionsUsed >= this.maxNumberOfNonPooledConnections) {
                        try {
                            wait();// Notify is called when connections are released.
                        } catch (InterruptedException exception) {
                            throw ConcurrencyException.waitFailureOnServerSession(exception);
                        }
                    }
                    this.numberOfNonPooledConnectionsUsed++;
                }
            }
            try {
            Accessor accessor = clientSession.getLogin().buildAccessor();
            clientSession.connect(accessor);
            clientSession.addWriteConnection(ServerSession.NOT_POOLED, accessor);
            } catch (DatabaseException dbe) {
                // A DatabaseException was thrown, undo the numberOfNonPooledConnectionsUsed counter increment otherwise
                // the counter will be out of synch with the actual number of connections.
                if (this.maxNumberOfNonPooledConnections != NO_MAX) {
                    synchronized (this) {
                        this.numberOfNonPooledConnectionsUsed--;
                        notify();
                    }
                }
                throw dbe;
            }
            
        }
    }

    /**
     * PUBLIC:
     * Return a client session for this server session.
     * Each user/client connected to this server session must acquire there own client session
     * to communicate to the server through.
     * This method allows for a client session to be acquired sharing the same login as the server session.
     */
    @Override
    public ClientSession acquireClientSession() throws DatabaseException {
        return acquireClientSession(getDefaultConnectionPolicy());
    }

    /**
     * PUBLIC:
     * Return a client session for this server session.
     * Each user/client connected to this server session must acquire there own client session
     * to communicate to the server through.
     * This method allows for a client session to be acquired sharing the same login as the server session.
     * The properties set into the client session at construction time, before postAcquireClientSession is risen.
     */
    public ClientSession acquireClientSession(Map properties) throws DatabaseException {
        return acquireClientSession(getDefaultConnectionPolicy(), properties);
    }

    /**
     * PUBLIC:
     * Return a client session for this server session.
     * Each user/client connected to this server session must acquire there own client session
     * to communicate to the server through.
     * This method allows for a client session to be acquired sharing its connection from a pool
     * of connection allocated on the server session.
     * By default this uses a lazy connection policy.
     */
    @Override
    public ClientSession acquireClientSession(String poolName) throws DatabaseException {
        return acquireClientSession(new ConnectionPolicy(poolName));
    }

    /**
     * PUBLIC:
     * Return a client session for this server session.
     * Each user/client connected to this server session must acquire there own client session
     * to communicate to the server through.
     * This method allows for a client session to be acquired sharing its connection from a pool
     * of connection allocated on the server session.
     * By default this uses a lazy connection policy.
     * The properties set into the client session at construction time, before postAcquireClientSession is risen.
     */
    public ClientSession acquireClientSession(String poolName, Map properties) throws DatabaseException {
        return acquireClientSession(new ConnectionPolicy(poolName), properties);
    }

    /**
     * PUBLIC:
     * Return a client session for this server session.
     * Each user/client connected to this server session must acquire there own client session
     * to communicate to the server through.
     * The client must provide its own login to use, and the client session returned
     * will have its own exclusive database connection.  This connection will be used to perform
     * all database modification for all units of work acquired from the client session.
     * By default this does not use a lazy connection policy.
     */
    @Override
    public ClientSession acquireClientSession(Login login) throws DatabaseException {
        return acquireClientSession(new ConnectionPolicy(login));
    }

    /**
     * PUBLIC:
     * Return a client session for this server session.
     * Each user/client connected to this server session must acquire there own client session
     * to communicate to the server through.
     * The client must provide its own login to use, and the client session returned
     * will have its own exclusive database connection.  This connection will be used to perform
     * all database modification for all units of work acquired from the client session.
     * By default this does not use a lazy connection policy.
     * The properties set into the client session at construction time, before postAcquireClientSession is risen.
     */
    public ClientSession acquireClientSession(Login login, Map properties) throws DatabaseException {
        return acquireClientSession(new ConnectionPolicy(login), properties);
    }

    /**
     * PUBLIC:
     * Return a client session for this server session.
     * The connection policy specifies how the client session's connection will be acquired.
     */
    @Override
    public ClientSession acquireClientSession(ConnectionPolicy connectionPolicy) throws DatabaseException, ValidationException {
        return acquireClientSession(connectionPolicy, null);
    }

    /**
     * PUBLIC:
     * Return a client session for this server session.
     * The connection policy specifies how the client session's connection will be acquired.
     * The properties set into the client session at construction time, before postAcquireClientSession is risen.
     */
    public ClientSession acquireClientSession(ConnectionPolicy connectionPolicy, Map properties) throws DatabaseException, ValidationException {
        if (!isConnected()) {
            throw ValidationException.loginBeforeAllocatingClientSessions();
        }
        if (!connectionPolicy.isPooled() && (connectionPolicy.getLogin() == null)) {
            //the user has passed in a connection policy with no login info. Use the
            //default info from the default connection policy
            connectionPolicy.setPoolName(getDefaultConnectionPolicy().getPoolName());
            connectionPolicy.setLogin(getDefaultConnectionPolicy().getLogin());
        }
        if (connectionPolicy.isPooled()) {
            ConnectionPool pool = this.connectionPools.get(connectionPolicy.getPoolName());
            if (pool == null) {
                throw ValidationException.poolNameDoesNotExist(connectionPolicy.getPoolName());
            }
            connectionPolicy.setLogin(pool.getLogin());
        }
        ClientSession client = null;
        if (getProject().hasIsolatedClasses()) {
            if (connectionPolicy.isExclusive()) {
                client = new ExclusiveIsolatedClientSession(this, connectionPolicy, properties);
            } else {
                client = new IsolatedClientSession(this, connectionPolicy, properties);
            }
        } else {
            if (connectionPolicy.isExclusiveIsolated()) {
                throw ValidationException.clientSessionCanNotUseExclusiveConnection();
            } else if(connectionPolicy.isExclusiveAlways()) {
                client = new ExclusiveIsolatedClientSession(this, connectionPolicy, properties);
            } else {
                client = new ClientSession(this, connectionPolicy, properties);
            }
        }
        if (isFinalizersEnabled()) {
            client.registerFinalizer();
        }
        if (!connectionPolicy.isLazy()) {
            acquireClientConnection(client);
        }
        if (shouldLog(SessionLog.FINER, SessionLog.CONNECTION)) {
            log(SessionLog.FINER, SessionLog.CONNECTION, "client_acquired", String.valueOf(System.identityHashCode(client)));
        }

        return client;
    }

    /**
     * INTERNAL:
     * Acquires a special historical session for reading objects as of a past time.
     */
    @Override
    public org.eclipse.persistence.sessions.Session acquireHistoricalSession(org.eclipse.persistence.history.AsOfClause clause) throws ValidationException {
        throw ValidationException.cannotAcquireHistoricalSession();
    }

    /**
     * PUBLIC:
     * Return a unit of work for this session.
     * The unit of work is an object level transaction that allows
     * a group of changes to be applied as a unit.
     * First acquire a client session as server session does not allow direct units of work.
     *
     * @see UnitOfWorkImpl
     */
    @Override
    public UnitOfWorkImpl acquireUnitOfWork() {
        return acquireClientSession().acquireUnitOfWork();
    }

    /**
     * PUBLIC:
     * Add the connection pool.
     * Connections are pooled to share and restrict the number of database connections.
     */
    @Override
    public void addConnectionPool(String poolName, Login login, int minNumberOfConnections, int maxNumberOfConnections) throws ValidationException {
        if (minNumberOfConnections > maxNumberOfConnections) {
            throw ValidationException.maxSizeLessThanMinSize();
        }
        if (isConnected()) {
            throw ValidationException.poolsMustBeConfiguredBeforeLogin();
        }
        ConnectionPool pool = null;
        if (login.shouldUseExternalConnectionPooling()) {
            pool = new ExternalConnectionPool(poolName, login, this);
        } else {
            pool = new ConnectionPool(poolName, login, minNumberOfConnections, maxNumberOfConnections, this);
        }
        addConnectionPool(pool);
    }

    /**
     * PUBLIC:
     * Connection are pooled to share and restrict the number of database connections.
     */
    @Override
    public void addConnectionPool(ConnectionPool pool) {
        pool.setOwner(this);
        getConnectionPools().put(pool.getName(), pool);

    }

    /**
     * INTERNAL:
     * Return a read connection from the read pool.
     * Note that depending on the type of pool this may be a shared or exclusive connection.
     * Each query execution is assigned a read connection.
     */
    public Accessor allocateReadConnection() {
        Accessor connection = this.readConnectionPool.acquireConnection();
        //if connection is using external connection pooling then the event will be risen right after it connects.
        if (!connection.usesExternalConnectionPooling()) {
            if (this.eventManager != null) {
                this.eventManager.postAcquireConnection(connection);
            }
        }
        return connection;
    }

    /**
     * INTERNAL:
     * Startup the server session, also startup all of the connection pools.
     */
    @Override
    public void connect() {
        // make sure pools correspond to their logins
        updateStandardConnectionPools();
        // Configure the read pool
        this.readConnectionPool.startUp();
        setAccessor(allocateReadConnection());
        releaseReadConnection(getAccessor());

        for (ConnectionPool pool : getConnectionPools().values()) {
            pool.startUp();
        }
    }

    /**
     * INTERNAL:
     * Disconnect the accessor only.
     */
    @Override
    public void disconnect() throws DatabaseException {
        try {
            super.disconnect();
        } catch (DatabaseException ex) {
            // the exception caused by attempt to disconnect session's accessor - ignore it.
        }
    }

    /**
     * INTERNAL:
     * Return the connections to use for the query execution.
     */
    @Override
    public List<Accessor> getAccessors(Call call, AbstractRecord translationRow, DatabaseQuery query) {
        // Check for partitioning.
        List<Accessor> accessors = null;
        if (query.getPartitioningPolicy() != null) {
            accessors = query.getPartitioningPolicy().getConnectionsForQuery(this, query, translationRow);
            if (accessors != null) {
                return accessors;
            }
        }
        if ((query.getDescriptor() != null) && (query.getDescriptor().getPartitioningPolicy() != null)) {
            accessors = query.getDescriptor().getPartitioningPolicy().getConnectionsForQuery(this, query, translationRow);
            if (accessors != null) {
                return accessors;
            }
        }
        if (this.partitioningPolicy != null) {
            accessors = this.partitioningPolicy.getConnectionsForQuery(this, query, translationRow);
            if (accessors != null) {
                return accessors;
            }
        }
        // accessors == null
        accessors = new ArrayList(1);
        accessors.add(this.readConnectionPool.acquireConnection());
        return accessors;
    }

    /**
     * INTERNAL:
     * Execute the call on the correct connection accessor.
     * By default the server session executes calls using is read connection pool.
     * A connection is allocated for the execution of the query, then released back to the pool.
     * If partitioning is used the partition policy can use a different connection pool, or even
     * execute the call on multiple connections.
     */
    @Override
    public Object executeCall(Call call, AbstractRecord translationRow, DatabaseQuery query) throws DatabaseException {
        RuntimeException exception = null;
        Object result = null;
        boolean accessorAllocated = false;
        if (query.getAccessors() == null) {
            List<Accessor> accessors = getAccessors(call, translationRow, query);
            query.setAccessors(accessors);
            if (this.eventManager != null) {
                for (Accessor accessor : accessors) {
                    //if connection is using external connection pooling then the event will be risen right after it connects.
                    if (!accessor.usesExternalConnectionPooling()) {
                        this.eventManager.postAcquireConnection(accessor);
                    }
                }
            }
            accessorAllocated = true;
        }
        try {
            result = basicExecuteCall(call, translationRow, query);
        } catch (RuntimeException caughtException) {
            exception = caughtException;
        } finally {
            // EL Bug 244241 - connection not released on query timeout when cursor used
            // Don't release the cursoredStream connection until Stream is closed
            // or unless an exception occurred executing the call.
            if (call.isFinished() || exception != null) {
                if (accessorAllocated) {
                    try {
                        releaseConnectionAfterCall(query);
                    } catch (RuntimeException releaseException) {
                        if (exception == null) {
                            throw releaseException;
                        }
                        //else ignore
                    }
                }
            } else {
                if (query.isObjectLevelReadQuery()) {
                    ((DatabaseCall)call).setHasAllocatedConnection(accessorAllocated);
                }
            }
            if (exception != null) {
                throw exception;
            }
        }
        return result;
    }

    /**
     * INTERNAL:
     * Release (if required) connection after call.
     */
    @Override
    public void releaseConnectionAfterCall(DatabaseQuery query) {
        RuntimeException exception = null;
        for (Accessor accessor : query.getAccessors()) {
            //if connection is using external connection pooling then the event has been risen right before it disconnected.
            try {
                if (!accessor.usesExternalConnectionPooling()) {
                    preReleaseConnection(accessor);
                }
                accessor.getPool().releaseConnection(accessor);
            } catch (RuntimeException ex) {
                if (exception == null) {
                    exception = ex;
                }
            }
        }
        query.setAccessors(null);
        if (exception != null) {
            throw exception;
        }
    }

    /**
     * PUBLIC:
     * Return the results from executing the database query.
     * The query arguments are passed in as a List of argument values in the same order as the query arguments.
     */
    @Override
    public Object executeQuery(DatabaseQuery query, List argumentValues) throws DatabaseException {
        if (query == null) {
            throw QueryException.queryNotDefined();
        }
        query.checkDescriptor(this);
        ClassDescriptor descriptor = query.getDescriptor();
        AbstractRecord row = query.rowFromArguments(argumentValues, this);
        if (query.isObjectBuildingQuery() && descriptor != null && !descriptor.getCachePolicy().isSharedIsolation()) {
            ClientSession client = acquireClientSession();
            Object result = null;
            try {
                result = client.executeQuery(query, row);
            } finally {
                client.release();
            }
            return result;
        }
        return super.executeQuery( query,  row);
    }

    /**
     * PUBLIC:
     * Return the pool by name.
     */
    @Override
    public ConnectionPool getConnectionPool(String poolName) {
        return this.connectionPools.get(poolName);
    }

    /**
     * INTERNAL:
     * Connection are pooled to share and restrict the number of database connections.
     */
    public Map<String, ConnectionPool> getConnectionPools() {
        return connectionPools;
    }

    /**
     * PUBLIC:
     * The default connection policy is used by default by the acquireClientConnection() protocol.
     * By default it is a connection pool with min 5 and max 10 lazy pooled connections.
     */
    @Override
    public ConnectionPolicy getDefaultConnectionPolicy() {
        if (this.defaultConnectionPolicy == null) {
            this.defaultConnectionPolicy = new ConnectionPolicy(DEFAULT_POOL);
        }
        return this.defaultConnectionPolicy;
    }

    /**
     * PUBLIC:
     * Return the default connection pool.
     */
    @Override
    public ConnectionPool getDefaultConnectionPool() {
        return getConnectionPool(DEFAULT_POOL);
    }

    /**
     * INTERNAL:
     * Gets the session which this query will be executed on.
     * Generally will be called immediately before the call is translated,
     * which is immediately before session.executeCall.
     * <p>
     * Since the execution session also knows the correct datasource platform
     * to execute on, it is often used in the mappings where the platform is
     * needed for type conversion, or where calls are translated.
     * <p>
     * Is also the session with the accessor.  Will return a ClientSession if
     * it is in transaction and has a write connection.
     * @return a session with a live accessor
     * @param query may store session name or reference class for brokers case
     */
    @Override
    public AbstractSession getExecutionSession(DatabaseQuery query) {
        if (query.isObjectLevelModifyQuery()) {
            throw QueryException.invalidQueryOnServerSession(query);
        }
        return this;
    }

    /**
     * PUBLIC:
     * Return the number of non-pooled database connections allowed.
     * This can be enforced to make up for the resource limitation of most JDBC drivers and database clients.
     * By default this is 50.
     */
    @Override
    public int getMaxNumberOfNonPooledConnections() {
        return maxNumberOfNonPooledConnections;
    }

    /**
     * INTERNAL:
     * Return the current number of non-pooled connections in use.
     */
    public int getNumberOfNonPooledConnectionsUsed() {
        return numberOfNonPooledConnectionsUsed;
    }

    /**
     * INTERNAL:
     * Return the login for the read connection.  Used by the platform autodetect feature
     */
    @Override
    protected Login getReadLogin(){
        return this.readConnectionPool.getLogin();
    }


    /**
     * PUBLIC:
     * Return the read connection pool.
     * The read connection pool handles allocating connection for read queries.
     */
    @Override
    public ConnectionPool getReadConnectionPool() {
        return readConnectionPool;
    }

    /**
     * PUBLIC:
     * Return if this session has been connected to the database.
     */
    @Override
    public boolean isConnected() {
        if (this.readConnectionPool == null) {
            return false;
        }

        return this.readConnectionPool.isConnected();
    }

    /**
     * INTERNAL:
     * Return if this session is a server session.
     */
    @Override
    public boolean isServerSession() {
        return true;
    }

    /**
     * PUBLIC:
     * Shutdown the server session, also shutdown all of the connection pools.
     */
    @Override
    public void logout() {
        try {
            super.logout();
        } finally {
            this.readConnectionPool.shutDown();

            for (Iterator poolsEnum = getConnectionPools().values().iterator(); poolsEnum.hasNext();) {
                ((ConnectionPool)poolsEnum.next()).shutDown();
            }
        }
    }

    /**
     * INTERNAL:
     * Release any invalid connection in the client session.
     */
    public void releaseInvalidClientSession(ClientSession clientSession) throws DatabaseException {
        for (Iterator<Accessor> accessors = clientSession.getWriteConnections().values().iterator(); accessors.hasNext(); ) {
            Accessor accessor = accessors.next();
            if (!accessor.isValid()) {
                if (clientSession.getConnectionPolicy().isPooled()) {
                    try {
                        accessor.getPool().releaseConnection(accessor);
                    } catch (Exception ignore) {}
                } else {
                    try {
                    if (!accessor.usesExternalConnectionPooling()) {
                        clientSession.disconnect(accessor);
                    } else {
                        accessor.closeConnection();
                    }
                    } finally {
                    if (this.maxNumberOfNonPooledConnections != NO_MAX) {
                        synchronized (this) {
                            this.numberOfNonPooledConnectionsUsed--;
                            notify();
                        }
                    }
                }
                }
                accessors.remove();
            }
        }
    }

    /**
     * INTERNAL:
     * Release the clients connection resource.
     */
    public void releaseClientSession(ClientSession clientSession) throws DatabaseException {
        if (clientSession.getConnectionPolicy().isPooled()) {
            for (Accessor accessor : clientSession.getWriteConnections().values()) {
                //if connection is using external connection pooling then the event has been risen right before it disconnected.
                if(!accessor.usesExternalConnectionPooling()) {
                    clientSession.preReleaseConnection(accessor);
                }
                accessor.getPool().releaseConnection(accessor);
            }
            clientSession.setWriteConnections(null);
        } else {
            for (Accessor accessor : clientSession.getWriteConnections().values()) {
                //if connection is using external connection pooling then the event has been risen right before it disconnected.
                if(!accessor.usesExternalConnectionPooling()) {
                    clientSession.preReleaseConnection(accessor);
                    try {
                        clientSession.disconnect(accessor);
                    } catch (DatabaseException ex) {
                        // ignore - connection is thrown away.
                    }
                } else {
                    // should be already closed - but just in case it's still connected (and the event will risen before connection is closed).
                    accessor.closeConnection();
                }
            }
            clientSession.setWriteConnections(null);
            if (this.maxNumberOfNonPooledConnections != NO_MAX) {
                synchronized (this) {
                    this.numberOfNonPooledConnectionsUsed--;
                    notify();
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Release the read connection back into the read pool.
     */
    @Override
    public void releaseReadConnection(Accessor connection) {
        //if connection is using external connection pooling then the event has been risen right before it disconnected.
        if (!connection.usesExternalConnectionPooling()) {
            if (this.eventManager != null) {
                this.eventManager.preReleaseConnection(connection);
            }
        }
        this.readConnectionPool.releaseConnection(connection);
    }

    /**
     * INTERNAL:
     * Connection are pooled to share and restrict the number of database connections.
     */
    public void setConnectionPools(Map<String, ConnectionPool> connectionPools) {
        this.connectionPools = connectionPools;
    }

    /**
     * PUBLIC:
     * The default connection policy is used by default by the acquireClientConnection() protocol.
     * By default it is a connection pool with min 5 and max 10 lazy pooled connections.
     */
    @Override
    public void setDefaultConnectionPolicy(ConnectionPolicy defaultConnectionPolicy) {
        this.defaultConnectionPolicy = defaultConnectionPolicy;
    }

    /**
     * PUBLIC:
     * Creates and adds "default" connection pool using default parameter values
     */
    public void setDefaultConnectionPool() {
        addConnectionPool(DEFAULT_POOL, getDatasourceLogin(), ConnectionPool.MIN_CONNECTIONS, ConnectionPool.MAX_CONNECTIONS);
    }

    /**
     * PUBLIC:
     * Set the number of non-pooled database connections allowed.
     * This can be enforced to make up for the resource limitation of most JDBC drivers and database clients.
     * By default this is 50.
     */
    @Override
    public void setMaxNumberOfNonPooledConnections(int maxNumberOfNonPooledConnections) {
        this.maxNumberOfNonPooledConnections = maxNumberOfNonPooledConnections;
    }

    /**
     * INTERNAL:
     * Set the current number of connections being used that are not from a connection pool.
     */
    public void setNumberOfNonPooledConnectionsUsed(int numberOfNonPooledConnectionsUsed) {
        this.numberOfNonPooledConnectionsUsed = numberOfNonPooledConnectionsUsed;
    }

    /**
     * PUBLIC:
     * Set the read connection pool.
     * The read connection pool handles allocating connection for read queries.
     * If external connection pooling is used, an external connection pool will be used by default.
     */
    @Override
    public void setReadConnectionPool(ConnectionPool readConnectionPool) {
        if (isConnected()) {
            throw ValidationException.cannotSetReadPoolSizeAfterLogin();
        }
        this.readConnectionPool = readConnectionPool;
        this.readConnectionPool.setOwner(this);
    }

    /**
     * PUBLIC:
     * Creates and sets the new read connection pool.
     * By default the same connection pool is used for read and write,
     * this allows a different login/pool to be used for reading.
     * By default 32 min/max connections are used in the pool with an initial of 1 connection.
     */
    public void setReadConnectionPool(Login readLogin) throws ValidationException {
        if (isConnected()) {
            throw ValidationException.poolsMustBeConfiguredBeforeLogin();
        }
        ConnectionPool pool = null;
        if (readLogin.shouldUseExternalConnectionPooling()) {
            pool = new ExternalConnectionPool("read", readLogin, this);
        } else {
            pool = new ConnectionPool("read", readLogin, this);
        }
        this.readConnectionPool = pool;
    }

    /**
     * INTERNAL:
     * Set isSynchronized flag to indicate that this session is synchronized.
     * The method is ignored on ServerSession and should never be called.
     */
    @Override
    public void setSynchronized(boolean synched) {
    }

    /**
     * INTERNAL:
     * Updates standard connection pools. Should not be called after session is connected.
     * This is needed in case of pools' logins been altered after the pool has been created
     * (SessionManager does that)
     * All pools should be re-created in case their type doesn't match their login.
     * In addition, sequenceConnectionPool should be removed in case its login
     * has shouldUseExternaltransactionController()==true (see setSequenceConnectionPool)
     */
    protected void updateStandardConnectionPools() {
        if (getDefaultConnectionPool() != null) {
            if (getDefaultConnectionPool().isThereConflictBetweenLoginAndType()) {
                setDefaultConnectionPool();
            }
        }

        if (this.readConnectionPool != null) {
            if (this.readConnectionPool.isThereConflictBetweenLoginAndType()) {
                setReadConnectionPool(this.readConnectionPool.getLogin());
            }
        }
    }

    /**
     * PUBLIC:
     * Configure the read connection pool.
     * The read connection pool handles allocating connection for read queries.
     */
    @Override
    public void useExclusiveReadConnectionPool(int minNumerOfConnections, int maxNumerOfConnections) {
        setReadConnectionPool(new ConnectionPool("read", getDatasourceLogin(), minNumerOfConnections, maxNumerOfConnections, this));
    }

    /**
     * PUBLIC:
     * Configure the read connection pool.
     * The read connection pool handles allocating connection for read queries.
     */
    @Override
    public void useExclusiveReadConnectionPool(int initialNumberOfConnections, int minNumerOfConnections, int maxNumerOfConnections) {
        setReadConnectionPool(new ConnectionPool("read", getDatasourceLogin(), initialNumberOfConnections, minNumerOfConnections, maxNumerOfConnections, this));
    }

    /**
     * PUBLIC:
     * Configure the read connection pool.
     * The read connection pool handles allocating connection for read queries.
     */
    @Override
    public void useExternalReadConnectionPool() {
        setReadConnectionPool(new ExternalConnectionPool("read", getDatasourceLogin(), this));
    }

    /**
     * PUBLIC:
     * Configure the read connection pool.
     * The read connection pool handles allocating connection for read queries.
     * If external connection pooling is used, an external connection pool will be used by default.
     * This API uses a ReadConnectionPool which shares read connections.
     * Some JDBC drivers may not support concurrent access to a connection, or have poor concurrency,
     * so an exclusive read connection pool is normally recommended.
     * @see #useExclusiveReadConnectionPool(int, int)
     */
    @Override
    public void useReadConnectionPool(int minNumerOfConnections, int maxNumerOfConnections) {
        setReadConnectionPool(new ReadConnectionPool("read", getDatasourceLogin(), minNumerOfConnections, maxNumerOfConnections, this));
    }

    /**
     * PUBLIC:
     * Configure the read connection pool.
     * The read connection pool handles allocating connection for read queries.
     * If external connection pooling is used, an external connection pool will be used by default.
     * This API uses a ReadConnectionPool which shares read connections.
     * Some JDBC drivers may not support concurrent access to a connection, or have poor concurrency,
     * so an exclusive read connection pool is normally recommended.
     * @see #useExclusiveReadConnectionPool(int, int, int)
     */
    @Override
    public void useReadConnectionPool(int initialNumerOfConnections, int minNumerOfConnections, int maxNumerOfConnections) {
        setReadConnectionPool(new ReadConnectionPool("read", getDatasourceLogin(), initialNumerOfConnections,
                minNumerOfConnections, maxNumerOfConnections, this));
    }

    /**
     * INTERNAL:
     * This method will be used to update the query with any settings required
     * For this session.  It can also be used to validate execution.
     */
    @Override
    public void validateQuery(DatabaseQuery query) {
        if (query.isObjectLevelReadQuery() && ((query.getDescriptor().getCachePolicy().isIsolated())
                || ((ObjectLevelReadQuery)query).shouldUseExclusiveConnection())) {
            throw QueryException.isolatedQueryExecutedOnServerSession();
        }
    }

    /**
     * INTERNAL:
     * Return SequencingServer object owned by the session.
     */
    public SequencingServer getSequencingServer() {
        return getSequencingHome().getSequencingServer();
    }
}
