Пример #1
0
        //--- Methods ---
        internal void Add(string[] path, int level, DreamFeature feature)
        {
            // check if we reached the last part of the feature path
            if (level == path.Length)
            {
                // add feature to signature map
                SignatureMap.Add(feature);
            }
            else
            {
                string key = path[level];
                DreamFeatureDirectory entry = null;

                // check if sub-feature already exists
                if (Subfeatures.TryGetValue(key, out entry))
                {
                    entry.Add(path, level + 1, feature);
                }
                else
                {
                    DreamFeatureDirectory tree = new DreamFeatureDirectory();
                    tree.Add(path, level + 1, feature);
                    Subfeatures.Add(key, tree);
                }
            }
        }
Пример #2
0
        internal void Add(string[] path, int level, DreamFeatureDirectory features)
        {
            // check if we reached the last part of the feature path
            if(level == path.Length) {
                throw new ArgumentException(string.Format("feature path is already in use ({0})", string.Join("/", path)));
            } else {
                string key = path[level];
                DreamFeatureDirectory entry = null;
                Subfeatures.TryGetValue(key, out entry);

                // check if added feature directory is a leaf node
                if(level == (path.Length - 1)) {

                    // check if there was an existing sub-feature
                    if(entry != null) {
                        features.CopyAndMergeFrom(entry);
                        Subfeatures[key] = features;
                    } else {
                        Subfeatures.Add(key, features);
                    }
                } else {

                    // check if a sub-feature needs to be created
                    if(entry == null) {
                        entry = new DreamFeatureDirectory();
                        Subfeatures.Add(key, entry);
                    }
                    entry.Add(path, level + 1, features);
                }
            }
        }
Пример #3
0
 internal void CopyAndMergeFrom(DreamFeatureDirectory features)
 {
     SignatureMap.AddRange(features.SignatureMap);
     foreach (KeyValuePair <string, DreamFeatureDirectory> pair in features.Subfeatures)
     {
         DreamFeatureDirectory entry;
         if (Subfeatures.TryGetValue(pair.Key, out entry))
         {
             entry.CopyAndMergeFrom(pair.Value);
         }
         else
         {
             Subfeatures.Add(pair.Key, pair.Value);
         }
     }
 }
Пример #4
0
        //--- Methods ---
        internal void Add(string[] path, int level, DreamFeature feature)
        {
            // check if we reached the last part of the feature path
            if(level == path.Length) {

                // add feature to signature map
                SignatureMap.Add(feature);
            } else {
                string key = path[level];
                DreamFeatureDirectory entry = null;

                // check if sub-feature already exists
                if(Subfeatures.TryGetValue(key, out entry)) {
                    entry.Add(path, level + 1, feature);
                } else {
                    DreamFeatureDirectory tree = new DreamFeatureDirectory();
                    tree.Add(path, level + 1, feature);
                    Subfeatures.Add(key, tree);
                }
            }
        }
Пример #5
0
        internal void Add(string[] path, int level, DreamFeatureDirectory features)
        {
            // check if we reached the last part of the feature path
            if (level == path.Length)
            {
                throw new ArgumentException(string.Format("feature path is already in use ({0})", string.Join("/", path)));
            }
            else
            {
                string key = path[level];
                DreamFeatureDirectory entry = null;
                Subfeatures.TryGetValue(key, out entry);

                // check if added feature directory is a leaf node
                if (level == (path.Length - 1))
                {
                    // check if there was an existing sub-feature
                    if (entry != null)
                    {
                        features.CopyAndMergeFrom(entry);
                        Subfeatures[key] = features;
                    }
                    else
                    {
                        Subfeatures.Add(key, features);
                    }
                }
                else
                {
                    // check if a sub-feature needs to be created
                    if (entry == null)
                    {
                        entry = new DreamFeatureDirectory();
                        Subfeatures.Add(key, entry);
                    }
                    entry.Add(path, level + 1, features);
                }
            }
        }
Пример #6
0
        protected override Yield Stop(Result result)
        {
            if(!IsRunning) {
                result.Return();
                yield break;
            }
            try {

                // BUG #810: announce to all root-level services that we're shutting down

                // dismiss all pending requests
                _requestQueue = null;

                // shutdown all services, except host and sub-services (the latter should be cleaned-up by their owners)
                _log.Debug("Stopping stand-alone services");
                Dictionary<string, ServiceEntry> services;
                lock(_services) {
                    services = new Dictionary<string, ServiceEntry>(_services);
                }
                foreach(KeyValuePair<string, ServiceEntry> entry in services) {
                    if((entry.Value.Owner == null) && !(ReferenceEquals(this, entry.Value.Service))) {
                        StopService(entry.Value.Service.Self);
                    }
                }

                // now destroy support services
                _log.Debug("Stopping host");
            } catch(Exception ex) {
                _log.ErrorExceptionMethodCall(ex, "Stop: host failed to deinitialize");
            }

            // stop storage service
            if(_storage != null) {
                yield return _storage.Delete(new Result<DreamMessage>(TimeSpan.MaxValue)).CatchAndLog(_log);
                _storage = null;
            }

            // check if any inner services failed to stop
            foreach(KeyValuePair<string, ServiceEntry> entry in _services) {
                _log.WarnMethodCall("Stop: service did not shutdown", entry.Key);
            }

            // invoke base.Stop
            yield return Coroutine.Invoke(base.Stop, new Result()).CatchAndLog(_log);

            // deinitialize fields
            _blueprints = null;
            _registeredTypes.Clear();
            _infos.Clear();
            _activities.Clear();
            _features = new DreamFeatureDirectory();
            _services.Clear();
            _aliases.Clear();

            // mark host as not running
            Plug.RemoveEndpoint(this);
            _running = false;
            _shutdown.Set();
            result.Return();
        }
Пример #7
0
        private DreamFeatureDirectory CreateServiceFeatureDirectory(IDreamService service, XDoc blueprint, XDoc config)
        {
            Type type = service.GetType();
            string path = config["path"].Contents.ToLowerInvariant();

            // add transport information
            XUri serviceUri = LocalMachineUri.AtAbsolutePath(path);
            config.Root.Elem("uri.self", serviceUri.ToString());

            // compile list of active service features, combined by suffix
            int serviceUriSegmentsLength = serviceUri.Segments.Length;
            DreamFeatureDirectory directory = new DreamFeatureDirectory();
            var methodInfos = GetMethodInfos(type);
            foreach(XDoc featureBlueprint in blueprint["features/feature"]) {
                string methodName = featureBlueprint["method"].Contents;
                string pattern = featureBlueprint["pattern"].AsText;

                // TODO (steveb): we should be a little more discerning here as this might trigger false positives
                bool atConfig = pattern.ContainsInvariantIgnoreCase("@config");

                // locate method
                var methods = methodInfos[methodName];
                if(methods.Count() > 1) {
                    var found = string.Join(", ", methods.Select(m => m.DeclaringType.FullName + "!" + m.Name + "(" + string.Join(", ", m.GetParameters().Select(p => p.ParameterType.Name + " " + p.Name).ToArray()) + ")").ToArray());
                    throw new MissingMethodException(string.Format("found multiple definitions for {0}: {1}", methodName, found));
                }
                if(methods.None()) {
                    throw new MissingMethodException(string.Format("could not find {0} in class {1}", methodName, type.FullName));
                }
                MethodInfo method = methods.First();

                // determine access level
                DreamAccess access;
                switch(featureBlueprint["access"].AsText) {
                case null:
                case "public":
                    access = DreamAccess.Public;
                    break;
                case "internal":
                    access = DreamAccess.Internal;
                    break;
                case "private":
                    access = DreamAccess.Private;
                    break;
                default:
                    throw new NotSupportedException(string.Format("access level is not supported ({0})", methodName));
                }

                // parse pattern string
                string[] parts = pattern.Split(new[] { ':' }, 2);
                string verb = parts[0].Trim();
                string signature = parts[1].Trim();
                if(signature.Length == 0) {
                    signature = string.Empty;
                }

                // add feature prologues
                List<DreamFeatureStage> stages = new List<DreamFeatureStage>();
                stages.AddRange(_defaultPrologues);
                if(!atConfig) {
                    DreamFeatureStage[] custom = service.Prologues;
                    if(!ArrayUtil.IsNullOrEmpty(custom)) {
                        stages.AddRange(custom);
                    }
                }

                // add feature handler
                int mainStageIndex = stages.Count;
                stages.Add(new DreamFeatureStage(service, method, access));

                // add feature epilogues
                if(!atConfig) {
                    DreamFeatureStage[] custom = service.Epilogues;
                    if(!ArrayUtil.IsNullOrEmpty(custom)) {
                        stages.AddRange(custom);
                    }
                }
                stages.AddRange(_defaultEpilogues);

                // create dream feature and add to service directory
                var paramAttributes = method.GetCustomAttributes(typeof(DreamFeatureParamAttribute), false).Cast<DreamFeatureParamAttribute>().ToArray();
                DreamFeature feature = new DreamFeature(service, serviceUri, mainStageIndex, stages.ToArray(), verb, signature, paramAttributes);
                directory.Add(feature.PathSegments, serviceUriSegmentsLength, feature);
            }
            return directory;
        }
Пример #8
0
 internal void CopyAndMergeFrom(DreamFeatureDirectory features)
 {
     SignatureMap.AddRange(features.SignatureMap);
     foreach(KeyValuePair<string, DreamFeatureDirectory> pair in features.Subfeatures) {
         DreamFeatureDirectory entry;
         if(Subfeatures.TryGetValue(pair.Key, out entry)) {
             entry.CopyAndMergeFrom(pair.Value);
         } else {
             Subfeatures.Add(pair.Key, pair.Value);
         }
     }
 }