/* * * 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. * */ #include "AclResourceCounter.h" #include "Acl.h" #include "qpid/log/Statement.h" #include "qpid/sys/Mutex.h" #include #include using namespace qpid::sys; namespace qpid { namespace acl { // // This module approves various resource creation requests: // Queues // // // // ResourceCounter::ResourceCounter(Acl& a, uint16_t ql) : acl(a), queueLimit(ql) {} ResourceCounter::~ResourceCounter() {} // // limitApproveLH // // Resource creation approver. // If user is under limit increment count and return true. // Called with lock held. // bool ResourceCounter::limitApproveLH( const std::string& theTitle, countsMap_t& theMap, const std::string& theName, uint16_t theLimit, bool emitLog) { bool result(true); if (theLimit > 0) { uint16_t count; countsMap_t::iterator eRef = theMap.find(theName); if (eRef != theMap.end()) { count = (uint16_t)(*eRef).second; result = count < theLimit; if (result) { count += 1; (*eRef).second = count; } } else { // Not found theMap[theName] = count = 1; } if (emitLog) { QPID_LOG(trace, theTitle << theName << " limit=" << theLimit << " curValue=" << count << " result=" << (result ? "allow" : "deny")); } } return result; } // // releaseLH // // Decrement the name's count in map. // called with dataLock already taken // void ResourceCounter::releaseLH( const std::string& theTitle, countsMap_t& theMap, const std::string& theName, uint16_t theLimit) { if (theLimit > 0) { countsMap_t::iterator eRef = theMap.find(theName); if (eRef != theMap.end()) { uint16_t count = (uint16_t) (*eRef).second; assert (count > 0); if (1 == count) { theMap.erase (eRef); } else { (*eRef).second = count - 1; } } else { // User had no connections. QPID_LOG(notice, theTitle << theName << "' not found in resource count pool"); } } } // // approveCreateQueue // Count an attempted queue creation by this user. // Disapprove if over limit. // bool ResourceCounter::approveCreateQueue(const std::string& userId, const std::string& queueName) { Mutex::ScopedLock locker(dataLock); bool okByQ = limitApproveLH("ACL Queue creation approver. userId:", queuePerUserMap, userId, queueLimit, true); if (okByQ) { // Queue is owned by this userId queueOwnerMap[queueName] = userId; QPID_LOG(trace, "ACL create queue approved for user '" << userId << "' queue '" << queueName << "'"); } else { QPID_LOG(error, "Client max queue count limit of " << queueLimit << " exceeded by '" << userId << "' creating queue '" << queueName << "'. Queue creation denied."); acl.reportQueueLimit(userId, queueName); } return okByQ; } // // recordDestroyQueue // Return a destroyed queue to a user's quota // void ResourceCounter::recordDestroyQueue(const std::string& queueName) { Mutex::ScopedLock locker(dataLock); queueOwnerMap_t::iterator eRef = queueOwnerMap.find(queueName); if (eRef != queueOwnerMap.end()) { releaseLH("ACL resource counter: Queue owner for queue '", queuePerUserMap, (*eRef).second, queueLimit); queueOwnerMap.erase(eRef); } else { QPID_LOG(notice, "ACL resource counter: Queue '" << queueName << "' not found in queue owner map"); } } }} // namespace qpid::acl