blob: bc6d81f8f0b1830f61e6ff69ca5e096c7abe02eb [file] [log] [blame]
/*
* 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.accumulo.core.client.impl;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.function.BiConsumer;
import org.apache.accumulo.core.Constants;
import org.apache.accumulo.core.client.NamespaceNotFoundException;
import org.apache.accumulo.core.util.Validator;
import org.apache.accumulo.fate.zookeeper.ZooCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Namespaces {
private static final Logger log = LoggerFactory.getLogger(Namespaces.class);
public static final String VALID_NAME_REGEX = "^\\w*$";
public static final Validator<String> VALID_NAME = new Validator<String>() {
@Override
public boolean test(String namespace) {
return namespace != null && namespace.matches(VALID_NAME_REGEX);
}
@Override
public String invalidMessage(String namespace) {
if (namespace == null)
return "Namespace cannot be null";
return "Namespaces must only contain word characters (letters, digits, and underscores): "
+ namespace;
}
};
public static final Validator<String> NOT_DEFAULT = new Validator<String>() {
@Override
public boolean test(String namespace) {
return !Namespace.DEFAULT.equals(namespace);
}
@Override
public String invalidMessage(String namespace) {
return "Namespace cannot be the reserved empty namespace";
}
};
public static final Validator<String> NOT_ACCUMULO = new Validator<String>() {
@Override
public boolean test(String namespace) {
return !Namespace.ACCUMULO.equals(namespace);
}
@Override
public String invalidMessage(String namespace) {
return "Namespace cannot be the reserved namespace, " + Namespace.ACCUMULO;
}
};
public static boolean exists(ClientContext context, Namespace.ID namespaceId) {
ZooCache zc = context.getZooCache();
List<String> namespaceIds = zc.getChildren(context.getZooKeeperRoot() + Constants.ZNAMESPACES);
return namespaceIds.contains(namespaceId.canonicalID());
}
public static List<Table.ID> getTableIds(ClientContext context, Namespace.ID namespaceId)
throws NamespaceNotFoundException {
String namespace = getNamespaceName(context, namespaceId);
List<Table.ID> tableIds = new LinkedList<>();
for (Entry<String,Table.ID> nameToId : Tables.getNameToIdMap(context).entrySet())
if (namespace.equals(Tables.qualify(nameToId.getKey()).getFirst()))
tableIds.add(nameToId.getValue());
return tableIds;
}
public static List<String> getTableNames(ClientContext context, Namespace.ID namespaceId)
throws NamespaceNotFoundException {
String namespace = getNamespaceName(context, namespaceId);
List<String> names = new LinkedList<>();
for (String name : Tables.getNameToIdMap(context).keySet())
if (namespace.equals(Tables.qualify(name).getFirst()))
names.add(name);
return names;
}
/**
* Gets all the namespaces from ZK. The first arg (t) the BiConsumer accepts is the ID and the
* second (u) is the namespaceName.
*/
private static void getAllNamespaces(ClientContext context,
BiConsumer<String,String> biConsumer) {
final ZooCache zc = context.getZooCache();
List<String> namespaceIds = zc.getChildren(context.getZooKeeperRoot() + Constants.ZNAMESPACES);
for (String id : namespaceIds) {
byte[] path = zc.get(context.getZooKeeperRoot() + Constants.ZNAMESPACES + "/" + id
+ Constants.ZNAMESPACE_NAME);
if (path != null) {
biConsumer.accept(id, new String(path, UTF_8));
}
}
}
/**
* Return sorted map with key = ID, value = namespaceName
*/
public static SortedMap<Namespace.ID,String> getIdToNameMap(ClientContext context) {
SortedMap<Namespace.ID,String> idMap = new TreeMap<>();
getAllNamespaces(context, (id, name) -> idMap.put(Namespace.ID.of(id), name));
return idMap;
}
/**
* Return sorted map with key = namespaceName, value = ID
*/
public static SortedMap<String,Namespace.ID> getNameToIdMap(ClientContext context) {
SortedMap<String,Namespace.ID> nameMap = new TreeMap<>();
getAllNamespaces(context, (id, name) -> nameMap.put(name, Namespace.ID.of(id)));
return nameMap;
}
/**
* Look for namespace ID in ZK. Throw NamespaceNotFoundException if not found.
*/
public static Namespace.ID getNamespaceId(ClientContext context, String namespaceName)
throws NamespaceNotFoundException {
final ArrayList<Namespace.ID> singleId = new ArrayList<>(1);
getAllNamespaces(context, (id, name) -> {
if (name.equals(namespaceName))
singleId.add(Namespace.ID.of(id));
});
if (singleId.isEmpty())
throw new NamespaceNotFoundException(null, namespaceName,
"getNamespaceId() failed to find namespace");
return singleId.get(0);
}
/**
* Look for namespace ID in ZK. Fail quietly by logging and returning null.
*/
public static Namespace.ID lookupNamespaceId(ClientContext context, String namespaceName) {
Namespace.ID id = null;
try {
id = getNamespaceId(context, namespaceName);
} catch (NamespaceNotFoundException e) {
if (log.isDebugEnabled())
log.debug("Failed to find namespace ID from name: " + namespaceName, e);
}
return id;
}
/**
* Return true if namespace name exists
*/
public static boolean namespaceNameExists(ClientContext context, String namespaceName) {
return lookupNamespaceId(context, namespaceName) != null;
}
/**
* Look for namespace name in ZK. Throw NamespaceNotFoundException if not found.
*/
public static String getNamespaceName(ClientContext context, Namespace.ID namespaceId)
throws NamespaceNotFoundException {
String name;
ZooCache zc = context.getZooCache();
byte[] path = zc.get(context.getZooKeeperRoot() + Constants.ZNAMESPACES + "/"
+ namespaceId.canonicalID() + Constants.ZNAMESPACE_NAME);
if (path != null)
name = new String(path, UTF_8);
else
throw new NamespaceNotFoundException(namespaceId.canonicalID(), null,
"getNamespaceName() failed to find namespace");
return name;
}
}