All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.antmedia.datastore.db.MongoStore Maven / Gradle / Ivy

Go to download

Ant Media Server supports RTMP, RTSP, MP4, HLS, WebRTC, Adaptive Streaming, etc.

There is a newer version: 2.10.0
Show newest version
package io.antmedia.datastore.db;

import java.io.File;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.bson.types.ObjectId;
import org.mongodb.morphia.Datastore;
import org.mongodb.morphia.Key;
import org.mongodb.morphia.Morphia;
import org.mongodb.morphia.query.Criteria;
import org.mongodb.morphia.query.FindOptions;
import org.mongodb.morphia.query.Query;
import org.mongodb.morphia.query.UpdateOperations;
import org.mongodb.morphia.query.UpdateResults;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.WriteResult;

import io.antmedia.AntMediaApplicationAdapter;
import io.antmedia.datastore.db.types.Broadcast;
import io.antmedia.datastore.db.types.ConferenceRoom;
import io.antmedia.datastore.db.types.Endpoint;
import io.antmedia.datastore.db.types.P2PConnection;
import io.antmedia.datastore.db.types.Playlist;
import io.antmedia.datastore.db.types.SocialEndpointCredentials;
import io.antmedia.datastore.db.types.StreamInfo;
import io.antmedia.datastore.db.types.TensorFlowObject;
import io.antmedia.datastore.db.types.Token;
import io.antmedia.datastore.db.types.VoD;
import io.antmedia.muxer.MuxAdaptor;
import io.antmedia.settings.ServerSettings;

public class MongoStore extends DataStore {

	private Morphia morphia;
	private Datastore datastore;
	private Datastore vodDatastore;
	private Datastore endpointCredentialsDS;
	private Datastore tokenDatastore;
	private Datastore detectionMap;
	private Datastore conferenceRoomDatastore;

	protected static Logger logger = LoggerFactory.getLogger(MongoStore.class);

	public static final String IMAGE_ID = "imageId"; 
	public static final String STATUS = "status";
	private static final String ORIGIN_ADDRESS = "originAdress";
	private static final String START_TIME = "startTime"; 
	private static final String DURATION = "duration"; 
	private static final String CREATION_DATE = "creationDate";
	private static final String PLAYLIST_ID = "playlistId";

	
	public MongoStore(String host, String username, String password, String dbName) {
		morphia = new Morphia();
		morphia.mapPackage("io.antmedia.datastore.db.types");

		String uri = getMongoConnectionUri(host, username, password);

		MongoClientURI mongoUri = new MongoClientURI(uri);
		MongoClient client = new MongoClient(mongoUri);
		
		
		
		//TODO: Refactor these stores so that we don't have separate datastore for each class
		datastore = morphia.createDatastore(client, dbName);
		vodDatastore=morphia.createDatastore(client, dbName+"VoD");
		endpointCredentialsDS = morphia.createDatastore(client, dbName+"_endpointCredentials");
		tokenDatastore = morphia.createDatastore(client, dbName + "_token");
		detectionMap = morphia.createDatastore(client, dbName + "detection");
		conferenceRoomDatastore = morphia.createDatastore(client, dbName + "room");

		
		//*************************************************
		//do not create data store for each type as we do above
		//*************************************************

		tokenDatastore.ensureIndexes();
		datastore.ensureIndexes();
		vodDatastore.ensureIndexes();
		endpointCredentialsDS.ensureIndexes();
		detectionMap.ensureIndexes();
		conferenceRoomDatastore.ensureIndexes();
	}
	
	public static String getMongoConnectionUri(String host, String username, String password) {
		String credential = "";
		if(username != null && !username.isEmpty()) {
			credential = username+":"+password+"@";
		}

		String uri = "mongodb://"+credential+host;

		logger.info("uri:{}",uri);

		return uri;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * io.antmedia.datastore.db.IDataStore#save(io.antmedia.datastore.db.types.
	 * Broadcast)
	 */
	@Override
	public String save(Broadcast broadcast) {
		if (broadcast == null) {
			return null;
		}
		try {
			String streamId = null;
			if (broadcast.getStreamId() == null) {
				streamId = RandomStringUtils.randomAlphanumeric(12) + System.currentTimeMillis();
				broadcast.setStreamId(streamId);
			}
			streamId = broadcast.getStreamId();
			String rtmpURL = broadcast.getRtmpURL();
			if (rtmpURL != null) {
				rtmpURL += streamId;
			}
			broadcast.setRtmpURL(rtmpURL);
			if(broadcast.getStatus()==null) {
				broadcast.setStatus(AntMediaApplicationAdapter.BROADCAST_STATUS_CREATED);
			}

			synchronized(this) {
				Key key = datastore.save(broadcast);
			}
			return streamId;
		} catch (Exception e) {
			logger.error(ExceptionUtils.getStackTrace(e));
		}
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see io.antmedia.datastore.db.IDataStore#get(java.lang.String)
	 */
	@Override
	public Broadcast get(String id) {
		synchronized(this) {
			try {
				return datastore.find(Broadcast.class).field("streamId").equal(id).get();
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return null;
	}

	@Override
	public VoD getVoD(String id) {
		synchronized(this) {
			try {
				return vodDatastore.find(VoD.class).field("vodId").equal(id).get();
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see io.antmedia.datastore.db.IDataStore#updateStatus(java.lang.String,
	 * java.lang.String)
	 */
	@Override
	public boolean updateStatus(String id, String status) {
		synchronized(this) {
			try {
				Query query = datastore.createQuery(Broadcast.class).field("streamId").equal(id);

				UpdateOperations ops = datastore.createUpdateOperations(Broadcast.class).set(STATUS, status);

				if(status.contentEquals(AntMediaApplicationAdapter.BROADCAST_STATUS_BROADCASTING)) {
					ops.set(START_TIME, System.currentTimeMillis());
				}
				
				UpdateResults update = datastore.update(query, ops);
				return update.getUpdatedCount() == 1;
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return false;

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see io.antmedia.datastore.db.IDataStore#updateDuration(java.lang.String,
	 * long)
	 */
	@Override
	public boolean updateDuration(String id, long duration) {
		synchronized(this) {
			try {
				Query query = datastore.createQuery(Broadcast.class).field("streamId").equal(id);

				UpdateOperations ops = datastore.createUpdateOperations(Broadcast.class).set(DURATION,
						duration);

				UpdateResults update = datastore.update(query, ops);
				return update.getUpdatedCount() == 1;
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return false;
	}



	/*
	 * (non-Javadoc)
	 * 
	 * @see io.antmedia.datastore.db.IDataStore#addEndpoint(java.lang.String,
	 * io.antmedia.datastore.db.types.Endpoint)
	 */
	@Override
	public boolean addEndpoint(String id, Endpoint endpoint) {
		synchronized(this) {
			if (id != null && endpoint != null) {
				try {
					Query query = datastore.createQuery(Broadcast.class).field("streamId").equal(id);

					UpdateOperations ops = datastore.createUpdateOperations(Broadcast.class).push("endPointList",
							endpoint);

					UpdateResults update = datastore.update(query, ops);
					return update.getUpdatedCount() == 1;
				} catch (Exception e) {
					logger.error(ExceptionUtils.getStackTrace(e));
				}
			}
		}
		return false;
	}

	@Override
	public boolean removeEndpoint(String id, Endpoint endpoint) {
		boolean result = false;
		synchronized(this) {
			if (id != null && endpoint != null) {
				Query query = datastore.createQuery(Broadcast.class).field("streamId").equal(id);
				UpdateOperations ops = datastore.createUpdateOperations(Broadcast.class)

						.removeAll("endPointList", endpoint);
				UpdateResults update = datastore.update(query, ops);
				return update.getUpdatedCount() == 1;
			}
		}
		return result;
	}

	@Override
	public boolean removeAllEndpoints(String id) {
		boolean result = false;
		synchronized(this) {
			if (id != null) {
				Query query = datastore.createQuery(Broadcast.class).field("streamId").equal(id);
				UpdateOperations ops = datastore.createUpdateOperations(Broadcast.class).unset("endPointList");
				UpdateResults update = datastore.update(query, ops);
				return update.getUpdatedCount() == 1;
			}
		}
		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see io.antmedia.datastore.db.IDataStore#getBroadcastCount()
	 */
	@Override
	public long getBroadcastCount() {
		synchronized(this) {
			return datastore.getCount(Broadcast.class);
		}
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see io.antmedia.datastore.db.IDataStore#delete(java.lang.String)
	 */
	@Override
	public boolean delete(String id) {
		synchronized(this) {
			try {
				Query query = datastore.createQuery(Broadcast.class).field("streamId").equal(id);
				WriteResult delete = datastore.delete(query);
				return delete.getN() == 1;
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return false;
	}

	@Override
	public List getBroadcastList(int offset, int size) {
		synchronized(this) {
			if (size > MAX_ITEM_IN_ONE_LIST) {
				size = MAX_ITEM_IN_ONE_LIST;
			}
			return datastore.find(Broadcast.class).asList(new FindOptions().skip(offset).limit(size));
		}
	}

	public Datastore getDataStore() {
		return datastore;
	}




	@Override
	public List getExternalStreamsList() {
		synchronized(this) {
			try {
				Query query = datastore.createQuery(Broadcast.class);
				query.and(
						query.or(
								query.criteria("type").equal(AntMediaApplicationAdapter.IP_CAMERA),
								query.criteria("type").equal(AntMediaApplicationAdapter.STREAM_SOURCE)
								), 
						query.and(
								query.criteria(STATUS).notEqual(AntMediaApplicationAdapter.BROADCAST_STATUS_PREPARING),
								query.criteria(STATUS).notEqual(AntMediaApplicationAdapter.BROADCAST_STATUS_BROADCASTING)
								)
						);
				
				List streamList = query.asList();
				
				UpdateOperations ops = datastore.createUpdateOperations(Broadcast.class).set(STATUS, AntMediaApplicationAdapter.BROADCAST_STATUS_PREPARING);
				UpdateResults update = datastore.update(query, ops);
				int updatedCount = update.getUpdatedCount();
				if(updatedCount != streamList.size()) {
					logger.error("Only {} stream status updated out of {}", updatedCount, streamList.size());
				}
						
				return streamList;
			} catch (Exception e) {

				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return null;
	}

	@Override
	public void close() {
		synchronized(this) {
			datastore.getMongo().close();
		}
	}

	@Override
	public List filterBroadcastList(int offset, int size, String type) {
		synchronized(this) {
			try {
				return datastore.find(Broadcast.class).field("type").equal(type).asList(new FindOptions().skip(offset).limit(size));
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return null;	
	}

	@Override
	public String addVod(VoD vod) {

		String id = null;
		boolean result = false;
		synchronized(this) {
			try {	
				if (vod.getVodId() == null) {
					vod.setVodId(RandomStringUtils.randomAlphanumeric(12) + System.currentTimeMillis());
				}
				vodDatastore.save(vod);
				result = true;
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}

			if(result) {
				id = vod.getVodId();
			}
		}
		return id;

	}

	@Override
	public List getVodList(int offset, int size, String sortBy, String orderBy) {
		synchronized(this) {
			if(sortBy != null && orderBy != null && !sortBy.isEmpty() && !orderBy.isEmpty()) {
				String sortString = orderBy.contentEquals("desc") ? "-" : "";
				if(sortBy.contentEquals("name")) {
					sortString += "vodName";
				}
				else if(sortBy.contentEquals("date")) {
					sortString += CREATION_DATE;
				}
				return vodDatastore.find(VoD.class).order(sortString).asList(new FindOptions().skip(offset).limit(size));
			}
			return vodDatastore.find(VoD.class).asList(new FindOptions().skip(offset).limit(size));
		}
	}


	@Override
	public boolean deleteVod(String id) {
		synchronized(this) {
			try {
				Query query = vodDatastore.createQuery(VoD.class).field("vodId").equal(id);
				WriteResult delete = vodDatastore.delete(query);
				return delete.getN() == 1;
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return false;
	}



	@Override
	public long getTotalVodNumber() {
		synchronized(this) {
			return vodDatastore.getCount(VoD.class);
		}
	}

	@Override
	public int fetchUserVodList(File userfile) {

		if(userfile==null) {
			return 0;
		}

		int numberOfSavedFiles = 0;
		synchronized(this) {
			try {
				Query query = vodDatastore.createQuery(VoD.class).field("type").equal("userVod");
				WriteResult delete = vodDatastore.delete(query);
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}

			File[] listOfFiles = userfile.listFiles();

			if (listOfFiles != null) {

				for (File file : listOfFiles) {

					String fileExtension = FilenameUtils.getExtension(file.getName());

					if (file.isFile() &&
							("mp4".equals(fileExtension) || "flv".equals(fileExtension) || "mkv".equals(fileExtension))) {

						long fileSize = file.length();
						long unixTime = System.currentTimeMillis();


						String filePath=file.getPath();

						String[] subDirs = filePath.split(Pattern.quote(File.separator));

						Integer pathLength=Integer.valueOf(subDirs.length);

						String relativePath = "streams/"+subDirs[pathLength-2]+'/'+subDirs[pathLength-1];
						String vodId = RandomStringUtils.randomNumeric(24);
						VoD newVod = new VoD("vodFile", "vodFile", relativePath, file.getName(), unixTime, 0, fileSize,
								VoD.USER_VOD,vodId);

						addVod(newVod);
						numberOfSavedFiles++;
					}
				}
			}
		}
		return numberOfSavedFiles;

	}




	@Override
	public boolean updateSourceQualityParametersLocal(String id, String quality, double speed, int pendingPacketQueue) {
		synchronized(this) {
			try {
				Query query = datastore.createQuery(Broadcast.class).field("streamId").equal(id);
				UpdateOperations ops = datastore.createUpdateOperations(Broadcast.class)
						.set("speed", speed).set("pendingPacketSize", pendingPacketQueue);

				if (quality != null) {
					ops.set("quality", quality);
				}
				UpdateResults update = datastore.update(query, ops);
				return update.getUpdatedCount() == 1;
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return false;
	}


	public SocialEndpointCredentials addSocialEndpointCredentials(SocialEndpointCredentials credentials) {
		SocialEndpointCredentials addedCredential = null;
		synchronized(this) {
			if (credentials != null && credentials.getAccountName() != null && credentials.getAccessToken() != null
					&& credentials.getServiceName() != null) 
			{
				if (credentials.getId() == null) {
					//create new id if id is not set
					//String id = RandomStringUtils.randomAlphanumeric(6);
					//credentials.setId(id);
					endpointCredentialsDS.save(credentials);
					addedCredential = credentials;
				}
				else {
					SocialEndpointCredentials endpointCredentials = getSocialEndpointCredentials(credentials.getId());
					if (endpointCredentials != null) {
						UpdateOperations ops = endpointCredentialsDS
								.createUpdateOperations(SocialEndpointCredentials.class)
								.set("accessToken", credentials.getAccessToken());
						if (credentials.getAccountId() != null) {
							ops.set("accountId", credentials.getAccountId());
						}
						if (credentials.getAccountName() != null) {
							ops.set("accountName", credentials.getAccountName());
						}
						if (credentials.getAccountType() != null) {
							ops.set("accountType", credentials.getAccountType());
						}
						if (credentials.getAuthTimeInMilliseconds() != null) {
							ops.set("authTimeInMilliseconds", credentials.getAuthTimeInMilliseconds());
						}
						if (credentials.getExpireTimeInSeconds() != null) {
							ops.set("expireTimeInSeconds", credentials.getExpireTimeInSeconds());
						}
						if (credentials.getRefreshToken() != null) {
							ops.set("refreshToken", credentials.getRefreshToken());
						}
						if (credentials.getTokenType() != null) {
							ops.set("tokenType", credentials.getTokenType());
						}



						UpdateResults update = endpointCredentialsDS.update(endpointCredentials, ops);
						addedCredential = credentials;
					}
				}
			}
		}
		return addedCredential;
	}

	@Override
	public List getSocialEndpoints(int offset, int size) {
		synchronized(this) {
			return endpointCredentialsDS.find(SocialEndpointCredentials.class).asList(new FindOptions().skip(offset).limit(size));
		}
	}

	@Override
	public boolean removeSocialEndpointCredentials(String id) {
		synchronized(this) {
			try {
				Query query = endpointCredentialsDS
						.createQuery(SocialEndpointCredentials.class)
						.field("id").equal(new ObjectId(id));
				WriteResult delete = endpointCredentialsDS.delete(query);
				return delete.getN() == 1;
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return false;
	}

	@Override
	public SocialEndpointCredentials getSocialEndpointCredentials(String id) {
		synchronized(this) {
			try {
				return endpointCredentialsDS.get(SocialEndpointCredentials.class, new ObjectId(id));
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return null;
	}

	public Datastore getEndpointCredentialsDS() {
		return endpointCredentialsDS;
	}

	public void setEndpointCredentialsDS(Datastore endpointCredentialsDS) {
		this.endpointCredentialsDS = endpointCredentialsDS;
	}

	@Override
	public long getTotalBroadcastNumber() {
		synchronized(this) {
			return datastore.getCount(Broadcast.class);
		}
	}

	public Datastore getVodDatastore() {
		return vodDatastore;
	}

	public void setVodDatastore(Datastore vodDatastore) {
		this.vodDatastore = vodDatastore;
	}

	@Override
	public long getActiveBroadcastCount() {
		synchronized(this) {
			return datastore.find(Broadcast.class).filter(STATUS, AntMediaApplicationAdapter.BROADCAST_STATUS_BROADCASTING).count();
		}
	}

	public void saveDetection(String id, long timeElapsed, List detectedObjects) {
		synchronized(this) {
			if (detectedObjects != null) {
				for (TensorFlowObject tensorFlowObject : detectedObjects) {
					tensorFlowObject.setDetectionTime(timeElapsed);
					tensorFlowObject.setImageId(id);
					detectionMap.save(tensorFlowObject);
				}
			}
		}
	}

	@Override
	public List getDetectionList(String idFilter, int offsetSize, int batchSize) {
		synchronized(this) {
			try {
				if (batchSize > MAX_ITEM_IN_ONE_LIST) {
					batchSize = MAX_ITEM_IN_ONE_LIST;
				}
				return detectionMap.find(TensorFlowObject.class).field(IMAGE_ID).startsWith(idFilter).asList(new FindOptions().skip(offsetSize).limit(batchSize));
			} catch (Exception e) {
				logger.error(e.getMessage());
			}
		}
		return null;	
	}

	@Override
	public List getDetection(String id) {
		synchronized(this) {
			try {
				return detectionMap.find(TensorFlowObject.class).field(IMAGE_ID).equal(id).asList();
			} catch (Exception e) {
				logger.error(e.getMessage());
			}
		}
		return null;	
	}

	@Override
	public long getObjectDetectedTotal(String id) {
		synchronized(this) {
			return detectionMap.find(TensorFlowObject.class).field(IMAGE_ID).equal(id).asList().size();
		}
	}



	@Override
	public boolean updateBroadcastFields(String streamId, Broadcast broadcast) {
		boolean result = false;
		synchronized(this) {
			try {
				logger.warn("result inside edit camera: {}" , result);
				Query query = datastore.createQuery(Broadcast.class).field("streamId").equal(streamId);

				UpdateOperations ops = datastore.createUpdateOperations(Broadcast.class);
				if (broadcast.getName() != null) {
					ops.set("name", broadcast.getName());
				}

				if (broadcast.getDescription() != null) {
					ops.set("description", broadcast.getDescription());
				}

				if (broadcast.getUsername() != null) {
					ops.set("username", broadcast.getUsername());
				}

				if (broadcast.getPassword() != null) {
					ops.set("password", broadcast.getPassword());
				}

				if (broadcast.getIpAddr() != null) {
					ops.set("ipAddr", broadcast.getIpAddr());
				}

				if ( broadcast.getStreamUrl() != null) {
					ops.set("streamUrl", broadcast.getStreamUrl());
				}
				
				if ( broadcast.getDuration() != null) {
					ops.set(DURATION, broadcast.getDuration());
				}
				
				if (broadcast.getLatitude() != null) {
					ops.set("latitude", broadcast.getLatitude());
				}
				
				if (broadcast.getLongitude() != null) {
					ops.set("longitude", broadcast.getLongitude());
				}
				
				if (broadcast.getAltitude() != null) {
					ops.set("altitude", broadcast.getAltitude());
				}
				
				if (broadcast.getMainTrackStreamId() != null) {
					ops.set("mainTrackStreamId", broadcast.getMainTrackStreamId());
				}
				
				if (broadcast.getStartTime() != 0) {
					ops.set(START_TIME, broadcast.getStartTime());
				}
				
				if (broadcast.getOriginAdress() != null) {
					ops.set(ORIGIN_ADDRESS, broadcast.getOriginAdress());
				}
				
				if (broadcast.getStatus() != null) {
					ops.set(STATUS, broadcast.getStatus());
				}
				
				
				ops.set("receivedBytes", broadcast.getReceivedBytes());
				ops.set("bitrate", broadcast.getBitrate());
				ops.set("userAgent", broadcast.getUserAgent());

				UpdateResults update = datastore.update(query, ops);
				return update.getUpdatedCount() == 1;
			} catch (Exception e) {
				logger.error(e.getMessage());
			}
		}
		return false;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean updateHLSViewerCountLocal(String streamId, int diffCount) {
		synchronized(this) {
			try {
				Query query = datastore.createQuery(Broadcast.class).field("streamId").equal(streamId);
				UpdateOperations ops = datastore.createUpdateOperations(Broadcast.class).inc("hlsViewerCount", diffCount);

				UpdateResults update = datastore.update(query, ops);
				return update.getUpdatedCount() == 1;
			} catch (Exception e) {
				logger.error(e.getMessage());
			}
		}
		return false;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean updateWebRTCViewerCountLocal(String streamId, boolean increment) {
		return updateViewerField(streamId, increment, "webRTCViewerCount");
	}

	@Override
	public boolean updateRtmpViewerCountLocal(String streamId, boolean increment) {
		return updateViewerField(streamId, increment, "rtmpViewerCount");
	}

	private boolean updateViewerField(String streamId, boolean increment, String fieldName) {
		synchronized(this) {
			try {
				Query query = datastore.createQuery(Broadcast.class).field("streamId").equal(streamId);
				UpdateOperations ops = datastore.createUpdateOperations(Broadcast.class);
				String field = fieldName;
				if (increment) {
					ops.inc(field);
				}
				else {
					ops.dec(field);
				}

				UpdateResults update = datastore.update(query, ops);
				return update.getUpdatedCount() == 1;
			} catch (Exception e) {
				logger.error(e.getMessage());
			}
		}
		return false;
	}


	@Override
	public void saveStreamInfo(StreamInfo streamInfo) {
		synchronized(this) {
			Query query = datastore.createQuery(StreamInfo.class);
			
			List criteriaList = new ArrayList<>();
			if (streamInfo.getVideoPort() != 0) {
				criteriaList.add(query.criteria("videoPort").equal(streamInfo.getVideoPort()));
				criteriaList.add(query.criteria("audioPort").equal(streamInfo.getVideoPort()));
				criteriaList.add(query.criteria("dataChannelPort").equal(streamInfo.getVideoPort()));
			}
			if (streamInfo.getAudioPort() != 0) {
				criteriaList.add(query.criteria("videoPort").equal(streamInfo.getAudioPort()));
				criteriaList.add(query.criteria("audioPort").equal(streamInfo.getAudioPort()));
				criteriaList.add(query.criteria("dataChannelPort").equal(streamInfo.getAudioPort()));
			}
			
			if (streamInfo.getDataChannelPort() != 0) {
				criteriaList.add(query.criteria("videoPort").equal(streamInfo.getDataChannelPort()));
				criteriaList.add(query.criteria("audioPort").equal(streamInfo.getDataChannelPort()));
				criteriaList.add(query.criteria("dataChannelPort").equal(streamInfo.getDataChannelPort()));
			}
			
			Criteria[] criteriaArray = new Criteria[criteriaList.size()];
			criteriaList.toArray(criteriaArray);
			if (criteriaArray.length > 0) {
				query.and(
						query.criteria("host").equal(streamInfo.getHost()),
						query.or(
								criteriaArray
								)
						);
			}
			else {
				query.and(
						query.criteria("host").equal(streamInfo.getHost())
						);
			}
			
			long count = query.count();
			if(count > 0) {
				logger.error("{} port duplications are detected for host: {}, video port: {}, audio port:{}",
						count, streamInfo.getHost(), streamInfo.getVideoPort(), streamInfo.getAudioPort());

				WriteResult res = datastore.delete(query);
				if(res.getN() != count) {
					logger.error("Only {} stream info were deleted out of {} having duplicated port.", res.getN(), count);
				}
			}
			datastore.save(streamInfo);
		}
	}

	@Override
	public void addStreamInfoList(List streamInfoList) {
		synchronized(this) {
			for (StreamInfo streamInfo : streamInfoList) {
				datastore.save(streamInfo);
			}
		}
	}

	public List getStreamInfoList(String streamId) {
		synchronized(this) {
			return datastore.find(StreamInfo.class).field("streamId").equal(streamId).asList();
		}
	}

	public void clearStreamInfoList(String streamId) {
		synchronized(this) {
			Query query = datastore.createQuery(StreamInfo.class).field("streamId").equal(streamId);
			long count = query.count();
			WriteResult res = datastore.delete(query);

			if(res.getN() != count) {
				logger.error("{} StreamInfo were deleted out of {} for stream {}",res.getN(), count, streamId);
			}
		}
	}

	@Override
	public boolean saveToken(Token token) {
		boolean result = false;
		synchronized(this) {
			if(token.getStreamId() != null && token.getTokenId() != null) {

				try {
					tokenDatastore.save(token);
					result = true;

				} catch (Exception e) {
					logger.error(ExceptionUtils.getStackTrace(e));
				}
			}
		}

		return result;
	}

	@Override
	public Token validateToken(Token token) {
		Token fetchedToken = null;
		synchronized(this) {
			if (token.getTokenId() != null) {
				fetchedToken = tokenDatastore.find(Token.class).field("tokenId").equal(token.getTokenId()).get();
				if (fetchedToken != null 
						&& fetchedToken.getType().equals(token.getType())
						&& Instant.now().getEpochSecond() < fetchedToken.getExpireDate()) {
					if(token.getRoomId() == null || token.getRoomId().isEmpty()) {

						if(fetchedToken.getStreamId().equals(token.getStreamId())) {	
							Query query = tokenDatastore.createQuery(Token.class).field("tokenId").equal(token.getTokenId());
							tokenDatastore.delete(query);
						}
						else {
							fetchedToken = null;
						}

					}
					return fetchedToken;

				}else {
					fetchedToken = null;
				}
			}
		}
		return fetchedToken;
	}

	@Override
	public boolean revokeTokens(String streamId) {
		synchronized(this) {
			Query query = tokenDatastore.createQuery(Token.class).field("streamId").equal(streamId);
			WriteResult delete = tokenDatastore.delete(query);

			return delete.getN() >= 1;
		}
	}

	@Override
	public List listAllTokens(String streamId, int offset, int size) {
		synchronized(this) {
			return 	tokenDatastore.find(Token.class).field("streamId").equal(streamId).asList(new FindOptions() .skip(offset).limit(size));
		}
	}

	@Override
	public boolean setMp4Muxing(String streamId, int enabled) {
		synchronized(this) {
			try {
				if (streamId != null && (enabled == MuxAdaptor.MP4_ENABLED_FOR_STREAM || enabled == MuxAdaptor.MP4_NO_SET_FOR_STREAM || enabled == MuxAdaptor.MP4_DISABLED_FOR_STREAM)) {
					Query query = datastore.createQuery(Broadcast.class).field("streamId").equal(streamId);
					UpdateOperations ops = datastore.createUpdateOperations(Broadcast.class).set("mp4Enabled", enabled);
					UpdateResults update = datastore.update(query, ops);
					return update.getUpdatedCount() == 1;
				}
			} catch (Exception e) {
				logger.error(e.getMessage());
			}
		}
		return false;

	}

	@Override
	public void clearStreamsOnThisServer(String hostAddress) {
		synchronized(this) {
			Query query = datastore.createQuery(Broadcast.class);
			query.and(
					query.or(
							query.criteria(ORIGIN_ADDRESS).doesNotExist(), //check for non cluster mode
							query.criteria(ORIGIN_ADDRESS).equal(hostAddress)
							),
					query.criteria("zombi").equal(true)
					);
			long count = query.count();
			
			if(count > 0) {
				logger.error("There are {} streams for {} at start. They are deleted now.", count, hostAddress);

				WriteResult res = datastore.delete(query);
				if(res.getN() != count) {
					logger.error("Only {} streams were deleted ou of {} streams.", res.getN(), count);
				}
			}

			Query querySI = datastore.createQuery(StreamInfo.class).field("host").equal(hostAddress);
			count = querySI.count();
			if(count > 0) {
				logger.error("There are {} stream info adressing {} at start. They are deleted now.", count, hostAddress);
				WriteResult res = datastore.delete(querySI);
				if(res.getN() != count) {
					logger.error("Only {} stream info were deleted out of {} streams.", res.getN(), count);
				}
			}
		}
	}

	@Override
	public boolean createConferenceRoom(ConferenceRoom room) {
		boolean result = false;
		synchronized(this) {
			if(room != null && room.getRoomId() != null) {

				try {
					conferenceRoomDatastore.save(room);
					result = true;

				} catch (Exception e) {
					logger.error(ExceptionUtils.getStackTrace(e));
				}
			}
		}
		return result;
	}

	@Override
	public boolean editConferenceRoom(String roomId, ConferenceRoom room) {
		boolean result = false;
		synchronized(this) {
			try {
				Query query = conferenceRoomDatastore.createQuery(ConferenceRoom.class).field("roomId").equal(room.getRoomId());

				UpdateOperations ops = conferenceRoomDatastore.createUpdateOperations(ConferenceRoom.class).set("roomId", room.getRoomId())
						.set("startDate", room.getStartDate()).set("endDate", room.getEndDate());

				UpdateResults update = conferenceRoomDatastore.update(query, ops);
				return update.getUpdatedCount() == 1;
			} catch (Exception e) {
				logger.error(e.getMessage());
			}
		}
		return result;
	}

	@Override
	public boolean deleteConferenceRoom(String roomId) {
		synchronized(this) {
			try {
				Query query = conferenceRoomDatastore.createQuery(ConferenceRoom.class).field("roomId").equal(roomId);
				WriteResult delete = conferenceRoomDatastore.delete(query);
				return delete.getN() == 1;
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return false;
	}

	@Override
	public ConferenceRoom getConferenceRoom(String roomId) {
		synchronized(this) {
			try {
				return conferenceRoomDatastore.find(ConferenceRoom.class).field("roomId").equal(roomId).get();
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return null;
	}

	@Override
	public boolean deleteToken(String tokenId) {
		boolean result = false;
		synchronized(this) {
			try {
				Query query = tokenDatastore.createQuery(Token.class).field("tokenId").equal(tokenId);
				WriteResult delete = tokenDatastore.delete(query);
				result = delete.getN() == 1;
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return result;
	}

	@Override
	public Token getToken(String tokenId) {
		Token token = null;

		synchronized(this) {
			try {
				token =  tokenDatastore.find(Token.class).field("tokenId").equal(tokenId).get();
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return token;
	}
	
	@Override
	public long getLocalLiveBroadcastCount(String hostAddress) {
		synchronized(this) {
			Query query = datastore.createQuery(Broadcast.class);
			query.and(
					query.or(
							query.criteria(ORIGIN_ADDRESS).doesNotExist(), //check for non cluster mode
							query.criteria(ORIGIN_ADDRESS).equal(hostAddress)
							),
					query.criteria(STATUS).equal(AntMediaApplicationAdapter.BROADCAST_STATUS_BROADCASTING)
					);
			return query.count();
		}
	}

	@Override
	public boolean createP2PConnection(P2PConnection conn) {
		synchronized(this) {
			try {
				datastore.save(conn);
				return true;
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return false;
	}

	@Override
	public boolean deleteP2PConnection(String streamId) {
		synchronized(this) {
			try {
				Query query = datastore.createQuery(P2PConnection.class).field("streamId").equal(streamId);
				WriteResult delete = datastore.delete(query);
				return (delete.getN() == 1);
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return false;
	}
	
	@Override
	public P2PConnection getP2PConnection(String streamId) {
		synchronized(this) {
			try {
				return datastore.find(P2PConnection.class).field("streamId").equal(streamId).get();
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return null;
	}

	@Override
	public boolean addSubTrack(String mainTrackId, String subTrackId) {
		synchronized(this) {
			try {
				Query query = datastore.createQuery(Broadcast.class).field("streamId").equal(mainTrackId);

				UpdateOperations ops = datastore.createUpdateOperations(Broadcast.class).push("subTrackStreamIds",
						subTrackId);

				UpdateResults update = datastore.update(query, ops);
				return update.getUpdatedCount() == 1;
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return false;
	}
	
	
	@Override
	public boolean createPlaylist(Playlist playlist) {
		synchronized(this) {
			try {
				datastore.save(playlist);
				return true;
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return false;
	}

	@Override
	public Playlist getPlaylist(String playlistId) {
		synchronized(this) {
			try {
				return datastore.find(Playlist.class).field(PLAYLIST_ID).equal(playlistId).get();
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return null;
	}

	@Override
	public boolean deletePlaylist(String playlistId) {
		synchronized(this) {
			try {
				Query query = datastore.createQuery(Playlist.class).field(PLAYLIST_ID).equal(playlistId);
				WriteResult delete = datastore.delete(query);
				return (delete.getN() == 1);
			} catch (Exception e) {
				logger.error(ExceptionUtils.getStackTrace(e));
			}
		}
		return false;
	}

	@Override
	public boolean editPlaylist(String playlistId, Playlist playlist) {
		boolean result = false;
		synchronized(this) {
			try {
				Query query = datastore.createQuery(Playlist.class).field(PLAYLIST_ID).equal(playlist.getPlaylistId());

				UpdateOperations ops = datastore.createUpdateOperations(Playlist.class).set(PLAYLIST_ID, playlist.getPlaylistId())
						.set("playlistName", playlist.getPlaylistName()).set("playlistStatus", playlist.getPlaylistStatus())
						.set(CREATION_DATE, playlist.getCreationDate()).set(DURATION, playlist.getDuration())
						.set("broadcastItemList", playlist.getBroadcastItemList());

				UpdateResults update = datastore.update(query, ops);
				return update.getUpdatedCount() == 1;
			} catch (Exception e) {
				logger.error(e.getMessage());
			}
		}
		return result;
	}
	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy