/* This file is part of VoltDB.
 * Copyright (C) 2008-2019 VoltDB Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * 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 VoltDB.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.voltcore.network;

import java.util.Deque;

import java.util.concurrent.ConcurrentLinkedDeque;
import org.voltcore.utils.DBBPool;
import org.voltcore.utils.DBBPool.BBContainer;

public class NetworkDBBPool {

    private final Deque<BBContainer> m_buffers = new ConcurrentLinkedDeque<BBContainer>();
    private static final int LIMIT = Integer.getInteger("NETWORK_DBB_LIMIT", 512);
    private static final int SIZE = Integer.getInteger("NETWORK_DBB_SIZE", (1024 * 32));

    private final int m_numBuffers;
    private final int m_allocationSize;
    public NetworkDBBPool(int numBuffers) {
        m_numBuffers = numBuffers;
        m_allocationSize = SIZE;
    }

    NetworkDBBPool(int numBuffers, int allocSize) {
        m_numBuffers = numBuffers;
        m_allocationSize = allocSize;
    }

    public NetworkDBBPool() {
        m_numBuffers = LIMIT;
        m_allocationSize = SIZE;
    }

    BBContainer acquire() {
       final BBContainer cont = m_buffers.poll();
        if (cont == null) {
           final BBContainer originContainer = DBBPool.allocateDirect(m_allocationSize);
           return new BBContainer(originContainer.b()) {
                @Override
                public void discard() {
                    checkDoubleFree();
                    //If we had to allocate over the desired limit, start discarding
                    if (m_buffers.size() > m_numBuffers) {
                        originContainer.discard();
                        return;
                    }
                    m_buffers.push(originContainer);
                }
           };
       }
       return new BBContainer(cont.b()) {
           @Override
           public void discard() {
               checkDoubleFree();
               if (m_buffers.size() > m_numBuffers) {
                   cont.discard();
                   return;
               }
               m_buffers.push(cont);
           }
       };
    }

    void clear() {
        BBContainer cont = null;
        while ((cont = m_buffers.poll()) != null) {
            cont.discard();
        }
    }

}

@@ -785,16 +785,15 @@
 til.
-Deq
+Que
 ue;%0A
-%0A
 impo
@@ -820,31 +820,29 @@
 ent.
-ConcurrentLinkedDeq
+ArrayBlockingQue
 ue;%0A
+%0A
 impo
@@ -955,99 +955,8 @@
  %7B%0A%0A
-    private final Deque%3CBBContainer%3E m_buffers = new ConcurrentLinkedDeque%3CBBContainer%3E();%0A
     
@@ -1146,18 +1146,30 @@
 nal 
-int m_numB
+Queue%3CBBContainer%3E m_b
 uffe
@@ -1208,24 +1208,25 @@
 cationSize;%0A
+%0A
     public N
@@ -1269,66 +1269,30 @@
     
-m_numBuffers = numBuffers;%0A        m_allocationSize =
+this(numBuffers,
  SIZE
+)
 ;%0A  
@@ -1350,36 +1350,33 @@
 ze) %7B%0A        m_
-numB
+b
 uffers = numBuff
@@ -1368,16 +1368,41 @@
 ffers = 
+new ArrayBlockingQueue%3C%3E(
 numBuffe
@@ -1399,24 +1399,25 @@
 %3E(numBuffers
+)
 ;%0A        m_
@@ -1493,61 +1493,25 @@
     
-m_numBuffers = LIMIT;%0A        m_allocationSize =
+this(LIMIT,
  SIZE
+)
 ;%0A  
@@ -1546,29 +1546,24 @@
 () %7B%0A       
-final
  BBContainer
@@ -1584,24 +1584,25 @@
 ers.poll();%0A
+%0A
         if (
@@ -1632,41 +1632,13 @@
     
-final BBContainer originContainer
+ cont
  = D
@@ -1677,24 +1677,32 @@
 onSize);%0A   
+     %7D%0A%0A
         retu
@@ -1700,34 +1700,38 @@
      return new 
-BB
+Cached
 Container(origin
@@ -1728,92 +1728,36 @@
 ner(
-originContainer.b()) %7B%0A                @Override%0A                public
+cont);%0A    %7D%0A%0A   
  void 
-disc
+cle
 ar
-d
 () %7B
@@ -1769,222 +1769,101 @@
     
-            checkDoubleFree();%0A                    //If we had to allocate over the desired limit, start discarding%0A                    if (m_buffers.size() %3E m_numBuffers) %7B%0A                        originContainer
+BBContainer cont = null;%0A        while ((cont = m_buffers.poll()) != null) %7B%0A            cont
 .dis
@@ -1882,96 +1882,163 @@
     
+%7D%0A
     
+%7D%0A%0A
     
-        return;%0A                    %7D%0A                    m_buffers.push(originC
+private final class CachedContainer extends BBContainer %7B%0A        private final BBContainer m_original;%0A%0A        CachedContainer(BBContainer c
 onta
@@ -2042,17 +2042,18 @@
 ntainer)
-;
+ %7B
 %0A       
@@ -2061,34 +2061,36 @@
     
-    %7D%0A           %7D
+super(container.b())
 ;%0A      
  %7D%0A 
@@ -2089,56 +2089,49 @@
     
- %7D%0A
       
- return new BBContainer(cont.b()) %7B%0A   
+m_original = container;%0A        %7D%0A%0A
     
@@ -2144,19 +2144,16 @@
 verride%0A
-   
         
@@ -2172,27 +2172,24 @@
 discard() %7B%0A
-   
             
@@ -2219,23 +2219,21 @@
         
-   
 if (
+!
 m_buffer
@@ -2238,29 +2238,25 @@
 ers.
-size() %3E m_numBuffers
+offer(m_original)
 ) %7B%0A
@@ -2263,39 +2263,42 @@
                 
-   cont
+m_original
 .discard();%0A    
@@ -2309,254 +2309,24 @@
     
-       return;%0A               %7D%0A               m_buffers.push(cont);%0A           %7D%0A       %7D;%0A    %7D%0A%0A    void clear() %7B%0A        BBContainer cont = null;%0A        while ((cont = m_buffers.poll()) != null) %7B%0A            cont.discard();%0A        %7D%0A    %7D%0A
+%7D%0A        %7D%0A    %7D
 %0A%7D%0A

Use BlockingArrayQueue