Author: sebawagner Date: Fri Dec 14 07:42:19 2012 New Revision: 1421703 URL: http://svn.apache.org/viewvc?rev=1421703&view=rev Log: OPENMEETINGS-460 Fixes: When a user is hosted on a slave and uploads a document, the document is uploaded via HTTP and send to the server. The upload complete message has to be send to the slave server first, the master can't send a upload complete message. Also fixes a Bug + provides a JUnit test for an bug in the getServerForSession method
Added: incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/conference/room/ClientSessionInfo.java Modified: incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/conference/room/ClientListHashMapStore.java incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/conference/room/IClientList.java incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/conference/room/cache/HashMapStore.java incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/remote/ConferenceService.java incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/remote/red5/ScopeApplicationAdapter.java Modified: incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/conference/room/ClientListHashMapStore.java URL: http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/conference/room/ClientListHashMapStore.java?rev=1421703&r1=1421702&r2=1421703&view=diff ============================================================================== --- incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/conference/room/ClientListHashMapStore.java (original) +++ incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/conference/room/ClientListHashMapStore.java Fri Dec 14 07:42:19 2012 @@ -152,6 +152,22 @@ public class ClientListHashMapStore impl } return null; } + + public ClientSessionInfo getClientByPublicSIDAnyServer(String publicSID, boolean isAVClient) { + try { + for (Entry<Long,List<RoomClient>> entry : cache.getClientsByPublicSID(publicSID).entrySet()) { + for (RoomClient rcl : entry.getValue()) { + if (rcl.getIsAVClient() != isAVClient) { + continue; + } + return new ClientSessionInfo(rcl, entry.getKey()); + } + } + } catch (Exception err) { + log.error("[getClientByPublicSIDAnyServer]", err); + } + return null; + } public synchronized RoomClient getClientByUserId(Long userId) { try { @@ -291,7 +307,7 @@ public class ClientListHashMapStore impl sResult.setRecords(Long.valueOf(cache.size()).longValue()); ArrayList<ClientSession> myList = new ArrayList<ClientSession>(cache.size()); - //FIXME: Improve the handling of the Arrays/Map/List so that this reparsing is not needed + //FIXME: Improve the handling of the Arrays/Map/List so that this re-parsing is not needed for (Entry<Long, LinkedHashMap<String, RoomClient>> entry : cache.values().entrySet()) { for (RoomClient rcl : entry.getValue().values()) { myList.add(new ClientSession(entry.getKey(), rcl)); Added: incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/conference/room/ClientSessionInfo.java URL: http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/conference/room/ClientSessionInfo.java?rev=1421703&view=auto ============================================================================== --- incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/conference/room/ClientSessionInfo.java (added) +++ incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/conference/room/ClientSessionInfo.java Fri Dec 14 07:42:19 2012 @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License") + you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openmeetings.conference.room; + +public class ClientSessionInfo { + + private RoomClient rcl; + public Long serverId; + + public ClientSessionInfo(RoomClient rcl, Long serverId) { + super(); + this.rcl = rcl; + this.serverId = serverId; + } + + public RoomClient getRcl() { + return rcl; + } + public void setRcl(RoomClient rcl) { + this.rcl = rcl; + } + public Long getServerId() { + return serverId; + } + public void setServerId(Long serverId) { + this.serverId = serverId; + } + +} Modified: incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/conference/room/IClientList.java URL: http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/conference/room/IClientList.java?rev=1421703&r1=1421702&r2=1421703&view=diff ============================================================================== --- incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/conference/room/IClientList.java (original) +++ incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/conference/room/IClientList.java Fri Dec 14 07:42:19 2012 @@ -64,8 +64,33 @@ public interface IClientList { */ public abstract RoomClient getSyncClientByStreamId(String streamId); + /** + * get a client by its publicSID and the server, + * isAVClient is normally false, as you want the data connection. + * If you set isAVClient to true, you would obtain the RTMP + * connection that is used for Audio/Video streaming + * + * @param publicSID + * @param isAVClient + * @param server + * @return + */ public abstract RoomClient getClientByPublicSID(String publicSID, boolean isAVClient, Server server); + + /** + * same as {@link #getClientByPublicSID(String, boolean, Server)} but it ignores + * if the server part, so it will deliver any client just by its publicSID.<br/> + * <br/> + * <b>Note:</b> + * This method requires more time to find the user, so under normal circumstances + * you should use {@link #getClientByPublicSID(String, boolean, Server)}! + * + * @param publicSID + * @param isAVClient + * @return + */ + public ClientSessionInfo getClientByPublicSIDAnyServer(String publicSID, boolean isAVClient); /** * Modified: incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/conference/room/cache/HashMapStore.java URL: http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/conference/room/cache/HashMapStore.java?rev=1421703&r1=1421702&r2=1421703&view=diff ============================================================================== --- incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/conference/room/cache/HashMapStore.java (original) +++ incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/conference/room/cache/HashMapStore.java Fri Dec 14 07:42:19 2012 @@ -19,8 +19,10 @@ package org.apache.openmeetings.conference.room.cache; import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Map.Entry; import org.apache.openmeetings.OpenmeetingsVariables; @@ -43,7 +45,7 @@ import org.slf4j.Logger; * <li>client by publicSID</li> * <li>client by userId</li> * <li>clients by roomId</li> - * <li>TODO: roomIds by server</li> + * <li>roomIds by server</li> * </ul> * * @author sebawagner @@ -222,7 +224,7 @@ public class HashMapStore { } return null; } - + /** * * @param server @@ -242,6 +244,23 @@ public class HashMapStore { } /** + * Searches for the publicSID across all servers + * + * @param publicSID + * @return will return a map with the serverId as key and the RoomClients as list in the value + */ + public Map<Long,List<RoomClient>> getClientsByPublicSID(String publicSID) { + Map<Long,List<RoomClient>> clientList = new HashMap<Long,List<RoomClient>>(); + for (Entry<Long, LinkedHashMap<String, List<RoomClient>>> entry : clientsByServerAndPublicSID.entrySet()) { + List<RoomClient> clientListAtThisServer = entry.getValue().get(publicSID); + if (clientListAtThisServer != null) { + clientList.put(entry.getKey(), clientListAtThisServer); + } + } + return clientList; + } + + /** * get all clients by a specific {@link Server} * * @param server Modified: incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/remote/ConferenceService.java URL: http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/remote/ConferenceService.java?rev=1421703&r1=1421702&r2=1421703&view=diff ============================================================================== --- incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/remote/ConferenceService.java (original) +++ incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/remote/ConferenceService.java Fri Dec 14 07:42:19 2012 @@ -62,7 +62,7 @@ import org.springframework.beans.factory /** * - * @author swagner + * @author sebawagner * */ public class ConferenceService { @@ -794,6 +794,13 @@ public class ConferenceService { //But if the room is already opened, then the maxUser is no more relevant, //the user will be just redirected to the same server + //check if the user is on master hosted, (serverId == null) + for (Long activeRoomId : clientListManager.getActiveRoomIdsByServer(null)) { + if (activeRoomId.equals(roomId)) { + return null; + } + } + for (Server server : serverList) { for (Long activeRoomId : clientListManager.getActiveRoomIdsByServer(server)) { if (activeRoomId.equals(roomId)) { Modified: incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/remote/red5/ScopeApplicationAdapter.java URL: http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/remote/red5/ScopeApplicationAdapter.java?rev=1421703&r1=1421702&r2=1421703&view=diff ============================================================================== --- incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/remote/red5/ScopeApplicationAdapter.java (original) +++ incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/remote/red5/ScopeApplicationAdapter.java Fri Dec 14 07:42:19 2012 @@ -30,6 +30,7 @@ import java.util.Map; import java.util.Set; import org.apache.openmeetings.OpenmeetingsVariables; +import org.apache.openmeetings.conference.room.ClientSessionInfo; import org.apache.openmeetings.conference.room.IClientList; import org.apache.openmeetings.conference.room.RoomClient; import org.apache.openmeetings.conference.whiteboard.BrowserStatus; @@ -37,6 +38,7 @@ import org.apache.openmeetings.conferenc import org.apache.openmeetings.conference.whiteboard.WhiteboardManagement; import org.apache.openmeetings.data.basic.Sessionmanagement; import org.apache.openmeetings.data.basic.dao.ConfigurationDao; +import org.apache.openmeetings.data.basic.dao.ServerDao; import org.apache.openmeetings.data.calendar.daos.MeetingMemberDao; import org.apache.openmeetings.data.calendar.management.AppointmentLogic; import org.apache.openmeetings.data.conference.RoomDAO; @@ -49,6 +51,7 @@ import org.apache.openmeetings.persisten import org.apache.openmeetings.persistence.beans.calendar.MeetingMember; import org.apache.openmeetings.persistence.beans.rooms.Rooms; import org.apache.openmeetings.persistence.beans.user.Users; +import org.apache.openmeetings.quartz.scheduler.ClusterSlaveJob; import org.apache.openmeetings.remote.FLVRecorderService; import org.apache.openmeetings.remote.WhiteBoardService; import org.apache.openmeetings.utils.OmFileHelper; @@ -102,6 +105,10 @@ public class ScopeApplicationAdapter ext private RoomDAO roomDao; @Autowired private MeetingMemberDao meetingMemberDao; + @Autowired + private ClusterSlaveJob clusterSlaveJob; + @Autowired + private ServerDao serverDao; public static String lineSeperator = System.getProperty("line.separator"); @@ -2502,17 +2509,30 @@ public class ScopeApplicationAdapter ext } public synchronized void sendUploadCompletMessageByPublicSID(UploadCompleteMessage message, String publicSID) { - - //if the upload is locally, just proceed to the normal function - //Search for RoomClient on current server (serverId == null means it will look on the master for the RoomClient) - RoomClient currentClient = this.clientListManager - .getClientByPublicSID(publicSID, false, null); - - if (currentClient != null) { - sendMessageWithClientByPublicSID(message, publicSID); + try { + //if the upload is locally, just proceed to the normal function + //Search for RoomClient on current server (serverId == null means it will look on the master for the RoomClient) + RoomClient currentClient = this.clientListManager + .getClientByPublicSID(publicSID, false, null); + + if (currentClient != null) { + sendMessageWithClientByPublicSID(message, publicSID); + } + + //Check if the client is on any slave host + ClientSessionInfo clientSessionInfo = this.clientListManager.getClientByPublicSIDAnyServer(publicSID, false); + + if (clientSessionInfo == null) { + throw new Exception( + "Could not Find RoomClient on List publicSID: "+ publicSID); + } + + clusterSlaveJob.syncMessageToClientOnSlave( + serverDao.get(clientSessionInfo.getServerId()), clientSessionInfo.getRcl().getPublicSID(), message); + + } catch (Exception err) { + log.error("[sendMessageWithClient] ", err); } - - //Check if the client is on any slave host } @@ -2584,7 +2604,6 @@ public class ScopeApplicationAdapter ext } } catch (Exception err) { log.error("[sendMessageWithClient] ", err); - err.printStackTrace(); } } @@ -2672,7 +2691,6 @@ public class ScopeApplicationAdapter ext } catch (Exception err) { log.error("[sendMessageWithClient] ", err); - err.printStackTrace(); } }