/* * * 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.io.sstable; import java.io.File; import java.util.EnumSet; import com.google.common.base.Objects; import org.apache.cassandra.utils.Pair; /** * SSTables are made up of multiple components in separate files. Components are * identified by a type and an id, but required unique components (such as the Data * and Index files) may have implicit ids assigned to them. */ public class Component { final static EnumSet<Type> TYPES = EnumSet.allOf(Type.class); enum Type { // the base data for an sstable: the remaining components can be regenerated // based on the data component DATA("Data.db"), // index of the row keys with pointers to their positions in the data file PRIMARY_INDEX("Index.db"), // serialized bloom filter for the row keys in the sstable FILTER("Filter.db"), // 0-length file that is created when an sstable is ready to be deleted COMPACTED_MARKER("Compacted"), // statistical metadata about the content of the sstable STATS("Statistics.db"), // a bitmap secondary index: many of these may exist per sstable BITMAP_INDEX("Bitidx.db"); final String repr; Type(String repr) { this.repr = repr; } static Type fromRepresentation(String repr) { for (Type type : TYPES) if (repr.equals(type.repr)) return type; throw new RuntimeException("Invalid SSTable component: '" + repr + "'"); } } // singleton components for types that don't need ids public final static Component DATA = new Component(Type.DATA, -1); public final static Component PRIMARY_INDEX = new Component(Type.PRIMARY_INDEX, -1); public final static Component FILTER = new Component(Type.FILTER, -1); public final static Component COMPACTED_MARKER = new Component(Type.COMPACTED_MARKER, -1); public final static Component STATS = new Component(Type.STATS, -1); public final Type type; public final int id; public final int hashCode; public Component(Type type) { this(type, -1); } public Component(Type type, int id) { this.type = type; this.id = id; this.hashCode = Objects.hashCode(type, id); } /** * @return The unique (within an sstable) name for this component. */ public String name() { switch(type) { case DATA: case PRIMARY_INDEX: case FILTER: case COMPACTED_MARKER: case STATS: return type.repr; case BITMAP_INDEX: return String.format("%d-%s", id, type.repr); } throw new IllegalStateException(); } /** * Filename of the form "<ksname>/<cfname>-[tmp-][<version>-]<gen>-<component>", * where <component> is of the form "[<id>-]<component>". * @return A Descriptor for the SSTable, and a Component for this particular file. * TODO move descriptor into Component field */ public static Pair<Descriptor,Component> fromFilename(File directory, String name) { Pair<Descriptor,String> path = Descriptor.fromFilename(directory, name); // parse the component suffix String repr = path.right; int id = -1; int separatorPos = repr.indexOf('-'); if (separatorPos != -1) { id = Integer.parseInt(repr.substring(0, separatorPos)); repr = repr.substring(separatorPos+1, repr.length()); } Type type = Type.fromRepresentation(repr); // build (or retrieve singleton for) the component object Component component; switch(type) { case DATA: component = Component.DATA; break; case PRIMARY_INDEX: component = Component.PRIMARY_INDEX; break; case FILTER: component = Component.FILTER; break; case COMPACTED_MARKER: component = Component.COMPACTED_MARKER; break; case STATS: component = Component.STATS; break; case BITMAP_INDEX: component = new Component(type, id); break; default: throw new IllegalStateException(); } return new Pair<Descriptor,Component>(path.left, component); } @Override public String toString() { return this.name(); } @Override public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof Component)) return false; Component that = (Component)o; return this.type == that.type && this.id == that.id; } @Override public int hashCode() { return hashCode; } }