| /* |
| * |
| * 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 <assert.h> |
| #include <sstream> |
| |
| 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 |