openvidu-server: concurrent double initialization of single stream recording fix

pull/494/head
pabloFuente 2020-05-23 22:45:42 +02:00
parent 3374e511ee
commit f5171c9306
2 changed files with 92 additions and 57 deletions

View File

@ -17,6 +17,9 @@
package io.openvidu.server.core; package io.openvidu.server.core;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import io.openvidu.server.kurento.endpoint.EndpointType; import io.openvidu.server.kurento.endpoint.EndpointType;
@ -41,6 +44,12 @@ public class Participant {
private final String METADATA_SEPARATOR = "%/%"; private final String METADATA_SEPARATOR = "%/%";
/**
* This lock protects the initialization of a RecorderEndpoint when INDIVIDUAL
* recording
*/
public Lock singleRecordingLock = new ReentrantLock();
public Participant(String finalUserId, String participantPrivatetId, String participantPublicId, String sessionId, public Participant(String finalUserId, String participantPrivatetId, String participantPublicId, String sessionId,
Token token, String clientMetadata, GeoLocation location, String platform, EndpointType endpointType, Token token, String clientMetadata, GeoLocation location, String platform, EndpointType endpointType,
Long createdAt) { Long createdAt) {

View File

@ -208,9 +208,20 @@ public class SingleStreamRecordingService extends RecordingService {
public void startRecorderEndpointForPublisherEndpoint(final Session session, String recordingId, public void startRecorderEndpointForPublisherEndpoint(final Session session, String recordingId,
MediaProfileSpecType profile, final Participant participant, CountDownLatch globalStartLatch) { MediaProfileSpecType profile, final Participant participant, CountDownLatch globalStartLatch) {
log.info("Starting single stream recorder for stream {} in session {}", participant.getPublisherStreamId(), log.info("Starting single stream recorder for stream {} in session {}", participant.getPublisherStreamId(),
session.getSessionId()); session.getSessionId());
try {
if (participant.singleRecordingLock.tryLock(15, TimeUnit.SECONDS)) {
try {
if (this.activeRecorders.get(session.getSessionId())
.containsKey(participant.getPublisherStreamId())) {
log.warn("Concurrent initialization of RecorderEndpoint for stream {} of session {}. Returning",
participant.getPublisherStreamId(), session.getSessionId());
return;
}
if (recordingId == null) { if (recordingId == null) {
// Stream is being recorded because is a new publisher in an ongoing recorded // Stream is being recorded because is a new publisher in an ongoing recorded
// session. If recordingId is defined is because Stream is being recorded from // session. If recordingId is defined is because Stream is being recorded from
@ -260,9 +271,10 @@ public class SingleStreamRecordingService extends RecordingService {
} }
}); });
RecorderEndpointWrapper wrapper = new RecorderEndpointWrapper(recorder, participant.getParticipantPublicId(), RecorderEndpointWrapper wrapper = new RecorderEndpointWrapper(recorder,
recordingId, participant.getPublisherStreamId(), participant.getClientMetadata(), participant.getParticipantPublicId(), recordingId, participant.getPublisherStreamId(),
participant.getServerMetadata(), kurentoParticipant.getPublisher().getMediaOptions().hasAudio(), participant.getClientMetadata(), participant.getServerMetadata(),
kurentoParticipant.getPublisher().getMediaOptions().hasAudio(),
kurentoParticipant.getPublisher().getMediaOptions().hasVideo(), kurentoParticipant.getPublisher().getMediaOptions().hasVideo(),
kurentoParticipant.getPublisher().getMediaOptions().getTypeOfVideo()); kurentoParticipant.getPublisher().getMediaOptions().getTypeOfVideo());
@ -271,6 +283,20 @@ public class SingleStreamRecordingService extends RecordingService {
connectAccordingToProfile(kurentoParticipant.getPublisher(), recorder, profile); connectAccordingToProfile(kurentoParticipant.getPublisher(), recorder, profile);
wrapper.getRecorder().record(); wrapper.getRecorder().record();
} finally {
participant.singleRecordingLock.unlock();
}
} else {
log.error(
"Timeout waiting for individual recording lock to be available for participant {} of session {}",
participant.getParticipantPublicId(), session.getSessionId());
}
} catch (InterruptedException e) {
log.error(
"InterruptedException waiting for individual recording lock to be available for participant {} of session {}",
participant.getParticipantPublicId(), session.getSessionId());
}
} }
public void stopRecorderEndpointOfPublisherEndpoint(String sessionId, String streamId, public void stopRecorderEndpointOfPublisherEndpoint(String sessionId, String streamId,