public TagBL() { _dekiContext = DekiContext.Current; _session = DbUtils.CurrentSession; _user = _dekiContext.User; _eventSink = _dekiContext.Instance.EventSink; _culture = DreamContext.Current.Culture; }
//--- Cosntructors --- public IndexRebuilder( IDekiChangeSink eventSink, UserBE currentUser, ISearchBL searchBL, IPageBL pageBL, ICommentBL commentBL, IAttachmentBL attachmentBL, IUserBL userBL, NS[] indexNameSpaceWhitelist, DateTime now ) { _eventSink = eventSink; _currentUser = currentUser; _searchBL = searchBL; _pageBL = pageBL; _commentBL = commentBL; _attachmentBL = attachmentBL; _userBL = userBL; _indexNameSpaceWhitelist = indexNameSpaceWhitelist; _now = now; }
internal void EndShutdown() { if (_status != DekiInstanceStatus.STOPPING) { _log.WarnFormat("EndShutdown was attemped with instance in state {0}", _status); throw new InvalidOperationException("bad state"); } // shut down task timer try { TimerFactory.Dispose(); } catch (Exception e) { _log.Warn(string.Format("unable to shut down timerfactory for instance '{0}': {1}", Id, e.Message), e); } // shut down storage _log.DebugFormat("shutting down storage for '{0}'", Id); try { _storage.Dispose(); } catch (Exception e) { _log.Warn(string.Format("unable to cleanly shut down storage for instance '{0}': {1}", Id, e.Message), e); } _storage = null; // shut down services _log.DebugFormat("shutting down services for '{0}'", Id); try { ServiceBL.StopServices(); // reset instance fields RunningServices.Clear(); } catch (Exception e) { _log.Warn(string.Format("unable to cleanly shut down services for instance '{0}': {1}", Id, e.Message), e); } // shutting down cache try { Cache.Dispose(); } catch (Exception e) { _log.Warn(string.Format("unable to dispose the cache for instance '{0}': {1}", Id, e.Message), e); } // shutting down search cache try { SearchCache.Dispose(); } catch (Exception e) { _log.Warn(string.Format("unable to dispose the search cache for instance '{0}': {1}", Id, e.Message), e); } // sending shut down event try { _eventSink.InstanceShutdown(DekiContext.Current.Now); } catch (Exception e) { _log.Warn(string.Format("unable to send the shutdown notification event for instance '{0}': {1}", Id, e.Message), e); } _eventSink = null; // unregister the instance to database mapping if (null != _sessionFactory) { try { _sessionFactory.Dispose(); } catch (Exception e) { _log.Warn(string.Format("unable to cleanly shut down the session factory for instance '{0}': {1}", Id, e.Message), e); } _sessionFactory = null; } _log.DebugFormat("instance '{0}' stopped", Id); _status = DekiInstanceStatus.STOPPED; }
/// <summary> /// Calls methods to perform initial init of a wiki instance including db updates, etc /// </summary> public void Startup(DekiContext context) { if (context == null) { throw new ArgumentNullException("context"); } if (_status != DekiInstanceStatus.CREATED) { throw new InvalidOperationException("bad state"); } _status = DekiInstanceStatus.INITIALIZING; // run startup code try { // have to initialize the event sink first since because license checking might trigger a license transition event _eventSink = new DekiChangeSink(Id, DekiContext.Current.ApiUri, DekiContext.Current.Deki.PubSub.At("publish").WithCookieJar(DekiContext.Current.Deki.Cookies)); // create the IDekiDataSessionFactory for this instance Type typeMySql = Type.GetType("MindTouch.Deki.Data.MySql.MySqlDekiDataSessionFactory, mindtouch.deki.data.mysql", true); Type typeCaching = null; try { typeCaching = Type.GetType("MindTouch.Deki.Data.Caching.CachingDekiDataSessionFactory, mindtouch.data.caching", false); } catch (Exception x) { Log.Warn("The caching library was found but could not be loaded. Check that its version matches the version of your MindTouch API", x); } // FUN FACT: DekiInstanceSettings is a proxy for the static calls in ConfigBL, which expects to access DbUtils.CurrentSession, // which has to be initialized by the session factory.. Yes, the very session factory that takes DekiInstanceSettings as part // of its initialization call. I call it the M.C.Escher Design Pattern. var sessionFactory = (IDekiDataSessionFactory)typeMySql.GetConstructor(Type.EmptyTypes).Invoke(null); sessionFactory = new LoggingDekiDataSessionFactory(sessionFactory); sessionFactory = new DekiDataSessionProfilerFactory(sessionFactory); if (typeCaching != null) { sessionFactory = (IDekiDataSessionFactory)typeCaching.GetConstructor(new[] { typeof(IDekiDataSessionFactory) }).Invoke(new object[] { sessionFactory }); } _sessionFactory = sessionFactory; _sessionFactory.Initialize(Config ?? _deki.Config, _licenseController.LicenseDoc, new DekiInstanceSettings()); var state = context.LicenseManager.LicenseState; if (state == LicenseStateType.UNDEFINED) { throw new MindTouchInvalidLicenseStateException(); } // set deki license token _token = context.LicenseManager.LicenseDocument["licensee/deki"].AsText; if (string.IsNullOrEmpty(_token)) { // compute deki license token var tokenKey = _apiKey ?? _deki.MasterApiKey; ulong folded_productkey_md5 = 0; byte[] md5_bytes = StringUtil.ComputeHash(tokenKey, Encoding.UTF8); for (int i = 0; i < md5_bytes.Length; ++i) { folded_productkey_md5 ^= (ulong)md5_bytes[i] << (i & 7) * 8; } _token = folded_productkey_md5.ToString("X"); } // check if a storage config section was provided (default storage is filesystem provider) XDoc storageConfig; switch (ConfigBL.GetInstanceSettingsValue("storage/@type", ConfigBL.GetInstanceSettingsValue("storage/type", "default"))) { case "default": string defaultAttachPath = Path.Combine(_deki.DekiPath, "attachments"); storageConfig = new XDoc("config") .Elem("path", defaultAttachPath) .Elem("cache-path", Path.Combine(defaultAttachPath, ".cache")); _storage = new FSStorage(storageConfig); break; case "fs": string fsPath = ConfigBL.GetInstanceSettingsValue("storage/fs/path", null); //Replace a $1 with the wiki name fsPath = string.Format(PhpUtil.ConvertToFormatString(fsPath ?? string.Empty), Id); storageConfig = new XDoc("config") .Elem("path", fsPath) .Elem("cache-path", ConfigBL.GetInstanceSettingsValue("storage/fs/cache-path", null)); _storage = new FSStorage(storageConfig); break; case "s3": storageConfig = new XDoc("config") .Elem("publickey", ConfigBL.GetInstanceSettingsValue("storage/s3/publickey", null)) .Elem("privatekey", ConfigBL.GetInstanceSettingsValue("storage/s3/privatekey", null)) .Elem("bucket", ConfigBL.GetInstanceSettingsValue("storage/s3/bucket", null)) .Elem("prefix", string.Format(PhpUtil.ConvertToFormatString(ConfigBL.GetInstanceSettingsValue("storage/s3/prefix", string.Empty)), DekiContext.Current.Instance.Id)) .Elem("timeout", ConfigBL.GetInstanceSettingsValue("storage/s3/timeout", null)) .Elem("allowredirects", ConfigBL.GetInstanceSettingsValue("storage/s3/allowredirects", null)) .Elem("redirecttimeout", ConfigBL.GetInstanceSettingsValue("storage/s3/redirecttimeout", null)); _storage = new S3Storage(storageConfig, _loggerRepository.Get <S3Storage>()); break; default: throw new ArgumentException("Storage provider unknown or not defined (key: storage/type)", "storage/type"); } HomePageId = DbUtils.CurrentSession.Pages_HomePageId; _eventSink.InstanceStarting(DekiContext.Current.Now); } catch { // we failed to initialize _status = DekiInstanceStatus.ABANDONED; throw; } // set state to initializing _status = DekiInstanceStatus.INITIALIZING; }
internal void EndShutdown() { if(_status != DekiInstanceStatus.STOPPING) { _log.WarnFormat("EndShutdown was attemped with instance in state {0}", _status); throw new InvalidOperationException("bad state"); } // shut down task timer try { TimerFactory.Dispose(); } catch(Exception e) { _log.Warn(string.Format("unable to shut down timerfactory for instance '{0}': {1}", Id, e.Message), e); } // shut down storage _log.DebugFormat("shutting down storage for '{0}'", Id); try { _storage.Dispose(); } catch(Exception e) { _log.Warn(string.Format("unable to cleanly shut down storage for instance '{0}': {1}", Id, e.Message), e); } _storage = null; // shut down services _log.DebugFormat("shutting down services for '{0}'", Id); try { ServiceBL.StopServices(); // reset instance fields RunningServices.Clear(); } catch(Exception e) { _log.Warn(string.Format("unable to cleanly shut down services for instance '{0}': {1}", Id, e.Message), e); } // shutting down cache try { Cache.Dispose(); } catch(Exception e) { _log.Warn(string.Format("unable to dispose the cache for instance '{0}': {1}", Id, e.Message), e); } // shutting down search cache try { SearchCache.Dispose(); } catch(Exception e) { _log.Warn(string.Format("unable to dispose the search cache for instance '{0}': {1}", Id, e.Message), e); } // sending shut down event try { _eventSink.InstanceShutdown(DekiContext.Current.Now); } catch(Exception e) { _log.Warn(string.Format("unable to send the shutdown notification event for instance '{0}': {1}", Id, e.Message), e); } _eventSink = null; // unregister the instance to database mapping if(null != _sessionFactory) { try { _sessionFactory.Dispose(); } catch(Exception e) { _log.Warn(string.Format("unable to cleanly shut down the session factory for instance '{0}': {1}", Id, e.Message), e); } _sessionFactory = null; } _log.DebugFormat("instance '{0}' stopped", Id); _status = DekiInstanceStatus.STOPPED; }
/// <summary> /// Calls methods to perform initial init of a wiki instance including db updates, etc /// </summary> public void Startup(DekiContext context) { if(context == null) { throw new ArgumentNullException("context"); } if(_status != DekiInstanceStatus.CREATED) { throw new InvalidOperationException("bad state"); } _status = DekiInstanceStatus.INITIALIZING; // run startup code try { // have to initialize the event sink first since because license checking might trigger a license transition event _eventSink = new DekiChangeSink(Id, DekiContext.Current.ApiUri, DekiContext.Current.Deki.PubSub.At("publish").WithCookieJar(DekiContext.Current.Deki.Cookies)); // create the IDekiDataSessionFactory for this instance Type typeMySql = Type.GetType("MindTouch.Deki.Data.MySql.MySqlDekiDataSessionFactory, mindtouch.deki.data.mysql", true); Type typeCaching = null; try { typeCaching = Type.GetType("MindTouch.Deki.Data.Caching.CachingDekiDataSessionFactory, mindtouch.data.caching", false); } catch(Exception x) { Log.Warn("The caching library was found but could not be loaded. Check that its version matches the version of your MindTouch API", x); } // FUN FACT: DekiInstanceSettings is a proxy for the static calls in ConfigBL, which expects to access DbUtils.CurrentSession, // which has to be initialized by the session factory.. Yes, the very session factory that takes DekiInstanceSettings as part // of its initialization call. I call it the M.C.Escher Design Pattern. var sessionFactory = (IDekiDataSessionFactory)typeMySql.GetConstructor(Type.EmptyTypes).Invoke(null); sessionFactory = new LoggingDekiDataSessionFactory(sessionFactory); sessionFactory = new DekiDataSessionProfilerFactory(sessionFactory); if(typeCaching != null) { sessionFactory = (IDekiDataSessionFactory)typeCaching.GetConstructor(new[] { typeof(IDekiDataSessionFactory) }).Invoke(new object[] { sessionFactory }); } _sessionFactory = sessionFactory; _sessionFactory.Initialize(Config ?? _deki.Config, _licenseController.LicenseDoc, new DekiInstanceSettings()); var state = context.LicenseManager.LicenseState; if(state == LicenseStateType.UNDEFINED) { throw new MindTouchInvalidLicenseStateException(); } // set deki license token _token = context.LicenseManager.LicenseDocument["licensee/deki"].AsText; if(string.IsNullOrEmpty(_token)) { // compute deki license token var tokenKey = _apiKey ?? _deki.MasterApiKey; ulong folded_productkey_md5 = 0; byte[] md5_bytes = StringUtil.ComputeHash(tokenKey, Encoding.UTF8); for(int i = 0; i < md5_bytes.Length; ++i) { folded_productkey_md5 ^= (ulong)md5_bytes[i] << (i & 7) * 8; } _token = folded_productkey_md5.ToString("X"); } // check if a storage config section was provided (default storage is filesystem provider) XDoc storageConfig; switch(ConfigBL.GetInstanceSettingsValue("storage/@type", ConfigBL.GetInstanceSettingsValue("storage/type", "default"))) { case "default": string defaultAttachPath = Path.Combine(_deki.DekiPath, "attachments"); storageConfig = new XDoc("config") .Elem("path", defaultAttachPath) .Elem("cache-path", Path.Combine(defaultAttachPath, ".cache")); _storage = new FSStorage(storageConfig); break; case "fs": string fsPath = ConfigBL.GetInstanceSettingsValue("storage/fs/path", null); //Replace a $1 with the wiki name fsPath = string.Format(PhpUtil.ConvertToFormatString(fsPath ?? string.Empty), Id); storageConfig = new XDoc("config") .Elem("path", fsPath) .Elem("cache-path", ConfigBL.GetInstanceSettingsValue("storage/fs/cache-path", null)); _storage = new FSStorage(storageConfig); break; case "s3": storageConfig = new XDoc("config") .Elem("publickey", ConfigBL.GetInstanceSettingsValue("storage/s3/publickey", null)) .Elem("privatekey", ConfigBL.GetInstanceSettingsValue("storage/s3/privatekey", null)) .Elem("bucket", ConfigBL.GetInstanceSettingsValue("storage/s3/bucket", null)) .Elem("prefix", string.Format(PhpUtil.ConvertToFormatString(ConfigBL.GetInstanceSettingsValue("storage/s3/prefix", string.Empty)), DekiContext.Current.Instance.Id)) .Elem("timeout", ConfigBL.GetInstanceSettingsValue("storage/s3/timeout", null)) .Elem("allowredirects", ConfigBL.GetInstanceSettingsValue("storage/s3/allowredirects", null)) .Elem("redirecttimeout", ConfigBL.GetInstanceSettingsValue("storage/s3/redirecttimeout", null)); _storage = new S3Storage(storageConfig, _loggerRepository.Get<S3Storage>()); break; default: throw new ArgumentException("Storage provider unknown or not defined (key: storage/type)", "storage/type"); } HomePageId = DbUtils.CurrentSession.Pages_HomePageId; _eventSink.InstanceStarting(DekiContext.Current.Now); } catch { // we failed to initialize _status = DekiInstanceStatus.ABANDONED; throw; } // set state to initializing _status = DekiInstanceStatus.INITIALIZING; }