<commit_before>/*jslint es5: true */

/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2016 BMW Car IT GmbH
 * %%
 * Licensed 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.
 * #L%
 */

define("joynr/dispatching/subscription/SubscriptionManager", [
    "global/Promise",
    "joynr/messaging/MessagingQos",
    "joynr/start/settings/defaultMessagingSettings",
    "joynr/proxy/SubscriptionQos",
    "joynr/dispatching/types/SubscriptionStop",
    "joynr/dispatching/types/SubscriptionRequest",
    "joynr/dispatching/types/BroadcastSubscriptionRequest",
    "joynr/dispatching/subscription/SubscriptionListener",
    "joynr/util/LongTimer",
    "joynr/system/LoggerFactory",
    "uuid",
    "joynr/util/UtilInternal",
    "joynr/util/Typing",
    "joynr/types/TypeRegistrySingleton",
    "joynr/exceptions/PublicationMissedException",
    "joynr/util/JSONSerializer"
], function(
        Promise,
        MessagingQos,
        defaultMessagingSettings,
        SubscriptionQos,
        SubscriptionStop,
        SubscriptionRequest,
        BroadcastSubscriptionRequest,
        SubscriptionListener,
        LongTimer,
        LoggerFactory,
        uuid,
        Util,
        Typing,
        TypeRegistrySingleton,
        PublicationMissedException,
        JSONSerializer) {
    /**
     * @name SubscriptionManager
     * @constructor
     * @param {Dispatcher}
     *            dispatcher
     */
    function SubscriptionManager(dispatcher) {
        var log = LoggerFactory.getLogger("joynr.dispatching.subscription.SubscriptionManager");
        var typeRegistry = TypeRegistrySingleton.getInstance();
        if (!(this instanceof SubscriptionManager)) {
            // in case someone calls constructor without new keyword (e.g. var c =
            // Constructor({..}))
            return new SubscriptionManager(dispatcher);
        }

        // stores subscriptionId - SubscriptionInfo pairs
        var subscriptionInfos = {};
        // stores subscriptionId - SubscriptionListener
        var subscriptionListeners = {};
        var subscriptionResolvedMap = {};
        // stores the object which is returned by setTimeout mapped to the subscriptionId
        var publicationCheckTimerIds = {};

        /**
         * @param {String}
         *            subscriptionId Id of the subscription to check
         * @returns {Number} time of last received publication
         */
        function getLastPublicationTime(subscriptionId) {
            return subscriptionInfos[subscriptionId].lastPublicationTime_ms;
        }

        function setLastPublicationTime(subscriptionId, time_ms) {
            subscriptionInfos[subscriptionId].lastPublicationTime_ms = time_ms;
        }

        /**
         * @param {String}
         *            subscriptionId Id of the subscription to check
         * @param {Number}
         *            delay_ms Delay to the next publication check.
         * @returns {Boolean} true if subscription is expired, false if end date is not reached.
         */
        function subscriptionEnds(subscriptionId, delay_ms) {
            if (subscriptionInfos[subscriptionId] === undefined) {
                log.warn("subscriptionEnds has been called with unresolved subscriptionId \""
                    + subscriptionId
                    + "\"");
                return true;
            }
            var expiryDateMs = subscriptionInfos[subscriptionId].qos.expiryDateMs;
            // log.debug("Checking subscription end for subscriptionId: " + subscriptionId + "
            // expiryDateMs: " + expiryDateMs + "
            // current time: " + Date.now());
            var ends = expiryDateMs <= Date.now() + delay_ms;
            // if (ends === true) {
            // log.info("Subscription end date reached for id: " + subscriptionId);
            // }
            return ends;
        }

        /**
         * @param {String}
         *            subscriptionId Id of the subscription to check
         * @param {Number}
         *            alertAfterIntervalMs maximum delay between two incoming publications
         */
        function checkPublication(subscriptionId, alertAfterIntervalMs) {
            var subscriptionListener = subscriptionListeners[subscriptionId];
            var timeSinceLastPublication = Date.now() - getLastPublicationTime(subscriptionId);
            // log.debug("timeSinceLastPublication : " + timeSinceLastPublication + "
            // alertAfterIntervalMs: " + alertAfterIntervalMs);
            if (alertAfterIntervalMs > 0 && timeSinceLastPublication >= alertAfterIntervalMs) {
                // log.warn("publication missed for subscription id: " + subscriptionId);
                if (subscriptionListener.onError) {
                    var publicationMissedException = new PublicationMissedException({
                        detailMessage : "alertAfterIntervalMs period exceeded without receiving publication",
                        subscriptionId : subscriptionId
                    });
                    subscriptionListener.onError(publicationMissedException);
                }
            }

            var delay_ms;
            if (timeSinceLastPublication > alertAfterIntervalMs) {
                delay_ms = alertAfterIntervalMs;
            } else {
                delay_ms = alertAfterIntervalMs - timeSinceLastPublication;
            }
            if (!subscriptionEnds(subscriptionId, delay_ms)) {

                // log.debug("Rescheduling checkPublication with delay: " + delay_ms);
                publicationCheckTimerIds[subscriptionId] =
                        LongTimer.setTimeout(function checkPublicationDelay() {
                            checkPublication(subscriptionId, alertAfterIntervalMs);
                        }, delay_ms);
            }
        }

        function calculateTtl(messagingQos, subscriptionQos) {
            var ttl;
            if (subscriptionQos.expiryDateMs === SubscriptionQos.NO_EXPIRY_DATE) {
                ttl = defaultMessagingSettings.MAX_MESSAGING_TTL_MS;
            } else {
                ttl = subscriptionQos.expiryDateMs - Date.now();
            }

            return ttl;
        }

        function storeSubscriptionRequest(parameters, subscriptionRequest) {
            var subscriptionInfo = Util.extend({<commit_msg>[JS] Fix usage of default MAX_MESSAGING_TTL_MS in SubscriptionManager<commit_after>/*jslint es5: true */

/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2016 BMW Car IT GmbH
 * %%
 * Licensed 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.
 * #L%
 */

define("joynr/dispatching/subscription/SubscriptionManager", [
    "global/Promise",
    "joynr/messaging/MessagingQos",
    "joynr/start/settings/defaultMessagingSettings",
    "joynr/proxy/SubscriptionQos",
    "joynr/dispatching/types/SubscriptionStop",
    "joynr/dispatching/types/SubscriptionRequest",
    "joynr/dispatching/types/BroadcastSubscriptionRequest",
    "joynr/dispatching/subscription/SubscriptionListener",
    "joynr/util/LongTimer",
    "joynr/system/LoggerFactory",
    "uuid",
    "joynr/util/UtilInternal",
    "joynr/util/Typing",
    "joynr/types/TypeRegistrySingleton",
    "joynr/exceptions/PublicationMissedException",
    "joynr/util/JSONSerializer"
], function(
        Promise,
        MessagingQos,
        defaultMessagingSettings,
        SubscriptionQos,
        SubscriptionStop,
        SubscriptionRequest,
        BroadcastSubscriptionRequest,
        SubscriptionListener,
        LongTimer,
        LoggerFactory,
        uuid,
        Util,
        Typing,
        TypeRegistrySingleton,
        PublicationMissedException,
        JSONSerializer) {
    /**
     * @name SubscriptionManager
     * @constructor
     * @param {Dispatcher}
     *            dispatcher
     */
    function SubscriptionManager(dispatcher) {
        var log = LoggerFactory.getLogger("joynr.dispatching.subscription.SubscriptionManager");
        var typeRegistry = TypeRegistrySingleton.getInstance();
        if (!(this instanceof SubscriptionManager)) {
            // in case someone calls constructor without new keyword (e.g. var c =
            // Constructor({..}))
            return new SubscriptionManager(dispatcher);
        }

        // stores subscriptionId - SubscriptionInfo pairs
        var subscriptionInfos = {};
        // stores subscriptionId - SubscriptionListener
        var subscriptionListeners = {};
        var subscriptionResolvedMap = {};
        // stores the object which is returned by setTimeout mapped to the subscriptionId
        var publicationCheckTimerIds = {};

        /**
         * @param {String}
         *            subscriptionId Id of the subscription to check
         * @returns {Number} time of last received publication
         */
        function getLastPublicationTime(subscriptionId) {
            return subscriptionInfos[subscriptionId].lastPublicationTime_ms;
        }

        function setLastPublicationTime(subscriptionId, time_ms) {
            subscriptionInfos[subscriptionId].lastPublicationTime_ms = time_ms;
        }

        /**
         * @param {String}
         *            subscriptionId Id of the subscription to check
         * @param {Number}
         *            delay_ms Delay to the next publication check.
         * @returns {Boolean} true if subscription is expired, false if end date is not reached.
         */
        function subscriptionEnds(subscriptionId, delay_ms) {
            if (subscriptionInfos[subscriptionId] === undefined) {
                log.warn("subscriptionEnds has been called with unresolved subscriptionId \""
                    + subscriptionId
                    + "\"");
                return true;
            }
            var expiryDateMs = subscriptionInfos[subscriptionId].qos.expiryDateMs;
            // log.debug("Checking subscription end for subscriptionId: " + subscriptionId + "
            // expiryDateMs: " + expiryDateMs + "
            // current time: " + Date.now());
            var ends = expiryDateMs <= Date.now() + delay_ms;
            // if (ends === true) {
            // log.info("Subscription end date reached for id: " + subscriptionId);
            // }
            return ends;
        }

        /**
         * @param {String}
         *            subscriptionId Id of the subscription to check
         * @param {Number}
         *            alertAfterIntervalMs maximum delay between two incoming publications
         */
        function checkPublication(subscriptionId, alertAfterIntervalMs) {
            var subscriptionListener = subscriptionListeners[subscriptionId];
            var timeSinceLastPublication = Date.now() - getLastPublicationTime(subscriptionId);
            // log.debug("timeSinceLastPublication : " + timeSinceLastPublication + "
            // alertAfterIntervalMs: " + alertAfterIntervalMs);
            if (alertAfterIntervalMs > 0 && timeSinceLastPublication >= alertAfterIntervalMs) {
                // log.warn("publication missed for subscription id: " + subscriptionId);
                if (subscriptionListener.onError) {
                    var publicationMissedException = new PublicationMissedException({
                        detailMessage : "alertAfterIntervalMs period exceeded without receiving publication",
                        subscriptionId : subscriptionId
                    });
                    subscriptionListener.onError(publicationMissedException);
                }
            }

            var delay_ms;
            if (timeSinceLastPublication > alertAfterIntervalMs) {
                delay_ms = alertAfterIntervalMs;
            } else {
                delay_ms = alertAfterIntervalMs - timeSinceLastPublication;
            }
            if (!subscriptionEnds(subscriptionId, delay_ms)) {

                // log.debug("Rescheduling checkPublication with delay: " + delay_ms);
                publicationCheckTimerIds[subscriptionId] =
                        LongTimer.setTimeout(function checkPublicationDelay() {
                            checkPublication(subscriptionId, alertAfterIntervalMs);
                        }, delay_ms);
            }
        }

        function calculateTtl(messagingQos, subscriptionQos) {
            var ttl;
            if (subscriptionQos.expiryDateMs === SubscriptionQos.NO_EXPIRY_DATE) {
                return defaultMessagingSettings.MAX_MESSAGING_TTL_MS;
            }
            ttl = SubscriptionQos.expiryDateMs - Date.now();
            if (ttl > defaultMessagingSettings.MAX_MESSAGING_TTL_MS) {
                return defaultMessagingSettings.MAX_MESSAGING_TTL_MS;
            }
            return ttl;
        }

        function storeSubscriptionRequest(parameters, subscriptionRequest) {
            var subscriptionInfo = Util.extend({
{'fraction_non_alphanumeric': 0.08312798956370489, 'fraction_numerical': 0.0020292796057399622, 'mean_word_length': 2.165634319798119, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4674350', 'n_tokens_mistral': 3394, 'n_tokens_neox': 3341, 'n_words': 800}