diff --git a/src/java/org/apache/cassandra/avro/CassandraServer.java b/src/java/org/apache/cassandra/avro/CassandraServer.java index a18bccc349..9e7d853cba 100644 --- a/src/java/org/apache/cassandra/avro/CassandraServer.java +++ b/src/java/org/apache/cassandra/avro/CassandraServer.java @@ -521,6 +521,16 @@ public class CassandraServer implements Cassandra { return new org.apache.cassandra.db.TimestampClock(clock.timestamp); } + private static Map unavronateAccessMap(Map map) + { + Map out = new HashMap(); + if (map == null) + return out; + for (Map.Entry entry : map.entrySet()) + out.put(entry.getKey().toString(), entry.getValue()); + return out; + } + // FIXME: This is copypasta from o.a.c.db.RowMutation, (RowMutation.getRowMutation uses Thrift types directly). private static RowMutation getRowMutationFromMutations(String keyspace, byte[] key, Map> cfMap) { @@ -666,6 +676,8 @@ public class CassandraServer implements Cassandra { ksDef.name.toString(), (Class)Class.forName(ksDef.strategy_class.toString()), (int)ksDef.replication_factor, + unavronateAccessMap(ksDef.users_access), + unavronateAccessMap(ksDef.groups_access), cfDefs.toArray(new CFMetaData[cfDefs.size()])); AddKeyspace add = new AddKeyspace(ksmeta); add.apply(); diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java index 545b0d40a9..a9a4e7a939 100644 --- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java +++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java @@ -343,11 +343,16 @@ public class DatabaseDescriptor CommitLog.setSegmentSize(conf.commitlog_rotation_threshold_in_mb * 1024 * 1024); // Hardcoded system tables - KSMetaData systemMeta = new KSMetaData(Table.SYSTEM_TABLE, LocalStrategy.class, 1, new CFMetaData[]{CFMetaData.StatusCf, - CFMetaData.HintsCf, - CFMetaData.MigrationsCf, - CFMetaData.SchemaCf, - CFMetaData.StatisticsCf + KSMetaData systemMeta = new KSMetaData(Table.SYSTEM_TABLE, + LocalStrategy.class, + 1, + null, + null, + new CFMetaData[]{CFMetaData.StatusCf, + CFMetaData.HintsCf, + CFMetaData.MigrationsCf, + CFMetaData.SchemaCf, + CFMetaData.StatisticsCf }); CFMetaData.map(CFMetaData.StatusCf); CFMetaData.map(CFMetaData.HintsCf); @@ -617,7 +622,7 @@ public class DatabaseDescriptor cf.gc_grace_seconds, metadata); } - defs.add(new KSMetaData(keyspace.name, strategyClass, keyspace.replication_factor, cfDefs)); + defs.add(new KSMetaData(keyspace.name, strategyClass, keyspace.replication_factor, null, null, cfDefs)); } diff --git a/src/java/org/apache/cassandra/config/KSMetaData.java b/src/java/org/apache/cassandra/config/KSMetaData.java index 54f777c6b8..538d42f4ae 100644 --- a/src/java/org/apache/cassandra/config/KSMetaData.java +++ b/src/java/org/apache/cassandra/config/KSMetaData.java @@ -32,14 +32,18 @@ import java.util.Map; import org.apache.avro.util.Utf8; import org.apache.commons.lang.ObjectUtils; +import org.apache.cassandra.avro.AccessLevel; + public final class KSMetaData { public final String name; public final Class strategyClass; public final int replicationFactor; - private final Map cfMetaData; + public final Map cfMetaData; + public final Map usersAccess; + public final Map groupsAccess; - public KSMetaData(String name, Class strategyClass, int replicationFactor, CFMetaData... cfDefs) + public KSMetaData(String name, Class strategyClass, int replicationFactor, Map usersAccess, Map groupsAccess, CFMetaData... cfDefs) { this.name = name; this.strategyClass = strategyClass == null ? RackUnawareStrategy.class : strategyClass; @@ -48,6 +52,10 @@ public final class KSMetaData for (CFMetaData cfm : cfDefs) cfmap.put(cfm.cfName, cfm); this.cfMetaData = Collections.unmodifiableMap(cfmap); + this.usersAccess = usersAccess == null ? + Collections.emptyMap() : Collections.unmodifiableMap(usersAccess); + this.groupsAccess = groupsAccess == null ? + Collections.emptyMap() : Collections.unmodifiableMap(groupsAccess); } /** @@ -57,7 +65,7 @@ public final class KSMetaData { List newCfs = new ArrayList(cfMetaData().values()); newCfs.add(cfm); - return new KSMetaData(name, strategyClass, replicationFactor, newCfs.toArray(new CFMetaData[newCfs.size()])); + return new KSMetaData(name, strategyClass, replicationFactor, usersAccess, groupsAccess, newCfs.toArray(new CFMetaData[newCfs.size()])); } /** @@ -69,7 +77,7 @@ public final class KSMetaData List newCfs = new ArrayList(cfMetaData().values()); newCfs.remove(cfm); assert newCfs.size() == cfMetaData().size() - 1; - return new KSMetaData(name, strategyClass, replicationFactor, newCfs.toArray(new CFMetaData[newCfs.size()])); + return new KSMetaData(name, strategyClass, replicationFactor, usersAccess, groupsAccess, newCfs.toArray(new CFMetaData[newCfs.size()])); } /** @@ -81,7 +89,7 @@ public final class KSMetaData List newCfs = new ArrayList(cfMetaData().size()); for (CFMetaData oldCf : cfMetaData().values()) newCfs.add(CFMetaData.renameTable(oldCf, ksName)); - return new KSMetaData(ksName, strategyClass, replicationFactor, newCfs.toArray(new CFMetaData[newCfs.size()])); + return new KSMetaData(ksName, strategyClass, replicationFactor, usersAccess, groupsAccess, newCfs.toArray(new CFMetaData[newCfs.size()])); } public boolean equals(Object obj) @@ -102,13 +110,15 @@ public final class KSMetaData { return cfMetaData; } - + public org.apache.cassandra.avro.KsDef deflate() { org.apache.cassandra.avro.KsDef ks = new org.apache.cassandra.avro.KsDef(); ks.name = new Utf8(name); ks.strategy_class = new Utf8(strategyClass.getName()); ks.replication_factor = replicationFactor; + ks.users_access = SerDeUtils.toAvroMap(usersAccess); + ks.groups_access = SerDeUtils.toAvroMap(groupsAccess); ks.cf_defs = SerDeUtils.createArray(cfMetaData.size(), org.apache.cassandra.avro.CfDef.SCHEMA$); for (CFMetaData cfm : cfMetaData.values()) ks.cf_defs.add(cfm.deflate()); @@ -126,12 +136,14 @@ public final class KSMetaData { throw new ConfigurationException("Could not create ReplicationStrategy of type " + ks.strategy_class, ex); } + Map usersAccess = SerDeUtils.fromAvroMap(ks.users_access); + Map groupsAccess = SerDeUtils.fromAvroMap(ks.groups_access); int cfsz = (int)ks.cf_defs.size(); CFMetaData[] cfMetaData = new CFMetaData[cfsz]; Iterator cfiter = ks.cf_defs.iterator(); for (int i = 0; i < cfsz; i++) cfMetaData[i] = CFMetaData.inflate(cfiter.next()); - return new KSMetaData(ks.name.toString(), repStratClass, ks.replication_factor, cfMetaData); + return new KSMetaData(ks.name.toString(), repStratClass, ks.replication_factor, usersAccess, groupsAccess, cfMetaData); } } diff --git a/src/java/org/apache/cassandra/io/SerDeUtils.java b/src/java/org/apache/cassandra/io/SerDeUtils.java index 499ec99a5b..d27195e867 100644 --- a/src/java/org/apache/cassandra/io/SerDeUtils.java +++ b/src/java/org/apache/cassandra/io/SerDeUtils.java @@ -22,6 +22,8 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.Map; +import java.util.HashMap; import org.apache.avro.Schema; import org.apache.avro.io.BinaryDecoder; @@ -45,6 +47,22 @@ public final class SerDeUtils // unbuffered decoders private final static DecoderFactory DIRECT_DECODERS = new DecoderFactory().configureDirectDecoder(true); + public static Map toAvroMap(Map map) + { + Map out = new HashMap(); + for (Map.Entry entry : map.entrySet()) + out.put(new Utf8(entry.getKey()), entry.getValue()); + return out; + } + + public static Map fromAvroMap(Map map) + { + Map out = new HashMap(); + for (Map.Entry entry : map.entrySet()) + out.put(entry.getKey().toString(), entry.getValue()); + return out; + } + /** * Deserializes a single object based on the given Schema. * @param schema writer's schema diff --git a/src/java/org/apache/cassandra/thrift/CassandraServer.java b/src/java/org/apache/cassandra/thrift/CassandraServer.java index d86e77be56..7fefc72f14 100644 --- a/src/java/org/apache/cassandra/thrift/CassandraServer.java +++ b/src/java/org/apache/cassandra/thrift/CassandraServer.java @@ -225,6 +225,16 @@ public class CassandraServer implements Cassandra.Iface return thrift_clock; } + private static Map unthriftifyAccessMap(Map map) + { + Map out = new HashMap(); + if (map == null) + return out; + for (Map.Entry entry : map.entrySet()) + out.put(entry.getKey(), Enum.valueOf(org.apache.cassandra.avro.AccessLevel.class, entry.getValue().name())); + return out; + } + private Map> getSlice(List commands, ConsistencyLevel consistency_level) throws InvalidRequestException, UnavailableException, TimedOutException { @@ -881,7 +891,9 @@ public class CassandraServer implements Cassandra.Iface KSMetaData ksm = new KSMetaData( ks_def.name, (Class)Class.forName(ks_def.strategy_class), - ks_def.replication_factor, + ks_def.replication_factor, + unthriftifyAccessMap(ks_def.users_access), + unthriftifyAccessMap(ks_def.groups_access), cfDefs.toArray(new CFMetaData[cfDefs.size()])); applyMigrationOnStage(new AddKeyspace(ksm)); return DatabaseDescriptor.getDefsVersion().toString(); diff --git a/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java b/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java index 2b8f27a069..e62552257e 100644 --- a/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java +++ b/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java @@ -37,9 +37,7 @@ public class DatabaseDescriptorTest { protected D serDe(D record) throws IOException { - D actual = SerDeUtils.deserialize(record.getSchema(), SerDeUtils.serialize(record)); - assert actual.equals(record) : actual + " != " + record; - return actual; + return SerDeUtils.deserialize(record.getSchema(), SerDeUtils.serialize(record)); } @Test @@ -83,9 +81,9 @@ public class DatabaseDescriptorTest assert DatabaseDescriptor.getNonSystemTables().size() == 0; // add a few. - AddKeyspace ks0 = new AddKeyspace(new KSMetaData("ks0", RackUnawareStrategy.class, 3)); + AddKeyspace ks0 = new AddKeyspace(new KSMetaData("ks0", RackUnawareStrategy.class, 3, null, null)); ks0.apply(); - AddKeyspace ks1 = new AddKeyspace(new KSMetaData("ks1", RackUnawareStrategy.class, 3)); + AddKeyspace ks1 = new AddKeyspace(new KSMetaData("ks1", RackUnawareStrategy.class, 3, null, null)); ks1.apply(); assert DatabaseDescriptor.getTableDefinition("ks0") != null; diff --git a/test/unit/org/apache/cassandra/db/DefsTest.java b/test/unit/org/apache/cassandra/db/DefsTest.java index b20562f0b7..56246fa076 100644 --- a/test/unit/org/apache/cassandra/db/DefsTest.java +++ b/test/unit/org/apache/cassandra/db/DefsTest.java @@ -262,7 +262,7 @@ public class DefsTest extends CleanupHelper { DecoratedKey dk = Util.dk("key0"); CFMetaData newCf = new CFMetaData("NewKeyspace1", "AddedStandard1", ColumnFamilyType.Standard, ClockType.Timestamp, UTF8Type.instance, null, new TimestampReconciler(), "A new cf for a new ks", 0, false, 1.0, 0, 864000, Collections.emptyMap()); - KSMetaData newKs = new KSMetaData(newCf.tableName, RackUnawareStrategy.class, 5, newCf); + KSMetaData newKs = new KSMetaData(newCf.tableName, RackUnawareStrategy.class, 5, null, null, newCf); new AddKeyspace(newKs).apply(); @@ -414,7 +414,7 @@ public class DefsTest extends CleanupHelper { assert DatabaseDescriptor.getTableDefinition("EmptyKeyspace") == null; - KSMetaData newKs = new KSMetaData("EmptyKeyspace", RackUnawareStrategy.class, 5, new CFMetaData[]{}); + KSMetaData newKs = new KSMetaData("EmptyKeyspace", RackUnawareStrategy.class, 5, null, null); new AddKeyspace(newKs).apply(); assert DatabaseDescriptor.getTableDefinition("EmptyKeyspace") != null;