blob: 0cd405b54ee2b4bf788dffb1ac606362614f6efe [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.sentry.hdfs;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import com.codahale.metrics.Timer.Context;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.sentry.hdfs.service.thrift.SentryHDFSService;
import org.apache.sentry.hdfs.service.thrift.TAuthzUpdateRequest;
import org.apache.sentry.hdfs.service.thrift.TAuthzUpdateResponse;
import org.apache.sentry.hdfs.service.thrift.TPathsUpdate;
import org.apache.sentry.hdfs.service.thrift.TPermissionsUpdate;
import org.apache.thrift.TException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Process requests from HDFS Name Node plugin.
* The only supported request is {@link #get_all_authz_updates_from(long, long)}.
*/
public class SentryHDFSServiceProcessor implements SentryHDFSService.Iface {
private static final Logger LOGGER = LoggerFactory.getLogger(SentryHDFSServiceProcessor.class);
// Flag to prevent that multiple paths updates are sent to HDFS NameNodes at the same time.
// This helps to reduce memory consumption on large path images.
private static final AtomicBoolean pathsRetrieverBusy = new AtomicBoolean(false);
@Override
public TAuthzUpdateResponse get_all_authz_updates_from(long permSeqNum, long pathSeqNum) throws TException {
throw new UnsupportedOperationException(
"get_all_authz_updates_from() is not supported due to known bugs. Use get_authz_updates() instead.");
}
@Override
public TAuthzUpdateResponse get_authz_updates(TAuthzUpdateRequest request)
throws TException {
TAuthzUpdateResponse retVal = new TAuthzUpdateResponse();
if (SentryPlugin.instance == null) {
LOGGER.error("SentryPlugin not initialized yet !!");
retVal.setAuthzPathUpdate(Collections.<TPathsUpdate>emptyList());
retVal.setAuthzPermUpdate(Collections.<TPermissionsUpdate>emptyList());
return retVal;
}
try (Context timerContext = SentryHdfsMetricsUtil.getAllAuthzUpdatesTimer.time()) {
retVal.setAuthzPermUpdate(getPermissionsUpdatesFrom(request));
retVal.setAuthzPathUpdate(getPathsUpdatesFrom(request));
} catch (Exception e) {
LOGGER.error("Error Sending updates to downstream Cache", e);
throw new TException(e);
}
return retVal;
}
/**
* Retrieves and returns new requested permissions updates.
*
* @param request The requested thrift object that contains the permission seqNum
* @return A list of delta updates or a full image retrieved. It returns an empty list if there
* are not updates.
* @throws Exception If an error occurred while retrieving the updates.
*/
private List<TPermissionsUpdate> getPermissionsUpdatesFrom(TAuthzUpdateRequest request)
throws Exception {
LOGGER.debug("PERMISSIONS updates requested from HDFS [SeqNum={}]",
request.getPermSeqNum());
List<PermissionsUpdate> permUpdates =
SentryPlugin.instance.getAllPermsUpdatesFrom(request.getPermSeqNum());
List<TPermissionsUpdate> retPermUpdates = new ArrayList<>(permUpdates.size());
for (PermissionsUpdate update : permUpdates) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Sending PERM preUpdate seq [{}], [{}]",
update.getSeqNum(), update.toThrift());
}
retPermUpdates.add(update.toThrift());
}
SentryHdfsMetricsUtil.getPermUpdateHistogram.update(permUpdates.size());
return retPermUpdates;
}
/**
* Retrieves and returns new requested paths updates. To avoid too much memory consumption
* with large full images, then this method will serialize the access to the requested updates
* to only one request at a time.
*
* @param request The requested thrift object that contains the paths seqNum and imgNum
* @return A list of delta updates or a full image retrieved. It returns an empty list if there
* are not updates or another request is happening at the same time.
* @throws Exception If an error occurred while retrieving the updates.
*/
private List<TPathsUpdate> getPathsUpdatesFrom(TAuthzUpdateRequest request) throws Exception {
LOGGER.debug("PATHS updates requested from HDFS [ImgNum={}, SeqNum={}]",
request.getPathImgNum(), request.getPathSeqNum());
// If another paths updates request is in progress by another HDFS NameNode, then we
// return an empty image for now to avoid a large memory consumption
if (!pathsRetrieverBusy.compareAndSet(false, true)) {
LOGGER.debug("PATHS updates are not available because another request is in progress.");
return Collections.emptyList();
}
try {
List<PathsUpdate> pathUpdates =
SentryPlugin.instance.
getAllPathsUpdatesFrom(request.getPathSeqNum(), request.getPathImgNum());
List<TPathsUpdate> retPathUpdates = new ArrayList<>(pathUpdates.size());
for (PathsUpdate update : pathUpdates) {
LOGGER.debug("Sending PATH preUpdate seq [{}], [{}]",
update.getSeqNum(), update.getImgNum());
retPathUpdates.add(update.toThrift());
}
SentryHdfsMetricsUtil.getPathUpdateHistogram.update(pathUpdates.size());
return retPathUpdates;
} catch (Exception e) {
throw e;
} finally {
pathsRetrieverBusy.set(false);
}
}
@Override
public void handle_hms_notification(TPathsUpdate update) throws TException {
throw new UnsupportedOperationException("handle_hms_notification");
}
@Override
public long check_hms_seq_num(long pathSeqNum) throws TException {
throw new UnsupportedOperationException("check_hms_seq_num");
}
/**
* Not implemented for the time being..
*/
@Override
public Map<String, List<String>> get_all_related_paths(String arg0,
boolean arg1) throws TException {
// TODO Auto-generated method stub
return null;
}
}