package com.tesora.dve.server.connectionmanager; /* * #%L * Tesora Inc. * Database Virtualization Engine * %% * Copyright (C) 2011 - 2014 Tesora Inc. * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicInteger; import com.tesora.dve.exceptions.PEException; public class ConnectionSemaphore extends Semaphore { private static final long serialVersionUID = 1L; private static AtomicInteger minMemRequirement = new AtomicInteger(1000000); AtomicInteger maxConnections = new AtomicInteger(); double maxPercentWaiting = Double.parseDouble(System.getProperty("ConnectionSemaphore.maxPercentWaiting", "10"))/100; public ConnectionSemaphore(int permits) { super(permits); this.maxConnections.set(permits); } public void safeAcquire() throws PEException { if (getQueueLength() > Math.ceil(maxPercentWaiting * maxConnections.get())) throw new PEException("Too many requests pending (" + maxConnections.get() * maxPercentWaiting + ")"); verifyMinMemory(); try { super.acquire(); } catch (InterruptedException e) { throw new PEException("Request interrupted"); } } public void nonBlockingAcquire() throws PEException { verifyMinMemory(); if (false == super.tryAcquire()) throw new PEException("Too many connections (maximum = " + maxConnections.get() + ")"); } public void adjustMaxConnections(int newMax) { int delta = maxConnections.getAndSet(newMax) - newMax; if (delta > 0) super.reducePermits(delta); else if (delta < 0) super.release(Math.abs(delta)); } public static void adjustMinMemory(int minMem) { minMemRequirement.set(minMem); } public void verifyMinMemory() throws PEException { final Runtime rt = Runtime.getRuntime(); if (rt.maxMemory() - rt.totalMemory() + rt.freeMemory() < minMemRequirement.get()) throw new PEException("Not enough memory available to start new connection (Max: " + rt.maxMemory() + ", Allocated: " + rt.totalMemory() + ", Free: " + rt.freeMemory() + ")"); } }