Details

    • Type: New Feature New Feature
    • Status: Resolved
    • Priority: Critical Critical
    • Resolution: Fixed
    • Fix Version/s: 0.4
    • Component/s: Core
    • Labels:
      None

      Description

      Cassandra has preliminary support for multiple tables (namespaces / sets of ColumnFamilies) but a lot of the code assumes there is only one. Multitable support is important for allowing multiple applications to run on a single cluster. It's also useful to cleanly separate "system" columnfamilies from application data.

        Activity

        Hide
        Hudson added a comment -

        Integrated in Cassandra #117 (See http://hudson.zones.apache.org/hudson/job/Cassandra/117/)
        fix more null table parameters.
        patch by jbellis; reviewed by goffinet for
        remove table_ from CommitLog and add multitable tests.
        patch by jbellis; reviewed by goffinet for
        fix columnfamily id generation in the face of multiple tables and rip out TableMetadata serialization, which only complicates things needlessly.

        patch by jbellis; reviewed by goffinet for
        cleanup of table.open.

        patch by jbellis; reviewed by goffinet for
        multitable support.

        fix CF table dependencies, making CommitLogTest pass. Also fixes CASSANDRA-188 in passing.

        fix tablename being null bugs by always parsing tablename from filename.

        fix last part of SequenceFile.

        patch by jbellis; reviewed by goffinet for
        Pass and write table parameter as needed throughout the codebase to add multitable support.
        (Many places cheated and just assumed that tables.get(0) was the only table.)
        Patch builds but does not yet pass tests.

        Patch by goffinet; reviewed by jbellis for

        Show
        Hudson added a comment - Integrated in Cassandra #117 (See http://hudson.zones.apache.org/hudson/job/Cassandra/117/ ) fix more null table parameters. patch by jbellis; reviewed by goffinet for remove table_ from CommitLog and add multitable tests. patch by jbellis; reviewed by goffinet for fix columnfamily id generation in the face of multiple tables and rip out TableMetadata serialization, which only complicates things needlessly. patch by jbellis; reviewed by goffinet for cleanup of table.open. patch by jbellis; reviewed by goffinet for multitable support. fix CF table dependencies, making CommitLogTest pass. Also fixes CASSANDRA-188 in passing. fix tablename being null bugs by always parsing tablename from filename. fix last part of SequenceFile. patch by jbellis; reviewed by goffinet for Pass and write table parameter as needed throughout the codebase to add multitable support. (Many places cheated and just assumed that tables.get(0) was the only table.) Patch builds but does not yet pass tests. Patch by goffinet; reviewed by jbellis for
        Hide
        Chris Goffinet added a comment -

        +1

        Show
        Chris Goffinet added a comment - +1
        Hide
        Jonathan Ellis added a comment -

        patch 07 fixes a few more cases where a null table was sneaking in and causing trouble. (caught by system tests.)

        Show
        Jonathan Ellis added a comment - patch 07 fixes a few more cases where a null table was sneaking in and causing trouble. (caught by system tests.)
        Hide
        Jonathan Ellis added a comment -

        moved preliminary patches into CASSANDRA-237.

        Renumbered the others (new number = old number - 3) and added the new 0006-remove-table_-from-CommitLog-with-test.txt fixing the bug I mentioned in the previous comment.

        Show
        Jonathan Ellis added a comment - moved preliminary patches into CASSANDRA-237 . Renumbered the others (new number = old number - 3) and added the new 0006-remove-table_-from-CommitLog-with-test.txt fixing the bug I mentioned in the previous comment.
        Hide
        Jonathan Ellis added a comment -

        I see a bug already.

        As I mentioned (way) above, we want to have Row serialize the table name into the commitlog. CommitLog shouldn't have a table_ variable; it will contain rows from lots of tables.

        Creating a test that breaks this will need to force the log replay code to run. Haven't looked to see how hard that is.

        Show
        Jonathan Ellis added a comment - I see a bug already. As I mentioned (way) above, we want to have Row serialize the table name into the commitlog. CommitLog shouldn't have a table_ variable; it will contain rows from lots of tables. Creating a test that breaks this will need to force the log replay code to run. Haven't looked to see how hard that is.
        Hide
        Jonathan Ellis added a comment -

        There is a little more to do but this will do for a start I think.

        The remaining parts are (1) move the system columnfamilies into their own Table (they are initialized in DatabaseDescriptor.storeMetadata) and (2) testing. I added a note to http://wiki.apache.org/cassandra/HowToContribute linking the Hudson coverage reports and explaining how to build one manually. Potential problem areas for this ticket are the CommitLog classes and (once we migrate them) the code dealing with system tables, particularly Hints.

        Show
        Jonathan Ellis added a comment - There is a little more to do but this will do for a start I think. The remaining parts are (1) move the system columnfamilies into their own Table (they are initialized in DatabaseDescriptor.storeMetadata) and (2) testing. I added a note to http://wiki.apache.org/cassandra/HowToContribute linking the Hudson coverage reports and explaining how to build one manually. Potential problem areas for this ticket are the CommitLog classes and (once we migrate them) the code dealing with system tables, particularly Hints.
        Hide
        Jonathan Ellis added a comment -

        08
        add multitable test

        07
        fix id generation for multiple tables and rip out TableMetadata serialization, which only complicates things need (this is the actual commitlog change part!)

        06
        cleanup of table.open

        05
        fix CF table dependencies, making CommitLogTest pass. Also fixes CASSANDRA-188 in passing.

        fix table being null bugs by always parsing tablename from filename

        fix last part of SF

        04
        Chris Goffinet's patch with minor changes to get it to build

        03
        switch from byte[] to BitSet in CommitLogHeader

        02
        update comments, perform some renames, r/m unused code

        01
        CASSANDRA-79 add CommitLog test

        Show
        Jonathan Ellis added a comment - 08 add multitable test 07 fix id generation for multiple tables and rip out TableMetadata serialization, which only complicates things need (this is the actual commitlog change part!) 06 cleanup of table.open 05 fix CF table dependencies, making CommitLogTest pass. Also fixes CASSANDRA-188 in passing. fix table being null bugs by always parsing tablename from filename fix last part of SF 04 Chris Goffinet's patch with minor changes to get it to build 03 switch from byte[] to BitSet in CommitLogHeader 02 update comments, perform some renames, r/m unused code 01 CASSANDRA-79 add CommitLog test
        Hide
        Chris Goffinet added a comment -

        Reverted and provided a better diff

        Show
        Chris Goffinet added a comment - Reverted and provided a better diff
        Hide
        Chris Goffinet added a comment -

        Optimized imports

        Show
        Chris Goffinet added a comment - Optimized imports
        Hide
        Jonathan Ellis added a comment -

        i am working on the commitlog changes.

        in the meantime can you make your ide not mess with import ordering and resubmit this? (project settings -> code style -> import in intellij)

        order should be

        java

        org.apache.log4j
        org.apache.commons
        org.junit

        everything else

        Show
        Jonathan Ellis added a comment - i am working on the commitlog changes. in the meantime can you make your ide not mess with import ordering and resubmit this? (project settings -> code style -> import in intellij) order should be java org.apache.log4j org.apache.commons org.junit everything else
        Hide
        Chris Goffinet added a comment -

        Rebased from trunk per request from jbellis

        Show
        Chris Goffinet added a comment - Rebased from trunk per request from jbellis
        Hide
        Jonathan Ellis added a comment -

        I'm done with 208 for now and I can look at the commitlog stuff. Can you rebase this against head? Sorry about the conflicts.

        Show
        Jonathan Ellis added a comment - I'm done with 208 for now and I can look at the commitlog stuff. Can you rebase this against head? Sorry about the conflicts.
        Hide
        Chris Goffinet added a comment -

        This is some draft work for Multi-Table support. Still many bugs, and haven't completed CommitLog. The work done regarding to CommitLog assumes log per file. We will need to change this as comments suggest having 1 log file for all tables is preferred.

        Show
        Chris Goffinet added a comment - This is some draft work for Multi-Table support. Still many bugs, and haven't completed CommitLog. The work done regarding to CommitLog assumes log per file. We will need to change this as comments suggest having 1 log file for all tables is preferred.
        Hide
        Hudson added a comment -

        Integrated in Cassandra #85 (See http://hudson.zones.apache.org/hudson/job/Cassandra/85/)
        use cloneMeShallow where appropriate. patch by jbellis for

        Show
        Hudson added a comment - Integrated in Cassandra #85 (See http://hudson.zones.apache.org/hudson/job/Cassandra/85/ ) use cloneMeShallow where appropriate. patch by jbellis for
        Hide
        Chris Goffinet added a comment -

        Here is some draft work myself and phatduck (Arin) did. Its up on my multitable branch on github. We optimized imports so you will see some java imports removed. I also added some TODO's for places needing additional work.

        http://github.com/lenn0x/Cassandra/commit/3f218993957280c3510633564c2cc8c42b951fd7

        Show
        Chris Goffinet added a comment - Here is some draft work myself and phatduck (Arin) did. Its up on my multitable branch on github. We optimized imports so you will see some java imports removed. I also added some TODO's for places needing additional work. http://github.com/lenn0x/Cassandra/commit/3f218993957280c3510633564c2cc8c42b951fd7
        Hide
        Jonathan Ellis added a comment -

        I would vote for system table.

        Show
        Jonathan Ellis added a comment - I would vote for system table.
        Hide
        Jun Rao added a comment -

        We need a field in the CLHeader for each CF in each table. Yes, the mapping from CF to field has to be unique.

        Another issue. What happens to those system CFs (hinted handoff, system, etc)? Should they be put in each table or should they be put in a "system" table?

        Show
        Jun Rao added a comment - We need a field in the CLHeader for each CF in each table. Yes, the mapping from CF to field has to be unique. Another issue. What happens to those system CFs (hinted handoff, system, etc)? Should they be put in each table or should they be put in a "system" table?
        Hide
        Jonathan Ellis added a comment -

        Log entries are just Rows, right? So adding table name there fixes that part.

        the header stuff is a bit more complex. (you mean CL.clHeader_ right?) I don't think we want to actually add fields there – wouldn't just making the id generator global (so that the id would still uniquely identify a CF in any table) instead of per-table solve the updateHeader problem?

        Show
        Jonathan Ellis added a comment - Log entries are just Rows, right? So adding table name there fixes that part. the header stuff is a bit more complex. (you mean CL.clHeader_ right?) I don't think we want to actually add fields there – wouldn't just making the id generator global (so that the id would still uniquely identify a CF in any table) instead of per-table solve the updateHeader problem?
        Hide
        Jun Rao added a comment -

        We also need to add the table name to each log entry.

        Show
        Jun Rao added a comment - We also need to add the table name to each log entry.
        Hide
        Jonathan Ellis added a comment -

        agreed, one log file per node is the only sane way to do things or you would require a disk per table to avoid seeks on the CL devices.

        Show
        Jonathan Ellis added a comment - agreed, one log file per node is the only sane way to do things or you would require a disk per table to avoid seeks on the CL devices.
        Hide
        Jun Rao added a comment -

        We need to think a bit more about CommitLog. Do we create a log file per table or do we have a log file for all tables? The latter seems to make more sense. However, the CommitLog Header has a couple of fields per CF. This needs to be expanded to per CF per table.

        Show
        Jun Rao added a comment - We need to think a bit more about CommitLog. Do we create a log file per table or do we have a log file for all tables? The latter seems to make more sense. However, the CommitLog Header has a couple of fields per CF. This needs to be expanded to per CF per table.
        Hide
        Jonathan Ellis added a comment -

        Oh, and for objects that are serialized (via a manual serializer() method, with very few exceptions Cassandra does not use JDK serialization) you'll need to include the extra tableName field in de/serialization. ColumnFamily is the obvious one here. Maybe one or two more.

        Show
        Jonathan Ellis added a comment - Oh, and for objects that are serialized (via a manual serializer() method, with very few exceptions Cassandra does not use JDK serialization) you'll need to include the extra tableName field in de/serialization. ColumnFamily is the obvious one here. Maybe one or two more.
        Hide
        Jonathan Ellis added a comment - - edited

        From what I have seen the underlying mechanics for multiple table support are already there. We just need to make all the places that assume there is only one for convenience, stop doing so.

        DatabaseDescriptor parses and stores the results of the config xml. Right now the shortcut for "get the table name" is DD.getTables().get(0). I suggest auditing the calls to getTables() and see if any are actually using it for more than that. (I don't think there are.) Then start fixing them. When you are done, get rid of it so nobody is tempted to be lazy like that again.

        There are two classes of fixes. Client API fixes and internal uses. The client ones are probably easier in general. What should happen is, the client gives cassandra a table name as part of any API call, and that is passed to one of the handler methods (e.g., ReadVerbHandler, RowMutationVerbHandler). Those will have the table name as part of the Command object they read off the wire. So just start including the table name down the call stack.

        The internal ones are a bit harder but only a little. Often an object will need the table name in a place where its caller does not know the table either, e.g. ColumnFamily.getColumnComparator. Here you'll need to add an instance variable containing either the table name or a reference to the parent Table object. Adding factory methods to Table such as Table.getColumnFamily may be convenient.

        Some of DatabaseDescriptor itself needs to stop assuming only one table. This will not be much code. applicationColumnFamilies_ is one place. at the very least that needs another layer of Map<tablename, appCFs> like tableToCFMetaDataMap_ does. If you're more ambitious you could try moving those into the Table object as additional cleanup.

        Please leave any questions here in case anyone else wants to help.

        Show
        Jonathan Ellis added a comment - - edited From what I have seen the underlying mechanics for multiple table support are already there. We just need to make all the places that assume there is only one for convenience, stop doing so. DatabaseDescriptor parses and stores the results of the config xml. Right now the shortcut for "get the table name" is DD.getTables().get(0). I suggest auditing the calls to getTables() and see if any are actually using it for more than that. (I don't think there are.) Then start fixing them. When you are done, get rid of it so nobody is tempted to be lazy like that again. There are two classes of fixes. Client API fixes and internal uses. The client ones are probably easier in general. What should happen is, the client gives cassandra a table name as part of any API call, and that is passed to one of the handler methods (e.g., ReadVerbHandler, RowMutationVerbHandler). Those will have the table name as part of the Command object they read off the wire. So just start including the table name down the call stack. The internal ones are a bit harder but only a little. Often an object will need the table name in a place where its caller does not know the table either, e.g. ColumnFamily.getColumnComparator. Here you'll need to add an instance variable containing either the table name or a reference to the parent Table object. Adding factory methods to Table such as Table.getColumnFamily may be convenient. Some of DatabaseDescriptor itself needs to stop assuming only one table. This will not be much code. applicationColumnFamilies_ is one place. at the very least that needs another layer of Map<tablename, appCFs> like tableToCFMetaDataMap_ does. If you're more ambitious you could try moving those into the Table object as additional cleanup. Please leave any questions here in case anyone else wants to help.

          People

          • Assignee:
            Jonathan Ellis
            Reporter:
            Jonathan Ellis
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development