All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.cassandra.schema.TableMetadataRefCache Maven / Gradle / Ivy

Go to download

The Apache Cassandra Project develops a highly scalable second-generation distributed database, bringing together Dynamo's fully distributed design and Bigtable's ColumnFamily-based data model.

There is a newer version: 5.0.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.cassandra.schema;

import java.util.Collections;
import java.util.Map;

import com.google.common.collect.MapDifference;
import com.google.common.collect.Maps;

import org.apache.cassandra.utils.Pair;

/**
 * Manages the cached {@link TableMetadataRef} objects which holds the references to {@link TableMetadata} objects.
 * 

* The purpose of {@link TableMetadataRef} is that the reference to {@link TableMetadataRef} remains unchanged when * the metadata of the table changes. {@link TableMetadata} is immutable, so when it changes, we only switch * the reference inside the existing {@link TableMetadataRef} object. */ class TableMetadataRefCache { public final static TableMetadataRefCache EMPTY = new TableMetadataRefCache(Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap()); // UUID -> mutable metadata ref map. We have to update these in place every time a table changes. private final Map metadataRefs; // keyspace and table names -> mutable metadata ref map. private final Map, TableMetadataRef> metadataRefsByName; // (keyspace name, index name) -> mutable metadata ref map. We have to update these in place every time an index changes. private final Map, TableMetadataRef> indexMetadataRefs; public TableMetadataRefCache(Map metadataRefs, Map, TableMetadataRef> metadataRefsByName, Map, TableMetadataRef> indexMetadataRefs) { this.metadataRefs = Collections.unmodifiableMap(metadataRefs); this.metadataRefsByName = Collections.unmodifiableMap(metadataRefsByName); this.indexMetadataRefs = Collections.unmodifiableMap(indexMetadataRefs); } /** * Returns cache copy with added the {@link TableMetadataRef} corresponding to the provided keyspace to {@link #metadataRefs} and * {@link #indexMetadataRefs}, assuming the keyspace is new (in the sense of not being tracked by the manager yet). */ TableMetadataRefCache withNewRefs(KeyspaceMetadata ksm) { return withUpdatedRefs(ksm.empty(), ksm); } /** * Returns cache copy with updated the {@link TableMetadataRef} in {@link #metadataRefs} and {@link #indexMetadataRefs}, * for an existing updated keyspace given it's previous and new definition. *

* Note that {@link TableMetadataRef} are not duplicated and table metadata is altered in the existing refs. */ TableMetadataRefCache withUpdatedRefs(KeyspaceMetadata previous, KeyspaceMetadata updated) { Tables.TablesDiff tablesDiff = Tables.diff(previous.tables, updated.tables); Views.ViewsDiff viewsDiff = Views.diff(previous.views, updated.views); MapDifference indexesDiff = previous.tables.indexesDiff(updated.tables); boolean hasCreatedOrDroppedTablesOrViews = tablesDiff.created.size() > 0 || tablesDiff.dropped.size() > 0 || viewsDiff.created.size() > 0 || viewsDiff.dropped.size() > 0; boolean hasCreatedOrDroppedIndexes = !indexesDiff.entriesOnlyOnRight().isEmpty() || !indexesDiff.entriesOnlyOnLeft().isEmpty(); Map metadataRefs = hasCreatedOrDroppedTablesOrViews ? Maps.newHashMap(this.metadataRefs) : this.metadataRefs; Map, TableMetadataRef> metadataRefsByName = hasCreatedOrDroppedTablesOrViews ? Maps.newHashMap(this.metadataRefsByName) : this.metadataRefsByName; Map, TableMetadataRef> indexMetadataRefs = hasCreatedOrDroppedIndexes ? Maps.newHashMap(this.indexMetadataRefs) : this.indexMetadataRefs; // clean up after removed entries tablesDiff.dropped.forEach(ref -> removeRef(metadataRefs, metadataRefsByName, ref)); viewsDiff.dropped.forEach(view -> removeRef(metadataRefs, metadataRefsByName, view.metadata)); indexesDiff.entriesOnlyOnLeft() .values() .forEach(indexTable -> indexMetadataRefs.remove(Pair.create(indexTable.keyspace, indexTable.indexName().get()))); // load up new entries tablesDiff.created.forEach(table -> putRef(metadataRefs, metadataRefsByName, new TableMetadataRef(table))); viewsDiff.created.forEach(view -> putRef(metadataRefs, metadataRefsByName, new TableMetadataRef(view.metadata))); indexesDiff.entriesOnlyOnRight() .values() .forEach(indexTable -> indexMetadataRefs.put(Pair.create(indexTable.keyspace, indexTable.indexName().get()), new TableMetadataRef(indexTable))); // refresh refs to updated ones tablesDiff.altered.forEach(diff -> metadataRefs.get(diff.after.id).set(diff.after)); viewsDiff.altered.forEach(diff -> metadataRefs.get(diff.after.metadata.id).set(diff.after.metadata)); indexesDiff.entriesDiffering() .values() .stream() .map(MapDifference.ValueDifference::rightValue) .forEach(indexTable -> indexMetadataRefs.get(Pair.create(indexTable.keyspace, indexTable.indexName().get())).set(indexTable)); return new TableMetadataRefCache(metadataRefs, metadataRefsByName, indexMetadataRefs); } private void putRef(Map metadataRefs, Map, TableMetadataRef> metadataRefsByName, TableMetadataRef ref) { metadataRefs.put(ref.id, ref); metadataRefsByName.put(Pair.create(ref.keyspace, ref.name), ref); } private void removeRef(Map metadataRefs, Map, TableMetadataRef> metadataRefsByName, TableMetadata tm) { metadataRefs.remove(tm.id); metadataRefsByName.remove(Pair.create(tm.keyspace, tm.name)); } /** * Returns cache copy with removed the {@link TableMetadataRef} from {@link #metadataRefs} and {@link #indexMetadataRefs} * for the provided (dropped) keyspace. */ TableMetadataRefCache withRemovedRefs(KeyspaceMetadata ksm) { return withUpdatedRefs(ksm, ksm.empty()); } public TableMetadataRef getTableMetadataRef(TableId id) { return metadataRefs.get(id); } public TableMetadataRef getTableMetadataRef(String keyspace, String table) { return metadataRefsByName.get(Pair.create(keyspace, table)); } public TableMetadataRef getIndexTableMetadataRef(String keyspace, String index) { return indexMetadataRefs.get(Pair.create(keyspace, index)); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy