Initializer implemented; some most-used data objects are preloaded from DB during the server initialization to avoid slow lazy loading while serving user requests

main
Inga 🏳‍🌈 13 years ago
parent 0b92260074
commit 89978e1fef
  1. 2
      FLocal.Common/SqlObject.cs
  2. 1
      FLocal.IISHandler/FLocal.IISHandler.csproj
  3. 139
      FLocal.IISHandler/Initializer.cs
  4. 8
      FLocal.IISHandler/MainHandler.cs

@ -77,7 +77,7 @@ namespace FLocal.Common {
}
}
protected void LoadIfNotLoaded() {
public void LoadIfNotLoaded() {
if(!this.isLoaded) {
lock(this.lockInitializer) {
if(!this.isLoaded) {

@ -156,6 +156,7 @@
<Compile Include="handlers\response\UploadInfoHandler.cs" />
<Compile Include="handlers\response\UserDataHandler.cs" />
<Compile Include="handlers\response\UserThreadsHandler.cs" />
<Compile Include="Initializer.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

@ -0,0 +1,139 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using Web.Core;
using Web.Core.DB;
using FLocal.Common;
using FLocal.Common.dataobjects;
namespace FLocal.IISHandler {
class Initializer {
public static readonly Initializer instance = new Initializer();
private bool isInitialized;
private readonly object locker = new object();
/// <summary>
/// We wouldn't want class constructor to throw an exception, so all "smart" things are inside the Initialize();
/// </summary>
private Initializer() {
this.isInitialized = false;
}
public void Initialize() {
if(!this.isInitialized) {
lock(this.locker) {
if(!this.isInitialized) {
this.DoInitialize();
this.isInitialized = true;
}
}
}
}
private void DoInitialize() {
Config.Init(ConfigurationManager.AppSettings);
foreach(var cacher in this.cachers) {
System.Threading.ThreadPool.QueueUserWorkItem(state => this.WrapCacher(cacher));
}
}
private IEnumerable<Action> cachers {
get {
yield return this.GetTableCacher<LocalNetwork>(LocalNetwork.LoadByIds, LocalNetwork.TableSpec.instance);
yield return this.GetTableCacher<Machichara>(Machichara.LoadByIds, Machichara.TableSpec.instance);
yield return this.GetTableCacher<ModernSkin>(ModernSkin.LoadByIds, ModernSkin.TableSpec.instance);
yield return this.GetTableCacher<PostLayer>(PostLayer.LoadByIds, PostLayer.TableSpec.instance);
yield return this.GetTableCacher<PunishmentType>(PunishmentType.LoadByIds, PunishmentType.TableSpec.instance);
yield return this.GetTableCacher<QuickLink>(QuickLink.LoadByIds, QuickLink.TableSpec.instance);
yield return this.GetTableCacher<Skin>(Skin.LoadByIds, Skin.TableSpec.instance);
yield return this.GetTableCacher<UserGroup>(UserGroup.LoadByIds, UserGroup.TableSpec.instance);
yield return this.CacheCategories;
}
}
private void WrapCacher(Action cacher) {
try {
cacher();
} catch(FLocalException) {
}
}
private Action GetTableCacher<SqlObjectType>(Func<IEnumerable<int>, List<SqlObjectType>> objectsLoader, ITableSpec tableSpec)
where SqlObjectType : SqlObject<SqlObjectType>, new()
{
return () => {
foreach(
SqlObjectType sqlObject
in
objectsLoader(
from stringId
in Config.instance.mainConnection.LoadIdsByConditions(
tableSpec,
new Web.Core.DB.conditions.EmptyCondition(),
Diapasone.unlimited
)
select int.Parse(stringId)
)
) {
sqlObject.LoadIfNotLoaded();
}
};
}
private void CacheCategories() {
foreach(var category in Category.allCategories) {
category.LoadIfNotLoaded();
foreach(var board in category.subBoards) {
this.CacheBoard(board);
}
}
int? _maxPostId = (
from category in Category.allCategories
from board in category.subBoards
select board.lastPostId
).Max();
if(_maxPostId.HasValue) {
int maxPostId = _maxPostId.Value;
int minPostId = Math.Min(maxPostId - 10000, 0);
for(int i=maxPostId; i>minPostId; i++) {
try {
var post = Post.LoadById(i);
} catch(NotFoundInDBException) {
}
}
}
}
private void CachePost(Post post) {
post.LoadIfNotLoaded();
post.thread.LoadIfNotLoaded();
post.poster.LoadIfNotLoaded();
post.latestRevision.LoadIfNotLoaded();
post.parentPost.LoadIfNotLoaded();
post.parentPost.latestRevision.LoadIfNotLoaded();
foreach(var punishment in post.punishments) {
punishment.LoadIfNotLoaded();
punishment.moderator.LoadIfNotLoaded();
}
if(post.id > post.thread.firstPostId) {
CachePost(post.thread.firstPost);
}
}
private void CacheBoard(Board board) {
board.LoadIfNotLoaded();
foreach(var subBoard in board.subBoards) {
CacheBoard(subBoard);
}
}
}
}

@ -15,14 +15,6 @@ namespace FLocal.IISHandler {
private void doProcessRequest(HttpContext httpcontext) {
if(!Config.isInitialized) {
lock(typeof(Config)) {
if(!Config.isInitialized) {
Config.Init(ConfigurationManager.AppSettings);
}
}
}
Uri current = httpcontext.Request.Url;
if(!current.Host.EndsWith(Config.instance.BaseHost)) {
throw new Web.Core.FLocalException("Wrong host: " + current.Host + " (expected *" + Config.instance.BaseHost + ")");

Loading…
Cancel
Save