001         package com.croftsoft.apps.chat.server;
002    
003         import java.util.*;
004    
005         import com.croftsoft.core.lang.NullArgumentException;
006         import com.croftsoft.core.lang.lifecycle.Commissionable;
007         import com.croftsoft.core.math.MathConstants;
008         import com.croftsoft.core.role.Server;
009         import com.croftsoft.core.security.Authentication;
010         import com.croftsoft.core.util.ClassMapServer;
011    import com.croftsoft.core.util.consumer.Consumer;
012         import com.croftsoft.core.util.loop.FixedDelayLoopGovernor;
013         import com.croftsoft.core.util.loop.Loopable;
014         import com.croftsoft.core.util.loop.Looper;
015    
016         import com.croftsoft.apps.chat.ChatConstants;
017         import com.croftsoft.apps.chat.model.ChatGame;
018         import com.croftsoft.apps.chat.model.seri.SeriChatGame;
019         import com.croftsoft.apps.chat.request.CreateUserRequest;
020         import com.croftsoft.apps.chat.request.PullRequest;
021         import com.croftsoft.apps.chat.request.Request;
022         import com.croftsoft.apps.chat.response.UnknownUserResponse;
023         import com.croftsoft.apps.chat.server.CreateUserServer;
024         import com.croftsoft.apps.chat.user.User;
025         import com.croftsoft.apps.chat.user.UserStore;
026    import com.croftsoft.apps.chat.user.seri.SeriUserStore;
027    
028         /*********************************************************************
029         * Chat server.
030         *
031         * @version
032         *   2003-06-18
033         * @since
034         *   2003-06-04
035         * @author
036         *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
037         *********************************************************************/
038    
039         public final class  ChatServer
040           implements Commissionable, Server
041         //////////////////////////////////////////////////////////////////////
042         //////////////////////////////////////////////////////////////////////
043         {
044    
045         private static final boolean  DEBUG = true;
046    
047         private static final long  SAMPLE_PERIOD
048           = 10 * MathConstants.MILLISECONDS_PER_SECOND;
049    
050         private static final double  UPDATE_RATE = 30.0;
051    
052         //
053    
054         private final UserStore         userStore;
055    
056         private final ChatGame          chatGame;
057    
058         private final Looper            looper;
059    
060         private final CreateUserServer  createUserServer;
061    
062         private final PullServer        pullServer;
063    
064         //
065    
066         private long  count;
067    
068         private long  startTime;
069    
070         private long  lastRequestTime;
071    
072         //////////////////////////////////////////////////////////////////////
073         //////////////////////////////////////////////////////////////////////
074    
075         public  ChatServer ( )
076         //////////////////////////////////////////////////////////////////////
077         {
078           userStore = new SeriUserStore ( );
079    
080           chatGame = new SeriChatGame ( userStore );
081    
082           createUserServer = new CreateUserServer ( userStore );
083    
084           pullServer = new PullServer ( ChatConstants.QUEUE_PULL_TIMEOUT );
085    
086           looper = new Looper (
087             new Loopable ( )
088             {
089               public boolean  loop ( )
090               {
091                 return ChatServer.this.loop ( );
092               }
093             },
094             new FixedDelayLoopGovernor ( UPDATE_RATE ),
095             null,
096             ( String ) null,
097             Thread.MIN_PRIORITY,
098             true );
099         }
100    
101         //////////////////////////////////////////////////////////////////////
102         //////////////////////////////////////////////////////////////////////
103    
104         public void  init ( )
105         //////////////////////////////////////////////////////////////////////
106         {
107           startTime = System.currentTimeMillis ( );
108    
109           lastRequestTime = startTime;
110    
111           looper.init ( );
112         }
113    
114         public void  destroy ( )
115         //////////////////////////////////////////////////////////////////////
116         {
117           looper.stop ( );
118    
119           looper.destroy ( );
120         }
121    
122         //////////////////////////////////////////////////////////////////////
123         //////////////////////////////////////////////////////////////////////
124    
125         public Object  serve ( Object  requestObject )
126         //////////////////////////////////////////////////////////////////////
127         {
128           if ( DEBUG )
129           {
130             System.out.println ( "ChatServer.serve(" + requestObject + ")" );
131           }
132    
133           synchronized ( this )
134           {
135             lastRequestTime = System.currentTimeMillis ( );
136    
137             if ( DEBUG )
138             {
139               ++count;
140             }
141           }
142    
143           looper.start ( );
144    
145           if ( requestObject instanceof CreateUserRequest )
146           {
147             CreateUserRequest  createUserRequest
148               = ( CreateUserRequest ) requestObject;
149    
150             return createUserServer.serve ( createUserRequest );
151           }
152    
153           if ( !( requestObject instanceof Request ) )
154           {
155             throw new IllegalArgumentException ( );
156           }
157    
158           Request  request = ( Request ) requestObject;
159    
160           Authentication  authentication = request.getAuthentication ( );
161    
162           User  user = userStore.getUser ( authentication );
163    
164           if ( user == null )
165           {
166             if ( request instanceof PullRequest )
167             {
168               return createUserServer.serve (
169                 new CreateUserRequest ( authentication ) );
170             }
171    
172             return new UnknownUserResponse ( request );
173           }
174    
175           user.updateLastRequestTime ( ); 
176    
177           if ( request instanceof PullRequest )
178           {
179             return pullServer.serve ( user, request );
180           }
181    
182           user.getRequestQueue ( ).replace ( request );
183    
184           return null;
185         }
186    
187         //////////////////////////////////////////////////////////////////////
188         // private methods
189         //////////////////////////////////////////////////////////////////////
190    
191         private boolean  loop ( )
192         //////////////////////////////////////////////////////////////////////
193         {
194           chatGame.update ( );
195    
196           long  currentTime = System.currentTimeMillis ( );
197    
198           synchronized ( this )
199           {
200             if ( DEBUG )
201             {
202               if ( currentTime >= startTime + SAMPLE_PERIOD )
203               {
204                 System.out.println ( "requests per second:  "
205                   + ( MathConstants.MILLISECONDS_PER_SECOND * count )
206                   / ( double ) ( currentTime - startTime ) );
207    
208                 startTime = currentTime;
209    
210                 count = 0;
211               }
212             }
213    
214             if ( currentTime
215               >= lastRequestTime + ChatConstants.REQUEST_TIMEOUT )
216             {
217               if ( DEBUG )
218               {
219                 System.out.println ( "ChatServer game loop pausing..." );
220               }
221    
222               return false;
223             }
224           }
225    
226           return true;
227         }
228    
229         //////////////////////////////////////////////////////////////////////
230         //////////////////////////////////////////////////////////////////////
231         }