protected virtual Yield PutConfig(DreamContext context, DreamMessage request, Result <DreamMessage> response) { XDoc config = request.ToDocument(); if (config.Name != "config") { throw new DreamBadRequestException("bad document type"); } if (IsStarted) { throw new DreamBadRequestException("service must be stopped first"); } _timerFactory = TaskTimerFactory.Create(this); // configure service container var lifetimeScope = _env.CreateServiceLifetimeScope(this, (c, b) => PreInitializeLifetimeScope(c, b, config)); // call container-less start (which contains shared start logic) yield return(Coroutine.Invoke(Start, request.ToDocument(), new Result())); // call start with container for sub-classes that want to resolve instances at service start yield return(Coroutine.Invoke(Start, config, lifetimeScope, new Result())); response.Return(DreamMessage.Ok(new XDoc("service-info") .Start("private-key") .Add(DreamCookie.NewSetCookie("service-key", PrivateAccessKey, Self.Uri).AsSetCookieDocument) .End() .Start("internal-key") .Add(DreamCookie.NewSetCookie("service-key", InternalAccessKey, Self.Uri).AsSetCookieDocument) .End() )); }
//--- Constructors --- internal InMemoryKeyValueCache(ISerializer serializer, int maxSize, TaskTimerFactory timerFactory) { _serializer = serializer; _maxSize = maxSize; _flushTimer = timerFactory.New(TimeSpan.FromSeconds(1), Flush, null, TaskEnv.None); _cache = new ExpiringDictionary <string, Entry>(timerFactory); }
private static void SigTermHandler() { Console.WriteLine("(initializing SIGTERM handler)"); UnixSignal.WaitAny(new[] { new UnixSignal(Signum.SIGTERM) }); TaskTimerFactory.ShutdownAll(); _host.Dispose(); }
//--- Constructors --- public SearchInstanceData(string indexPath, Analyzer analyzer, UpdateDelayQueue queue, TimeSpan commitInterval, TaskTimerFactory taskTimerFactory) { _analyzer = analyzer; _directory = FSDirectory.GetDirectory(indexPath); // Note (arnec): Needed with SimpleFSLock, since a hard shutdown will have left the lock dangling IndexWriter.Unlock(_directory); try { _writer = new IndexWriter(_directory, _analyzer, IndexWriter.MaxFieldLength.UNLIMITED); } catch (CorruptIndexException e) { _log.WarnFormat("The Search index at {0} is corrupt. You must repair or delete it before restarting the service. If you delete it, you must rebuild your index after service restart.", indexPath); if (e.Message.StartsWith("Unknown format version")) { _log.Warn("The index is considered corrupt because it's an unknown version. Did you accidentally downgrade your install?"); } throw; } _reader = IndexReader.Open(_directory); _searcher = new IndexSearcher(_reader); _queue = queue; _commitInterval = commitInterval; _taskTimerFactory = taskTimerFactory; if (_commitInterval != TimeSpan.Zero) { _commitTimer = _taskTimerFactory.New(_commitInterval, Commit, null, TaskEnv.None); } }
//--- Constructors --- /// <summary> /// Constructor for creating an instance. /// </summary> /// <param name="client">ISqsClient instance.</param> /// <param name="queueName">Queue name.</param> /// <param name="timerFactory">TimerFactory instance.</param> public SqsQueueDelayedSendClient(ISqsClient client, SqsQueueName queueName, TaskTimerFactory timerFactory) { if (client == null) { throw new ArgumentNullException("client"); } this.QueueName = queueName; _client = client; _timedSendAccumulator = new TimedAccumulator <KeyValuePair <int, string> >(items => AsyncUtil.ForkBackgroundSender(() => BatchSendMessages(items)), SqsUtils.MAX_NUMBER_OF_BATCH_SEND_MESSAGES, AUTOFLUSH_TIME, timerFactory); }
//--- Constructors --- /// <summary> /// Constructor for creating an instance. /// </summary> /// <param name="client">ISqsClient instance.</param> /// <param name="timerFactory">TimeFactory instance.</param> public SqsDelayedSendClient(ISqsClient client, TaskTimerFactory timerFactory) { if (client == null) { throw new ArgumentNullException("client"); } if (timerFactory == null) { throw new ArgumentNullException("timerFactory"); } _client = client; _timerFactory = timerFactory; }
//--- Constructors --- public LocalInstanceManager(DekiWikiService dekiService, TaskTimerFactory timerFactory) : base(dekiService, timerFactory) { var dekiServiceConfig = dekiService.Config; if (dekiServiceConfig["wikis/config"].IsEmpty) { //Not in cluster mode (no other wikis defined): run all hosts under default wiki. AssociateHostnameWithWiki("*", DEFAULT_WIKI_ID); } else { foreach (XDoc wikiDoc in dekiServiceConfig["wikis/config"]) { var wikiId = wikiDoc["@id"].AsText; AssociateHostnameWithWiki(wikiDoc["host"].Select(hostDoc => hostDoc.Contents).ToArray(), wikiId); } } }
//--- Constructors --- public RemoteInstanceManager(DekiWikiService dekiService, TaskTimerFactory timerFactory, XUri directoryUri, string tempPath) : base(dekiService, timerFactory) { // validate temp folder _tempPath = tempPath; if (!Directory.Exists(_tempPath)) { throw new ArgumentException("temp folder does not exist", "tempPath"); } // check remote directory _directory = Plug.New(directoryUri); var testMsg = _directory.GetAsync().Wait(); if (!testMsg.IsSuccessful) { _log.WarnFormat("Error validating remote deki portal service at '{0}'", directoryUri); } }
//--- Constructors --- /// <summary> /// Create new client instance /// </summary> /// <param name="config">Client configuration.</param> /// <param name="timerFactory">Timer factory.</param> public AmazonS3Client(AmazonS3ClientConfig config, TaskTimerFactory timerFactory) { _config = config; _bucketPlug = Plug.New(_config.S3BaseUri) .WithS3Authentication(_config.PrivateKey, _config.PublicKey) .WithTimeout(_config.Timeout) .At(_config.Bucket); _rootPlug = _bucketPlug; if (!string.IsNullOrEmpty(_config.RootPath)) { _keyRootParts = _config.RootPath.Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries); if (_keyRootParts != null && _keyRootParts.Any()) { _rootPlug = _rootPlug.At(_keyRootParts); } } _expirationEntries = new ExpiringHashSet <string>(timerFactory); _expirationEntries.EntryExpired += OnDelete; }
protected virtual Yield PutConfig(DreamContext context, DreamMessage request, Result <DreamMessage> response) { XDoc config = request.ToDocument(); if (config.Name != "config") { throw new DreamBadRequestException("bad document type"); } if (IsStarted) { throw new DreamBadRequestException("service must be stopped first"); } _timerFactory = TaskTimerFactory.Create(this); // configure service container var components = config["components"]; var servicecontainer = _env.CreateServiceContainer(this); var builder = new ContainerBuilder(); builder.Register(_timerFactory).ExternallyOwned(); if (!components.IsEmpty) { _log.Debug("registering service level module"); builder.RegisterModule(new XDocAutofacContainerConfigurator(components, DreamContainerScope.Service)); } builder.Build(servicecontainer); // call container-less start (which contains shared start logic) yield return(Coroutine.Invoke(Start, request.ToDocument(), new Result())); // call start with container for sub-classes that want to resolve instances at service start yield return(Coroutine.Invoke(Start, config, servicecontainer, new Result())); response.Return(DreamMessage.Ok(new XDoc("service-info") .Start("private-key") .Add(DreamCookie.NewSetCookie("service-key", PrivateAccessKey, Self.Uri).AsSetCookieDocument) .End() .Start("internal-key") .Add(DreamCookie.NewSetCookie("service-key", InternalAccessKey, Self.Uri).AsSetCookieDocument) .End() )); }
//--- Constructors --- public S3Storage(XDoc configuration, ILog log) { _timerFactory = TaskTimerFactory.Create(this); _log = log; _publicKey = configuration["publickey"].AsText; _privateKey = configuration["privatekey"].AsText; _bucket = configuration["bucket"].AsText; _prefix = configuration["prefix"].AsText; if (string.IsNullOrEmpty(_publicKey)) { throw new ArgumentException("Invalid Amazon S3 publickey"); } if (string.IsNullOrEmpty(_privateKey)) { throw new ArgumentException("Invalid Amazon S3 privatekey"); } if (string.IsNullOrEmpty(_bucket)) { throw new ArgumentException("Invalid Amazon S3 bucket"); } if (string.IsNullOrEmpty(_prefix)) { throw new ArgumentException("Invalid Amazon S3 prefix"); } _tempDirectory = Path.Combine(Path.GetTempPath(), "s3_cache_" + XUri.EncodeSegment(_prefix)); if (Directory.Exists(_tempDirectory)) { Directory.Delete(_tempDirectory, true); } Directory.CreateDirectory(_tempDirectory); _allowRedirects = configuration["allowredirects"].AsBool ?? false; _redirectTimeout = TimeSpan.FromSeconds(configuration["redirecttimeout"].AsInt ?? 60); _cacheTtl = (configuration["cachetimeout"].AsInt ?? 60 * 60).Seconds(); // initialize S3 plug _s3 = Plug.New("http://s3.amazonaws.com", TimeSpan.FromSeconds(configuration["timeout"].AsDouble ?? DEFAUTL_S3_TIMEOUT)).WithPreHandler(S3AuthenticationHeader).At(_bucket); }
//--- Class methods --- public static InstanceManager New(DekiWikiService dekiService, TaskTimerFactory timerFactory) { InstanceManager mgr; var srcString = dekiService.Config["wikis/@src"].AsText; if (!string.IsNullOrEmpty(srcString)) { XUri remoteDirUri; if (!XUri.TryParse(srcString, out remoteDirUri)) { //TODO: build a specialized exception out of this throw new ApplicationException(string.Format("Configuration is not valid. wikis/@src ({0})is not a valid url!", srcString)); } mgr = new RemoteInstanceManager(dekiService, timerFactory, remoteDirUri, dekiService.TempPath); } else { mgr = new LocalInstanceManager(dekiService, timerFactory); } mgr._maxInstances = dekiService.Config["wikis/@max"].AsInt ?? int.MaxValue; var timeoutSecs = dekiService.Config["wikis/@ttl"].AsDouble; if (timeoutSecs == null || timeoutSecs == 0) { mgr._inactiveInstanceTimeOut = TimeSpan.MaxValue; } else { mgr._inactiveInstanceTimeOut = TimeSpan.FromSeconds(timeoutSecs.Value); } var retryInterval = dekiService.Config["wikis/@retry-interval"].AsDouble ?? 10; mgr._abandonedInstanceRetryInterval = TimeSpan.FromSeconds(retryInterval); mgr._minInstanceIdletime = TimeSpan.FromSeconds(dekiService.Config["wikis/@idletime"].AsDouble ?? 60); return(mgr); }
//--- Constructors --- /// <summary> /// Create a new hashset /// </summary> /// <param name="taskTimerFactory">The timer factory to create the set's timer from</param> public ExpiringDictionary(TaskTimerFactory taskTimerFactory) : this(taskTimerFactory, false) { }
//--- Constructors --- public ExpiringSet(TaskTimerFactory taskTimerFactory, bool autoRefresh) { _taskTimerFactory = taskTimerFactory; _autoRefresh = autoRefresh; _expireTimer = _taskTimerFactory.New(DateTime.MaxValue, OnExpire, null, TaskEnv.None); }
//--- Class Methods --- private static int Main(string[] args) { bool useTty = true; TimeSpan time; // process command line arguments XDoc config = new XDoc("config"); for (int i = 0; i < args.Length; i += 2) { string key = args[i].ToLowerInvariant(); string value = ((i + 1) < args.Length) ? args[i + 1] : string.Empty; switch (key) { case "help": PrintUsage(); return(0); case "notty": --i; useTty = false; break; case "capture-stack-trace": --i; DebugUtil.CaptureStackTrace = true; break; case "nolog": --i; // NOTE (steveb): this option used to disable logging, but was removed in favor of using the automatic re-reading of app.config by log4net break; case "settings": case "config": if (!File.Exists(value)) { WriteError(key, "config file not found"); return(1); } config = XDocFactory.LoadFrom(value, MimeType.XML); break; case "script": config.Start("script").Attr("src", value).End(); break; case "ip": case "host": config.Elem("host", value); break; case "http-port": case "path-prefix": case "server-path": case "server-name": case "storage-dir": case "connect-limit": case "apikey": case "guid": config.Elem(key, value); break; case "public-uri": case "root-uri": config.Elem("uri.public", value); break; case "service-dir": config.Elem("storage-dir", value); break; case "collect-interval": int interval; if (!int.TryParse(value, out interval)) { WriteError(key, "invalid collection interval (must be an integer representing seconds)"); return(1); } if (interval > 0) { DebugUtil.SetCollectionInterval(TimeSpan.FromSeconds(interval)); } break; case "auth": config.Elem("authentication-shemes", value); break; default: WriteError(key, "unknown setting"); return(1); } } try { // initialize environment if (config["apikey"].IsEmpty) { string apikey = StringUtil.CreateAlphaNumericKey(32); config.Elem("apikey", apikey); Console.WriteLine("Dream Host APIKEY: {0}", apikey); } Console.WriteLine("-------------------- initializing"); time = DebugUtil.Stopwatch(() => { _host = new DreamHost(config); }); Console.WriteLine("-------------------- initialized {0} secs", time.TotalSeconds); // execute scripts time = DebugUtil.Stopwatch(() => { _host.RunScripts(config, null); }); Console.WriteLine("-------------------- ready {0} secs", time.TotalSeconds); // for UNIX systems, let's also listen to SIGTERM if (SysUtil.IsUnix) { new Thread(SigTermHandler) { IsBackground = true }.Start(); } // check if we can use the console if (useTty) { int debuglevel = 0; // wait for user input then exit while (_host.IsRunning) { Thread.Sleep(250); #region Interactive Key Handler if (Console.KeyAvailable) { ConsoleKeyInfo key = Console.ReadKey(true); switch (key.Key) { case ConsoleKey.Q: case ConsoleKey.Escape: case ConsoleKey.Spacebar: Console.WriteLine("Shutting down"); return(0); case ConsoleKey.G: Console.WriteLine("Full garbage collection pass"); System.GC.Collect(); break; case ConsoleKey.C: Console.Clear(); break; case ConsoleKey.D: switch (++debuglevel) { default: debuglevel = 0; Threading.RendezVousEvent.CaptureTaskState = false; DebugUtil.CaptureStackTrace = false; Console.WriteLine("Debug capture: none"); break; case 1: Threading.RendezVousEvent.CaptureTaskState = true; DebugUtil.CaptureStackTrace = false; Console.WriteLine("Debug capture: task-state only"); break; case 2: Threading.RendezVousEvent.CaptureTaskState = true; DebugUtil.CaptureStackTrace = true; Console.WriteLine("Debug capture: task-state and stack-trace"); break; } break; case ConsoleKey.I: { Console.WriteLine("--- System Information ---"); // show memory Console.WriteLine("Allocated memory: {0}", GC.GetTotalMemory(false)); // show threads int workerThreads; int completionThreads; int dispatcherThreads; int backgroundThreads; AsyncUtil.GetAvailableThreads(out workerThreads, out completionThreads, out dispatcherThreads, out backgroundThreads); int maxWorkerThreads; int maxCompletionThreads; int maxDispatcherThreads; int maxBackgroundThreads; AsyncUtil.GetMaxThreads(out maxWorkerThreads, out maxCompletionThreads, out maxDispatcherThreads, out maxBackgroundThreads); Console.WriteLine("Thread-pool worker threads available: {0} (max: {1})", workerThreads, maxWorkerThreads); Console.WriteLine("Thread-pool completion threads available: {0} (max: {1})", completionThreads, maxCompletionThreads); Console.WriteLine("Dispatcher threads available: {0} (max: {1})", dispatcherThreads, maxDispatcherThreads); Console.WriteLine("Thread-pool background worker threads available: {0} (max: {1})", backgroundThreads, maxBackgroundThreads); // show pending/waiting timers var taskTimerStats = Tasking.TaskTimerFactory.GetStatistics(); Console.WriteLine("Pending timer objects: {0}", taskTimerStats.PendingTimers); Console.WriteLine("Queued timer objects: {0}", taskTimerStats.QueuedTimers); Console.WriteLine("Timer retries: {0}", taskTimerStats.Retries); // show activities var activities = _host.ActivityMessages; Console.WriteLine("Host activities: {0}", activities.Length); foreach (var activity in activities) { Console.WriteLine("* {0}: {1}", activity.Created.ToString(XDoc.RFC_DATETIME_FORMAT), activity.Description); } // show pending tasks Console.WriteLine("Pending rendez-vous events: {0}", Threading.RendezVousEvent.PendingCounter); Console.WriteLine("Pending results: {0}", AResult.PendingCounter); lock (Threading.RendezVousEvent.Pending) { int count = 0; foreach (var entry in Threading.RendezVousEvent.Pending.Values) { ++count; if (entry.Key != null) { var context = entry.Key.GetState <DreamContext>(); if (context != null) { Console.WriteLine("--- DreamContext for pending rendez-vous event #{0} ---", count); Console.WriteLine(context.Uri.ToString(false)); } } Console.WriteLine(); if (entry.Value != null) { Console.WriteLine("--- Stack trace for pending rendez-vous event #{0} ---", count); Console.WriteLine(entry.Value.ToString()); } } } Console.WriteLine("--------------------------"); } break; case ConsoleKey.H: Console.WriteLine("Help:"); Console.WriteLine(" Q - quit application"); Console.WriteLine(" ESC - quit application"); Console.WriteLine(" SPACE - quit application"); Console.WriteLine(" G - full garbage collection"); Console.WriteLine(" C - clear screen"); Console.WriteLine(" D - set debug capture level"); Console.WriteLine(" I - show system information (memory, threads, pending tasks)"); Console.WriteLine(" H - this help text"); break; } } #endregion } } else { _host.WaitUntilShutdown(); } } finally { Console.WriteLine("-------------------- shutting down"); TaskTimerFactory.ShutdownAll(); if (_host != null) { _host.Dispose(); } } return(0); }
//--- Constructors --- protected InstanceManager(DekiWikiService dekiService, TaskTimerFactory timerFactory) { _dekiService = dekiService; _timerFactory = timerFactory; }
//--- Constructors --- public TimedAccumulator(Action <IEnumerable <T> > handler, int maxItems, TimeSpan autoFlushDelay, TaskTimerFactory timerFactory) { if (handler == null) { throw new ArgumentNullException("handler"); } _accumulator = new AutoFlushContainer <List <T> >( initialState: new List <T>(), flush: (list, disposing) => { if (list.Any()) { var items = list.GetRange(0, Math.Min(list.Count, maxItems)); list.RemoveRange(0, items.Count); handler(items); } }, maxUpdates: maxItems, autoFlushDelay: autoFlushDelay, timerFactory: timerFactory ); }
//--- Constructors --- /// <summary> /// Create a new factory instance. /// </summary> /// <param name="timer">The timer factory to be provided to cache instances.</param> /// <param name="factoryMethod">A function for creating a new cache instance from an <see cref="ISerializer"/> instance and timer factory.</param> public KeyValueCacheFactory(TaskTimerFactory timer, Func <ISerializer, TaskTimerFactory, IKeyValueCache> factoryMethod) { _timer = timer; _factoryMethod = factoryMethod; }
//--- Constructors --- public Listener(string queuename, Action <AwsSqsMessage> callback, IAwsSqsClient client, TaskTimerFactory timerFactory, TimeSpan interval) { _queuename = queuename; _callback = callback; _client = client; _cache = new ExpiringHashSet <string>(timerFactory); _cacheTimer = ((interval.TotalSeconds * 2 < 60) ? 60 : interval.TotalSeconds * 2 + 1).Seconds(); _pollTimer = timerFactory.New(tt => Coroutine.Invoke(PollSqs, new Result()) .WhenDone( r => { if (_isDisposed) { return; } _pollTimer.Change(interval, TaskEnv.None); }), null ); _pollTimer.Change(0.Seconds(), TaskEnv.None); }
//--- Constructors --- public SqsPollClient(IAwsSqsClient client, TaskTimerFactory timerFactory) { _client = client; _timerFactory = timerFactory; }
// --- Constructors --- public DreamCache(TaskTimerFactory taskTimerFactory) : this(taskTimerFactory, TimeSpan.FromSeconds(DEFAULT_EXPIRATION_SECS)) { }
/// <summary> /// Create a new factory instance. /// </summary> /// <param name="maxSize">Maximum number of bytes of memory the cache should use for stored items</param> /// <param name="timer">Timer factory to provide to the cache instance.</param> public InMemoryKeyValueCacheFactory(int maxSize, TaskTimerFactory timer) : base(timer, (s, t) => new InMemoryKeyValueCache(s, maxSize, t)) { }
//--- Constructors --- /// <summary> /// Create a new factory instance. /// </summary> /// <param name="timer">Timer factory to provide to the cache instance.</param> public InMemoryKeyValueCacheFactory(TaskTimerFactory timer) : this(DEFAULT_MAX_SIZE, timer) { }
//--- Constructors --- public AutoFlushContainer(T initialState, FlushDelegate flush, int maxUpdates, TimeSpan autoFlushDelay, TaskTimerFactory timerFactory) { if (flush == null) { throw new ArgumentNullException("flush"); } if (maxUpdates <= 0) { throw new ArgumentException("maxItems must be positive", "maxUpdates"); } if (autoFlushDelay <= TimeSpan.Zero) { throw new ArgumentException("maxDelay must be positive", "autoFlushDelay"); } _state = initialState; _flush = flush; _maxUpdates = maxUpdates; _autoFlushDelay = autoFlushDelay; _autoFlushTimer = timerFactory.New(DateTime.MaxValue, AutoFlushCallback, null, TaskEnv.None); }
/// <summary> /// Create a new hashset /// </summary> /// <param name="taskTimerFactory">The timer factory to create the set's timer from</param> /// <param name="autoRefresh"><see langword="True"/> if accessing an entry should extend the expiration time by the time-to-live</param> public ExpiringDictionary(TaskTimerFactory taskTimerFactory, bool autoRefresh) { _set = new ExpiringSet <TKey, TValue>(taskTimerFactory, autoRefresh); _set.CollectionChanged += OnCollectionChanged; _set.EntriesExpired += OnEntriesExpired; }
//--- Constructors --- /// <summary> /// Create a new hashset /// </summary> /// <param name="taskTimerFactory">The timer factory to create the set's timer from</param> public ExpiringHashSet(TaskTimerFactory taskTimerFactory) : this(taskTimerFactory, false) { }
/// <summary> /// Create a new hashset /// </summary> /// <param name="taskTimerFactory">The timer factory to create the set's timer from</param> /// <param name="autoRefresh"><see langword="True"/> if accessing an entry should extend the expiration time by the time-to-live</param> public ExpiringHashSet(TaskTimerFactory taskTimerFactory, bool autoRefresh) { _set = new ExpiringSet <T, T>(taskTimerFactory, autoRefresh); _set.CollectionChanged += OnCollectionChanged; _set.EntriesExpired += OnEntriesExpired; }
//--- Constructor --- internal DekiInstance(DekiWikiService deki, string id, XDoc instanceConfig, ILicenseController licenseController) { if (deki == null) { throw new ArgumentNullException("deki"); } if (string.IsNullOrEmpty(id)) { throw new ArgumentNullException("id"); } this.Id = id; // Note (arnec): this is now the the third place we define a wikiid based logger repository, however constructors interdependencies // currently neccessitates this duplication, and fortunately it is mostly an aesthetic issue. _loggerRepository = new ContextLoggerRepository("[" + Id + "] "); _log = _loggerRepository.Get(GetType()); this.TimerFactory = TaskTimerFactory.Create(this); this.Cache = new DreamCache(TimerFactory); var cacheFactory = new InMemoryKeyValueCacheFactory(TimerFactory); var searchSerializer = new SearchSerializer(); cacheFactory.SetSerializer <SearchResult>(searchSerializer); cacheFactory.SetSerializer <SearchResultDetail>(searchSerializer); this.SearchCache = cacheFactory.Create(); this.Config = instanceConfig; _licenseController = licenseController; this.Log = LogManager.GetLogger(deki.GetType().Name + "_" + id); _deki = deki; _status = DekiInstanceStatus.CREATED; _apiKey = Config[ConfigBL.SECURITY_APIKEY].AsText; foreach (XDoc hostDoc in Config["host"]) { string host = hostDoc.Contents; if (!StringUtil.EqualsInvariantIgnoreCase(host, "*")) { string port = hostDoc["@port"].AsText; string scheme = hostDoc["@https"].AsBool.GetValueOrDefault() ? "https://" : "http://"; string uri = scheme + host + (string.IsNullOrEmpty(port) ? "" : ":" + port); _canonicalUri = new XUri(uri); _log.DebugFormat("divined canonical use from hosts as {0}", _canonicalUri); break; } } if (_canonicalUri == null) { // Note (arnec): this is a best guess fallback. It will only work in these scenarios: // a) The host was set up with a uri.public that has ends in @api and with the @api points to the site uri, or // b) The api lives on the same machine as the site, so that deriving uri.public for the host from the machine // IP happens to point to the same machine // Either way it relies on the hard-coded assumption that the api is accessible via {site}/@api _canonicalUri = DreamContext.Current.ServerUri; if (_canonicalUri.LastSegment.EqualsInvariantIgnoreCase("@api")) { _canonicalUri = _canonicalUri.WithoutLastSegment(); } _log.DebugFormat("using server uri as canonical uri: {0}", _canonicalUri); } else { // Note (arnec): Propagating a much hard-coded assumption, i.e. that the Api for any Deki instance can be accessed // at the instances' canonical uri plus @api // register the api uri with the dream host so that requests originating from within Dream are guaranteed to be locally routed _deki.Env.At("status", "aliases").Post(new XDoc("aliases").Elem("uri.alias", _canonicalUri.At("@api")), new Result <DreamMessage>()); } }
public DreamCache(TaskTimerFactory taskTimerFactory, TimeSpan defaultExpiration) { _expirationTime = defaultExpiration; _expirations = new ExpiringHashSet <CacheItem>(taskTimerFactory); _expirations.EntryExpired += OnExpiration; }