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 }