001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.engine;
020
021import java.io.IOException;
022import java.util.ArrayList;
023import java.util.List;
024
025import lucee.commons.io.SystemUtil;
026import lucee.commons.lang.SerializableObject;
027import lucee.runtime.PageContext;
028import lucee.runtime.config.ConfigImpl;
029
030public class ThreadQueueImpl implements ThreadQueue {
031        private final SerializableObject token=new SerializableObject();
032        
033        
034        public final List<PageContext> list=new ArrayList<PageContext>();
035        //private final int max;
036        //private long timeout;
037        private int waiting=0;
038        
039        public ThreadQueueImpl(){
040                /*if(max<=1)this.max=1;
041                else this.max=max;
042                this.timeout=timeout;*/
043        }
044        
045        
046        @Override
047        public void enter(PageContext pc) throws IOException {
048                try{
049                        synchronized (token) {waiting++;}
050                        _enter(pc);
051                }
052                finally {
053                        synchronized (token) {waiting--;}
054                }
055        }
056        
057        private void _enter(PageContext pc) throws IOException {
058                ConfigImpl ci=(ConfigImpl) pc.getConfig();
059                long start=System.currentTimeMillis();
060                long timeout=ci.getQueueTimeout();
061                if(timeout<=0) timeout=ci.getRequestTimeout().getMillis();
062                
063                while(true) {
064                        synchronized (token) {
065                                if(list.size()<ci.getQueueMax()) {
066                                        list.add(pc);
067                                        return;
068                                }
069                        }
070                        if(timeout>0) SystemUtil.wait(token,timeout);
071                        else SystemUtil.wait(token);
072                        
073                        if(timeout>0 && (System.currentTimeMillis()-start)>=timeout)
074                                throw new IOException("Concurrent request timeout ("+(System.currentTimeMillis()-start)+") ["+timeout+" ms] has occurred, server is too busy handling other requests. This timeout setting can be changed in the server administrator.");
075                }
076        }
077        
078        @Override
079        public void exit(PageContext pc){
080                //print.e("exist("+Thread.currentThread().getName()+")");
081                synchronized (token) {
082                        list.remove(pc);
083                        token.notify();
084                }
085        }
086        
087        @Override
088        public int size(){
089                return waiting;
090        }
091
092        @Override
093        public void clear() {
094                list.clear();
095                token.notifyAll();
096        }
097        
098        
099        /*public static class Test extends Thread {
100                private ThreadQueueImpl queue;
101                public Test(ThreadQueueImpl queue){
102                        this.queue=queue;
103                }
104                public void run(){
105                        String name = Thread.currentThread().getName();
106                        try {
107                                queue.enter(name);
108                                queue.size();
109                                SystemUtil.sleep(50);
110                                queue.exit(name);
111                        }
112                        catch (IOException e) {
113                                e.printStackTrace();
114                        }
115                        
116                        
117                }
118        }
119        
120        public static void main(String[] args) {
121                ThreadQueueImpl queue=new ThreadQueueImpl(4,1000);
122                new Test(queue).start();
123                new Test(queue).start();
124                new Test(queue).start();
125                new Test(queue).start();
126                new Test(queue).start();
127                new Test(queue).start();
128                new Test(queue).start();
129                new Test(queue).start();
130                new Test(queue).start();
131                new Test(queue).start();
132                new Test(queue).start();
133                new Test(queue).start();
134                new Test(queue).start();
135                new Test(queue).start();
136                new Test(queue).start();
137                new Test(queue).start();
138                new Test(queue).start();
139                new Test(queue).start();
140                new Test(queue).start();
141                new Test(queue).start();
142                new Test(queue).start();
143                new Test(queue).start();
144                new Test(queue).start();
145                new Test(queue).start();
146                new Test(queue).start();
147                new Test(queue).start();
148                new Test(queue).start();
149                new Test(queue).start();
150                new Test(queue).start();
151                new Test(queue).start();
152                new Test(queue).start();
153                new Test(queue).start();
154                new Test(queue).start();
155                new Test(queue).start();
156                new Test(queue).start();
157                
158                
159        }*/
160        
161        
162}