Skip to content

Commit

Permalink
Add newSession method to create session without connecting
Browse files Browse the repository at this point in the history
JAVA-208 #fixes
  • Loading branch information
Sylvain Lebresne committed Mar 3, 2014
1 parent 2279838 commit 4614d9d
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 11 deletions.
2 changes: 2 additions & 0 deletions driver-core/CHANGELOG.rst
Expand Up @@ -5,6 +5,8 @@ CHANGELOG
------

- [improvement] Handle the static columns introduced in Cassandra 2.0.6 (JAVA-278)
- [improvement] Add Cluster#newSession method to create Session without connecting
right away (JAVA-208)
- [bug] Add missing iso8601 patterns for parsing dates (JAVA-279)
- [bug] Properly parse BytesType as the blob type
- [bug] Potential NPE when parsing schema of pre-CQL tables of C* 1.2 nodes (JAVA-280)
Expand Down
48 changes: 41 additions & 7 deletions driver-core/src/main/java/com/datastax/driver/core/Cluster.java
Expand Up @@ -156,7 +156,34 @@ public static Cluster.Builder builder() {
}

/**
* Creates a new session on this cluster.
* Creates a new session on this cluster but does not initialize it.
* <p>
* Because this method does not perform any initialization, it cannot fail.
* The initialization of the session (the connection of the Session to the
* Cassandra nodes) will occur if either the {@link Session#init} method is
* called explicitly, or the time the
* returned session object is called.
* <p>
* Once a session returned by this method gets initialized (see above), it
* will be set to no keyspace. If you want to set such session to a
* keyspace, you will have to explicitly execute a 'USE <mykeyspace>' query.
* <p>
* Note that if you do not particularly need to defer initialization, it is
* simpler to use one of the {@code connect()} method of this class.
*
* @return a new, non-initialized session on this cluster.
*/
public Session newSession() {
return manager.newSession();
}

/**
* Creates a new session on this cluster and initialize it.
* <p>
* Note that this method will initialize the newly created session, trying
* to connect to the Cassandra nodes before returning. If you only want
* to create a Session object without initializing it right away, see
* {@link #newSession}.
*
* @return a new session on this cluster sets to no keyspace.
*
Expand All @@ -167,11 +194,20 @@ public static Cluster.Builder builder() {
* while contacting the initial contact points.
*/
public Session connect() {
return manager.newSession();
init();
Session session = manager.newSession();
session.init();
return session;
}

/**
* Creates a new session on this cluster and sets the keyspace to the provided one.
* Creates a new session on this cluster, initialize it and sets the keyspace
* to the provided one.
* <p>
* Note that this method will initialize the newly created session, trying
* to connect to the Cassandra nodes before returning. If you only want
* to create a Session object without initializing it right away, see
* {@link #newSession}.
*
* @param keyspace The name of the keyspace to use for the created
* {@code Session}.
Expand Down Expand Up @@ -947,7 +983,7 @@ private Manager(String clusterName, List<InetAddress> contactPoints, Configurati

// Initialization is not too performance intensive and in practice there shouldn't be contention
// on it so synchronized is good enough.
private synchronized void init() {
synchronized void init() {
if (isInit)
return;
isInit = true;
Expand Down Expand Up @@ -1011,9 +1047,7 @@ ReconnectionPolicy reconnectionPolicy() {
}

private Session newSession() {
init();

SessionManager session = new SessionManager(Cluster.this, metadata.allHosts());
SessionManager session = new SessionManager(Cluster.this);
sessions.add(session);
return session;
}
Expand Down
33 changes: 33 additions & 0 deletions driver-core/src/main/java/com/datastax/driver/core/Session.java
Expand Up @@ -44,6 +44,39 @@ public interface Session extends Closeable {
*/
public String getLoggedKeyspace();

/**
* Force the initialization of this Session instance if it hasn't been
* initialized yet.
* <p>
* Please note first that most use won't need to call this method
* explicitly. If you use the {@link Cluster#connect} method {@code Cluster}
* to create your Session, the returned session will be already
* initialized. Even if you create a non-initialized session through
* {@link Cluster#newSession}, that session will get automatically
* initialized the first time that session is used for querying. This method
* is thus only useful if you use {@link Cluster#newSession} and want to
* explicitly force initialization without querying.
* <p>
* Session initialization consists in connecting the Session to the known
* Cassandra hosts (at least those that should not be ignored due to
* the {@code LoadBalancingPolicy} in place).
* <p>
* If the Cluster instance this Session depends on is not itself
* initialized, it will be initialized by this method.
* <p>
* If the session is already initialized, this method is a no-op.
*
* @return this {@code Session} object.
*
* @throws NoHostAvailableException if this initialization triggers the
* Cluster initialization and no host amongst the contact points can be
* reached.
* @throws AuthenticationException if this initialization triggers the
* Cluster initialization and an authentication error occurs while contacting
* the initial contact points.
*/
public Session init();

/**
* Executes the provided query.
*
Expand Down
Expand Up @@ -44,15 +44,24 @@ class SessionManager implements Session {
final HostConnectionPool.PoolState poolsState;
final AtomicReference<CloseFuture> closeFuture = new AtomicReference<CloseFuture>();

private volatile boolean isInit;

// Package protected, only Cluster should construct that.
SessionManager(Cluster cluster, Collection<Host> hosts) {
SessionManager(Cluster cluster) {
this.cluster = cluster;

this.pools = new ConcurrentHashMap<Host, HostConnectionPool>(hosts.size());
this.pools = new ConcurrentHashMap<Host, HostConnectionPool>();
this.poolsState = new HostConnectionPool.PoolState();
}

public synchronized Session init() {
if (isInit)
return this;

// If we haven't initialized the cluster, do it now
cluster.init();

// Create pool to initial nodes (and wait for them to be created)
for (Host host : hosts) {
for (Host host : cluster.getMetadata().allHosts()) {
try {
addOrRenewPool(host, false).get();
} catch (ExecutionException e) {
Expand All @@ -62,6 +71,8 @@ class SessionManager implements Session {
Thread.currentThread().interrupt();
}
}
isInit = true;
return this;
}

public String getLoggedKeyspace() {
Expand Down Expand Up @@ -400,6 +411,9 @@ else if (fetchSize != Integer.MAX_VALUE)
* {@link LoadBalancingPolicy} and handle host failover.
*/
void execute(RequestHandler.Callback callback, Statement statement) {
// init() locks, so avoid if we know we don't need it.
if (!isInit)
init();
new RequestHandler(this, callback, statement).sendRequest();
}

Expand Down

0 comments on commit 4614d9d

Please sign in to comment.