Esempio n. 1
0
        /// <summary>
        /// Sends the message notification schema using the Ignite compute/invoke pattern as a reliable delivery mechanism
        /// </summary>
        private void SendInvokeStyleMessage(string gridName, ISiteModelAttributesChangedEvent evt)
        {
            var gridFactory = DIContext.Obtain <ITRexGridFactory>();

            var compute = gridFactory.Grid(StorageMutability.Immutable)?.GetCluster()?.ForAttribute(_messageRoleAttributeName, "True")?.GetCompute();

            if (compute != null)
            {
                var responses = compute.Broadcast(_messageSendComputeFunc, evt);

                if (responses == null || responses.Count == 0)
                {
                    _log.LogWarning($"Site model change notification responses collection from {gridName} is null or empty");
                }
                else
                {
                    _log.LogInformation($"Received notification confirmation for {responses.Count} recipients in the {gridName} grid.");
                    if (responses.Any(x => !x.Success))
                    {
                        _log.LogWarning($"Not all targeted nodes in {gridName} successfully processed message, Failures = {string.Join(',', responses.Where(x => !x.Success).Select(x => x.NodeUid))}");
                    }
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Handles the situation when TAG file processing or some other activity has modified the attributes of a site model
        /// requiring the site model to be reloaded
        /// </summary>
        public void SiteModelAttributesHaveChanged(ISiteModelAttributesChangedEvent message)
        {
            var messageAge = DateTime.UtcNow - message.TimeSentUtc;

            _log.LogInformation($"Entering attribute change notification processor for project {message.SiteModelID}, change event ID {message.ChangeEventUid}, event message age {messageAge}");

            if (messageAge.TotalSeconds > 1.0)
            {
                _log.LogWarning($"Message age more than 1 second [{messageAge}]");
            }

            // Site models have immutable characteristics in TRex. Multiple requests may reference the same site model
            // concurrently, with no interlocks enforcing access serialization. Any attempt to replace or modify an already loaded
            // site model may cause issue with concurrent request accessing that site model.
            // THe strategy here is to preserve continued access by concurrent requests to the site model retrieved
            // at the time the request was initiated by removing it from the SiteModels cache but not destroying it.
            // Once all request based references to the site model have completed the now orphaned site model will be cleaned
            // up by the garbage collector. Removal of the site model is interlocked with getting a site model reference
            // to ensure no concurrency issues within the underlying cache implementation
            // Note: The site model references some elements that may be preserved via the site model factory method that
            // accepts an origin site model.
            // These elements are:
            // 1. ExistenceMap
            // 2. Sub grid tree containing cached sub grid data
            // 3. Coordinate system
            // 4. Designs
            // 5. Surveyed Surfaces
            // 6. Machines
            // 7. Machines target values
            // 8. Machines design names
            // 9. Proofing runs
            // 10. Alignments
            // 11. Site model marked for deletion

            ISiteModel siteModel;

            // Construct a new site model that preserves elements not affected by the notification and replace the existing
            // site model reference with it.
            lock (_cachedModels)
            {
                _cachedModels.TryGetValue(message.SiteModelID, out siteModel);

                if (siteModel != null && message.SiteModelMarkedForDeletion)
                {
                    // Remove the site model from the cache and exit.
                    _cachedModels.Remove(message.SiteModelID);
                    return;
                }

                // Note: The spatial data grid is highly conserved and never killed in a site model change notification.
                var originFlags =
                    SiteModelOriginConstructionFlags.PreserveGrid
                    | (!message.ExistenceMapModified ? SiteModelOriginConstructionFlags.PreserveExistenceMap : 0)
                    | (!message.CsibModified ? SiteModelOriginConstructionFlags.PreserveCsib : 0)
                    | (!message.DesignsModified ? SiteModelOriginConstructionFlags.PreserveDesigns : 0)
                    | (!message.SurveyedSurfacesModified ? SiteModelOriginConstructionFlags.PreserveSurveyedSurfaces : 0)
                    | (!message.MachinesModified ? SiteModelOriginConstructionFlags.PreserveMachines : 0)
                    | (!message.MachineTargetValuesModified ? SiteModelOriginConstructionFlags.PreserveMachineTargetValues : 0)
                    | (!message.MachineDesignsModified ? SiteModelOriginConstructionFlags.PreserveMachineDesigns | SiteModelOriginConstructionFlags.PreserveSiteModelDesigns : 0)
                    | (!message.ProofingRunsModified ? SiteModelOriginConstructionFlags.PreserveProofingRuns : 0)
                    | (!message.AlignmentsModified ? SiteModelOriginConstructionFlags.PreserveAlignments : 0)
                ;

                _log.LogInformation($"Processing attribute change notification for site model {message.SiteModelID}. Preserved elements are {originFlags}");

                if (siteModel != null)
                {
                    // First create a new site model to replace the site model with, requesting certain elements of the existing site model
                    // to be preserved in the new site model instance.
                    siteModel = DIContext.Obtain <ISiteModelFactory>().NewSiteModel(siteModel, originFlags);

                    // Replace the site model reference in the cache with the new site model
                    _cachedModels[message.SiteModelID] = siteModel;
                }
            }

            // If the notification contains an existence map change mask then all cached sub grid based elements that match the masked sub grids
            // need to be evicted from all cached contexts related to this site model. Note: This operation is not performed under a lock as the
            // removal operations on the cache are lock free
            if (message.ExistenceMapChangeMask != null)
            {
                // Create and deserialize the sub grid but mask from the message
                var mask = new SubGridTreeSubGridExistenceBitMask();
                mask.FromBytes(message.ExistenceMapChangeMask);

                if (siteModel != null)
                {
                    // Iterate over all leaf sub grids in the mask. For each get the matching node sub grid in siteModel.Grid,
                    // and remove all sub grid references from that node sub grid matching the bits in the bit mask sub grid
                    mask.ScanAllSubGrids(leaf =>
                    {
                        // Obtain the matching node sub grid in Grid
                        var node = siteModel.Grid.LocateClosestSubGridContaining
                                       (leaf.OriginX << SubGridTreeConsts.SubGridIndexBitsPerLevel,
                                       leaf.OriginY << SubGridTreeConsts.SubGridIndexBitsPerLevel,
                                       leaf.Level);

                        // If there are sub grids present in Grid that match the sub grids identified by leaf
                        // remove the elements identified in leaf from the node sub grid.
                        if (node != null)
                        {
                            ((ISubGridTreeLeafBitmapSubGrid)leaf).ForEachSetBit((x, y) => node.SetSubGrid(x, y, null));
                        }

                        return(true); // Keep processing leaf sub grids
                    });
                }

                // Advise the spatial memory general sub grid result cache of the change so it can invalidate cached derivatives
                DIContext.ObtainOptional <ITRexSpatialMemoryCache>()?.InvalidateDueToProductionDataIngest(message.SiteModelID, message.ChangeEventUid, mask);

                // Advise any registered site model change map notifier of the changes
                DIContext.ObtainOptional <ISiteModelChangeMapDeltaNotifier>()?.Notify(message.SiteModelID, DateTime.UtcNow, mask, SiteModelChangeMapOrigin.Ingest, SiteModelChangeMapOperation.AddSpatialChanges);
            }
        }