use of io.cdap.cdap.spi.metadata.ScopedNameOfKind in project cdap by caskdata.
the class DatasetMetadataStorage method replaceInScope.
private MetadataDataset.Change replaceInScope(MetadataDatasetContext context, MetadataScope scope, MetadataEntity entity, Set<String> newTags, Map<String, String> newProperties, Map<ScopedNameOfKind, MetadataDirective> directives) {
MetadataDataset dataset = context.getDataset(scope);
MetadataDataset.Record before = dataset.getMetadata(entity);
if (newTags.isEmpty() && newProperties.isEmpty()) {
// this scope remains unchanged
return new MetadataDataset.Change(before, before);
}
Set<String> existingTags = before.getTags();
Set<String> tagsToKeepOrPreserve = directives.entrySet().stream().filter(entry -> entry.getKey().getScope() == scope && entry.getKey().getKind() == TAG && (entry.getValue() == MetadataDirective.KEEP || entry.getValue() == MetadataDirective.PRESERVE)).map(Map.Entry::getKey).map(ScopedName::getName).filter(existingTags::contains).collect(Collectors.toSet());
newTags = Sets.union(newTags, tagsToKeepOrPreserve);
Map<String, String> existingProperties = before.getProperties();
Map<String, String> propertiesToKeepOrPreserve = directives.entrySet().stream().filter(entry -> entry.getKey().getScope() == scope && entry.getKey().getKind() == PROPERTY).filter(entry -> existingProperties.containsKey(entry.getKey().getName())).filter(entry -> entry.getValue() == MetadataDirective.PRESERVE || entry.getValue() == MetadataDirective.KEEP && !newProperties.containsKey(entry.getKey().getName())).map(Map.Entry::getKey).map(ScopedName::getName).collect(Collectors.toMap(name -> name, existingProperties::get));
newProperties.putAll(propertiesToKeepOrPreserve);
Set<String> tagsToRemove = Sets.difference(before.getTags(), newTags);
Set<String> tagsToAdd = Sets.difference(newTags, before.getTags());
Set<String> propertiesToRemove = Sets.difference(before.getProperties().keySet(), newProperties.keySet());
@SuppressWarnings("ConstantConditions") Map<String, String> propertiesToAdd = Maps.filterEntries(newProperties, entry -> !entry.getValue().equals(existingProperties.get(entry.getKey())));
MetadataDataset.Record after = before;
if (!tagsToRemove.isEmpty()) {
after = dataset.removeTags(entity, tagsToRemove).getLatest();
}
if (!tagsToAdd.isEmpty()) {
after = dataset.addTags(entity, tagsToAdd).getLatest();
}
if (!propertiesToRemove.isEmpty()) {
after = dataset.removeProperties(entity, propertiesToRemove).getLatest();
}
if (!propertiesToAdd.isEmpty()) {
after = dataset.addProperties(entity, propertiesToAdd).getLatest();
}
return new MetadataDataset.Change(before, after);
}
use of io.cdap.cdap.spi.metadata.ScopedNameOfKind in project cdap by caskdata.
the class DatasetMetadataStorage method readScope.
private MetadataDataset.Record readScope(MetadataDatasetContext context, MetadataScope scope, Read read) {
MetadataEntity entity = read.getEntity();
if (read.getSelection() == null && (!read.getScopes().contains(scope) || read.getKinds().isEmpty())) {
return new MetadataDataset.Record(entity);
}
Set<ScopedNameOfKind> selectionForScope = null;
if (read.getSelection() != null) {
// noinspection ConstantConditions
selectionForScope = Sets.filter(read.getSelection(), entry -> entry.getScope() == scope);
if (selectionForScope.isEmpty()) {
return new MetadataDataset.Record(entity);
}
}
// now we know we must read from the dataset
MetadataDataset dataset = context.getDataset(scope);
if (selectionForScope != null) {
// request is for a specific set of tags and properties
Set<String> tagsToRead = selectionForScope.stream().filter(entry -> TAG == entry.getKind()).map(ScopedName::getName).collect(Collectors.toSet());
Set<String> propertiesToRead = selectionForScope.stream().filter(entry -> PROPERTY == entry.getKind()).map(ScopedName::getName).collect(Collectors.toSet());
Set<String> tags = tagsToRead.isEmpty() ? Collections.emptySet() : Sets.intersection(tagsToRead, dataset.getTags(entity));
Map<String, String> properties = propertiesToRead.isEmpty() ? Collections.emptyMap() : Maps.filterKeys(dataset.getProperties(entity), propertiesToRead::contains);
return new MetadataDataset.Record(entity, properties, tags);
}
if (MetadataKind.ALL.equals(read.getKinds())) {
// all metadata kinds requested
return dataset.getMetadata(entity);
}
// exactly one kind is requested
MetadataKind requestKind = read.getKinds().iterator().next();
if (requestKind == TAG) {
return new MetadataDataset.Record(entity, Collections.emptyMap(), dataset.getTags(entity));
}
if (requestKind == PROPERTY) {
return new MetadataDataset.Record(entity, dataset.getProperties(entity), Collections.emptySet());
}
throw new IllegalStateException("Encountered metadata read request for unknown kind " + requestKind);
}
use of io.cdap.cdap.spi.metadata.ScopedNameOfKind in project cdap by caskdata.
the class ElasticsearchMetadataStorageTest method testFiltering.
@Test
public void testFiltering() {
ScopedName sys = new ScopedName(MetadataScope.SYSTEM, "s");
ScopedName user = new ScopedName(MetadataScope.USER, "u");
String sval = "S";
String uval = "U";
Metadata before = new Metadata(tags(sys, user), props(sys, sval, user, uval));
// test selection to remove
Assert.assertEquals(new Metadata(tags(sys), props(user, uval)), ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.DISCARD, MetadataKind.NONE, MetadataScope.NONE, ImmutableSet.of(new ScopedNameOfKind(MetadataKind.TAG, user), new ScopedNameOfKind(MetadataKind.PROPERTY, sys))));
// test selection is not affected by scopes or kinds
Assert.assertEquals(new Metadata(tags(sys), props(user, uval)), ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.DISCARD, MetadataKind.ALL, MetadataScope.ALL, ImmutableSet.of(new ScopedNameOfKind(MetadataKind.TAG, user), new ScopedNameOfKind(MetadataKind.PROPERTY, sys))));
// test selection to keep
Assert.assertEquals(new Metadata(tags(user), props(sys, sval)), ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.KEEP, MetadataKind.NONE, MetadataScope.NONE, ImmutableSet.of(new ScopedNameOfKind(MetadataKind.TAG, user), new ScopedNameOfKind(MetadataKind.PROPERTY, sys))));
// test selection is not affected by scopes or kinds
Assert.assertEquals(new Metadata(tags(user), props(sys, sval)), ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.KEEP, MetadataKind.ALL, MetadataScope.ALL, ImmutableSet.of(new ScopedNameOfKind(MetadataKind.TAG, user), new ScopedNameOfKind(MetadataKind.PROPERTY, sys))));
// test removing nothing
Assert.assertEquals(before, ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.DISCARD, MetadataKind.NONE, MetadataScope.NONE, null));
Assert.assertEquals(before, ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.DISCARD, MetadataKind.NONE, MetadataScope.ALL, null));
Assert.assertEquals(before, ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.DISCARD, MetadataKind.ALL, MetadataScope.NONE, null));
// test keeping all
Assert.assertEquals(before, ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.KEEP, MetadataKind.ALL, MetadataScope.ALL, null));
// test removing all
Assert.assertEquals(Metadata.EMPTY, ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.DISCARD, MetadataKind.ALL, MetadataScope.ALL, null));
// test keeping nothing
Assert.assertEquals(Metadata.EMPTY, ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.KEEP, MetadataKind.NONE, MetadataScope.NONE, null));
// test keeping nothing
Assert.assertEquals(Metadata.EMPTY, ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.KEEP, MetadataKind.ALL, MetadataScope.NONE, null));
// test keeping nothing
Assert.assertEquals(Metadata.EMPTY, ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.KEEP, MetadataKind.NONE, MetadataScope.ALL, null));
// test removing all SYSTEM
Assert.assertEquals(new Metadata(tags(user), props(user, uval)), ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.DISCARD, MetadataKind.ALL, Collections.singleton(MetadataScope.SYSTEM), null));
// test removing all USER
Assert.assertEquals(new Metadata(tags(sys), props(sys, sval)), ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.DISCARD, MetadataKind.ALL, Collections.singleton(MetadataScope.USER), null));
// test keeping all SYSTEM
Assert.assertEquals(new Metadata(tags(sys), props(sys, sval)), ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.KEEP, MetadataKind.ALL, Collections.singleton(MetadataScope.SYSTEM), null));
// test keeping all USER
Assert.assertEquals(new Metadata(tags(user), props(user, uval)), ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.KEEP, MetadataKind.ALL, Collections.singleton(MetadataScope.USER), null));
// test removing all tags
Assert.assertEquals(new Metadata(tags(), props(sys, sval, user, uval)), ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.DISCARD, Collections.singleton(MetadataKind.TAG), MetadataScope.ALL, null));
// test removing all properties
Assert.assertEquals(new Metadata(tags(sys, user), props()), ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.DISCARD, Collections.singleton(MetadataKind.PROPERTY), MetadataScope.ALL, null));
// test keeping all tags
Assert.assertEquals(new Metadata(tags(sys, user), props()), ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.KEEP, Collections.singleton(MetadataKind.TAG), MetadataScope.ALL, null));
// test keeping all properties
Assert.assertEquals(new Metadata(tags(), props(sys, sval, user, uval)), ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.KEEP, Collections.singleton(MetadataKind.PROPERTY), MetadataScope.ALL, null));
// test removing all tags in SYSTEM scope
Assert.assertEquals(new Metadata(tags(user), props(sys, sval, user, uval)), ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.DISCARD, Collections.singleton(MetadataKind.TAG), Collections.singleton(MetadataScope.SYSTEM), null));
// test removing all properties in USER scope
Assert.assertEquals(new Metadata(tags(sys, user), props(sys, sval)), ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.DISCARD, Collections.singleton(MetadataKind.PROPERTY), Collections.singleton(MetadataScope.USER), null));
// test keeping all tags in SYSTEM scope
Assert.assertEquals(new Metadata(tags(sys), props()), ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.KEEP, Collections.singleton(MetadataKind.TAG), Collections.singleton(MetadataScope.SYSTEM), null));
// test keeping all properties in USER scope
Assert.assertEquals(new Metadata(tags(), props(user, uval)), ElasticsearchMetadataStorage.filterMetadata(before, ElasticsearchMetadataStorage.KEEP, Collections.singleton(MetadataKind.PROPERTY), Collections.singleton(MetadataScope.USER), null));
}
use of io.cdap.cdap.spi.metadata.ScopedNameOfKind in project cdap by caskdata.
the class ElasticsearchMetadataStorage method create.
/**
* Creates the Elasticsearch index request for an entity creation or update.
* See {@link MetadataMutation.Create} for detailed semantics.
*
* @param before the metadata for the mutation's entity before the change
* @param create the mutation to apply
*
* @return an ElasticSearch request to be executed, and the change caused by the mutation
*/
private RequestAndChange create(VersionedMetadata before, MetadataMutation.Create create) {
// if the entity did not exist before, none of the directives apply and this is equivalent to update()
if (!before.existing()) {
return update(create.getEntity(), before, create.getMetadata());
}
Metadata meta = create.getMetadata();
Map<ScopedNameOfKind, MetadataDirective> directives = create.getDirectives();
// determine the scopes that this mutation applies to (scopes that do not occur in the metadata are no changed)
Set<MetadataScope> scopes = Stream.concat(meta.getTags().stream(), meta.getProperties().keySet().stream()).map(ScopedName::getScope).collect(Collectors.toSet());
// compute what previously existing tags and properties have to be preserved (all others are replaced)
Set<ScopedName> existingTagsToKeep = new HashSet<>();
Map<ScopedName, String> existingPropertiesToKeep = new HashMap<>();
// all tags and properties that are in a scope not affected by this mutation
Sets.difference(MetadataScope.ALL, scopes).forEach(scope -> {
before.getMetadata().getTags().stream().filter(tag -> tag.getScope().equals(scope)).forEach(existingTagsToKeep::add);
before.getMetadata().getProperties().entrySet().stream().filter(entry -> entry.getKey().getScope().equals(scope)).forEach(entry -> existingPropertiesToKeep.put(entry.getKey(), entry.getValue()));
});
// tags and properties in affected scopes that must be kept or preserved
directives.entrySet().stream().filter(entry -> scopes.contains(entry.getKey().getScope())).forEach(entry -> {
ScopedNameOfKind key = entry.getKey();
if (key.getKind() == MetadataKind.TAG && (entry.getValue() == MetadataDirective.PRESERVE || entry.getValue() == MetadataDirective.KEEP)) {
ScopedName tag = new ScopedName(key.getScope(), key.getName());
if (!meta.getTags().contains(tag) && before.getMetadata().getTags().contains(tag)) {
existingTagsToKeep.add(tag);
}
} else if (key.getKind() == MetadataKind.PROPERTY) {
ScopedName property = new ScopedName(key.getScope(), key.getName());
String existingValue = before.getMetadata().getProperties().get(property);
String newValue = meta.getProperties().get(property);
if (existingValue != null && (entry.getValue() == MetadataDirective.PRESERVE && !existingValue.equals(newValue) || entry.getValue() == MetadataDirective.KEEP && newValue == null)) {
existingPropertiesToKeep.put(property, existingValue);
}
}
});
// compute the new tags and properties
Set<ScopedName> newTags = existingTagsToKeep.isEmpty() ? meta.getTags() : Sets.union(meta.getTags(), existingTagsToKeep);
Map<ScopedName, String> newProperties = meta.getProperties();
if (!existingPropertiesToKeep.isEmpty()) {
newProperties = new HashMap<>(newProperties);
newProperties.putAll(existingPropertiesToKeep);
}
Metadata after = new Metadata(newTags, newProperties);
return new RequestAndChange(writeToIndex(create.getEntity(), before.getVersion(), after), new MetadataChange(create.getEntity(), before.getMetadata(), after));
}
use of io.cdap.cdap.spi.metadata.ScopedNameOfKind in project cdap by caskdata.
the class DatasetMetadataStorageTest method testSearchWeight.
// this tests is not in MetadataStorageTest,
// because it tests result scoring and sorting specific to the dataset-based implementation
@Test
public void testSearchWeight() throws IOException {
MetadataStorage mds = getMetadataStorage();
String ns = "ns1";
NamespaceId nsId = new NamespaceId(ns);
MetadataEntity service1 = nsId.app("app1").service("service1").toMetadataEntity();
MetadataEntity dataset1 = nsId.dataset("ds1").toMetadataEntity();
MetadataEntity dataset2 = nsId.dataset("ds2").toMetadataEntity();
// Add metadata
String multiWordValue = "aV1 av2 , - , av3 - av4_av5 av6";
Map<String, String> userProps = ImmutableMap.of("key1", "value1", "key2", "value2", "multiword", multiWordValue);
Map<String, String> systemProps = ImmutableMap.of("sysKey1", "sysValue1");
Set<String> userTags = ImmutableSet.of("tag1", "tag2");
Set<String> temporaryUserTags = ImmutableSet.of("tag3", "tag4");
Map<String, String> dataset1UserProps = ImmutableMap.of("sKey1", "sValuee1 sValuee2");
Map<String, String> dataset2UserProps = ImmutableMap.of("sKey1", "sValue1 sValue2", "Key1", "Value1");
Set<String> sysTags = ImmutableSet.of("sysTag1");
MetadataRecord service1Record = new MetadataRecord(service1, union(new Metadata(USER, userTags, userProps), new Metadata(SYSTEM, sysTags, systemProps)));
mds.apply(new Update(service1Record.getEntity(), service1Record.getMetadata()), MutationOptions.DEFAULT);
// dd and then remove some metadata for dataset2
mds.apply(new Update(dataset2, new Metadata(USER, temporaryUserTags, userProps)), MutationOptions.DEFAULT);
mds.apply(new Remove(dataset2, temporaryUserTags.stream().map(tag -> new ScopedNameOfKind(TAG, USER, tag)).collect(Collectors.toSet())), MutationOptions.DEFAULT);
mds.apply(new Remove(dataset2, userProps.keySet().stream().map(tag -> new ScopedNameOfKind(PROPERTY, USER, tag)).collect(Collectors.toSet())), MutationOptions.DEFAULT);
MetadataRecord dataset1Record = new MetadataRecord(dataset1, new Metadata(USER, tags(), dataset1UserProps));
MetadataRecord dataset2Record = new MetadataRecord(dataset2, new Metadata(USER, tags(), dataset2UserProps));
mds.batch(ImmutableList.of(new Update(dataset1Record.getEntity(), dataset1Record.getMetadata()), new Update(dataset2Record.getEntity(), dataset2Record.getMetadata())), MutationOptions.DEFAULT);
// Test score and metadata match
assertInOrder(mds, SearchRequest.of("value1 multiword:av2").addNamespace(ns).build(), service1Record, dataset2Record);
assertInOrder(mds, SearchRequest.of("value1 sValue*").addNamespace(ns).setLimit(Integer.MAX_VALUE).build(), dataset2Record, dataset1Record, service1Record);
assertResults(mds, SearchRequest.of("*").addNamespace(ns).setLimit(Integer.MAX_VALUE).build(), dataset2Record, dataset1Record, service1Record);
// clean up
mds.batch(ImmutableList.of(new Drop(service1), new Drop(dataset1), new Drop(dataset2)), MutationOptions.DEFAULT);
}
Aggregations