cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Blake Eggleston (JIRA)" <>
Subject [jira] [Commented] (CASSANDRA-7837) Factor out static initialization / singletons
Date Sun, 14 Sep 2014 16:31:34 GMT


Blake Eggleston commented on CASSANDRA-7837:

I've finished the second stage of the refactor. All non service/singleton classes are now
instantiated with their dependencies, and don't use any static singletons.

I'd like to get some opinions on the best way to proceed from here.

In the code's current state, there are a lot of circular dependencies between the singletons.
However, most of the dependencies aren't accessed in the singleton's constructor. I could
wrap this up pretty quickly if I instantiated all of the services by passing the database
descriptor instance into the constructor, and expose the other singletons via getter methods
on the database descriptor. There are still be some hard dependencies needed by the singleton
constructors, but most of the singletons are accessed at runtime inside various singleton

This *would* be kind of ugly, and would be the bare minimum needed to remove static initialization
from Cassandra. However, with a big refactor like this, there's something to be said for quickly
delivering an mvp where things are in a less bad state, and continuing to improve upon it.

The alternative would be continuing to refactor the api to remove singleton interdependencies,
but that will require much deeper changes.


> Factor out static initialization / singletons
> ---------------------------------------------
>                 Key: CASSANDRA-7837
>                 URL:
>             Project: Cassandra
>          Issue Type: Improvement
>            Reporter: Blake Eggleston
>            Assignee: Blake Eggleston
> I've been spending some time experimenting with ways to factor out static initialization
and static singletons in Cassandra.
> This is a known issue, with obvious implications on testability and extensibility. It
also leads to subtle changes in behavior of the database and tests, as access patterns to
static methods reorder the initialization order of the static state. For instance, the test
org.apache.cassandra.config.DatabaseDescriptorTest.testKSMetaDataSerialization is no longer
testing anything, because Schema.getKeyspaceDefinitions() is now returning an empty array.
Once the initialization order is changed, the test fails because system keyspaces aren't being
filtered out, and fromThrift throws an exceptions when it sees LocalStrategy. Removing static
state and singletons will make testing each component in isolation easier, leading to fewer
> With a large refactor like this, we'd want to avoid having the refactor branch, and the
trunk branch diverging too far, or for too long. After a few failed attempts, I've worked
out a way to perform the refactor in a way that can be performed with a series of (relatively)
small patches, and avoid a big, scary merge. Each patch will build, the tests will pass, and
can be merged into trunk daily/regularly as they are completed.
> The process is as follows:
> # Condense all static state into static singletons. (DatabaseDescriptor.getPartitioner()
-> DatabaseDescriptor.instance.getPartitioner())
> ** In some cases, classes will need to be split into pairs of instance and factory classes,
like in the case of Keyspace and ColumnFamilyStore
> # Identify all non-singleton usages of static state (grep for '.instance.'), and refactor
to pass dependencies into their constructors from their instantiating services.
> # Work out and implement an initialization order for the singletons, preferring final
members passed into their constructor, using volatile members assigned during startup where
there are circular dependencies.
> ** We should consider splitting some of the singletons into more component specific classes
before this step. There is definitely a case for making that another ticket, but with the
non-singleton dependencies clearly defined at this point, we will have a clear idea of what
can be split up. Doing that would reduce the number of circular dependencies between singletons,
and make this stage a lot easier, with the additional benefit of further modularizing the
> # Remove static singleton instances. Initialize and start C* from a static method that
takes a configuration as an argument.
> ** CassandraDaemon and utilities will need to be updated, and we'll need a helper method
so tests can instantiate the database with a one or two liner.
> Obviously, this is a lot of work, but I think it's worth the effort. I've already gone
through a few practice runs, and it's doable. I'm happy to do the work, with guidance and
input from the C* team.
> Thoughts?

This message was sent by Atlassian JIRA

View raw message