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;
using System.IO;
using System.Threading;
using FLocal.Patcher.Common;
namespace FLocal.IISHandler {
class Initializer {
public static readonly Initializer instance = new Initializer();
private bool isInitialized;
private bool isCached;
private readonly object locker = new object();
///
/// We wouldn't want class constructor to throw an exception, so all "smart" things are inside the Initialize();
///
private Initializer() {
this.isInitialized = false;
this.isCached = false;
}
public void Initialize() {
if(!this.isInitialized) {
lock(this.locker) {
if(!this.isInitialized) {
this.DoInitialize();
this.isInitialized = true;
}
}
}
if(!this.isCached) {
lock(this.locker) {
if(!this.isCached) {
this.DoCache();
this.isCached = true;
}
}
}
}
private void DoInitialize() {
Config.Init(ConfigurationManager.AppSettings);
PatcherConfiguration.Init(ConfigurationManager.AppSettings);
}
private void DoCache() {
if(!PatcherInfo.instance.IsNeedsPatching) {
string dir = FLocal.Common.Config.instance.dataDir + "Logs\\";
using(StreamWriter writer = new StreamWriter(dir + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss") + ".INITIALIZE.txt")) {
writer.WriteLine("###INITIALIZE###");
foreach(var cacher in this.cachers) {
System.Threading.ThreadPool.QueueUserWorkItem(this.GetCacheWrapper(cacher));
writer.WriteLine("Pending " + cacher.Key);
}
}
}
}
private IEnumerable> cachers {
get {
yield return this.GetTableCacher(Machichara.LoadByIds, Machichara.TableSpec.instance);
yield return this.GetTableCacher(ModernSkin.LoadByIds, ModernSkin.TableSpec.instance);
yield return this.GetTableCacher(PostLayer.LoadByIds, PostLayer.TableSpec.instance);
yield return this.GetTableCacher(PunishmentType.LoadByIds, PunishmentType.TableSpec.instance);
yield return this.GetTableCacher(QuickLink.LoadByIds, QuickLink.TableSpec.instance);
yield return this.GetTableCacher(Skin.LoadByIds, Skin.TableSpec.instance);
yield return this.GetTableCacher(UserGroup.LoadByIds, UserGroup.TableSpec.instance);
yield return new KeyValuePair("categories", this.CacheCategories);
}
}
private WaitCallback GetCacheWrapper(KeyValuePair cacher) {
return state => {
string dir = FLocal.Common.Config.instance.dataDir + "Logs\\";
DateTime start = DateTime.Now;
/*using(StreamWriter writer = new StreamWriter(dir + start.ToString("yyyy-MM-dd_HH-mm-ss") + ".init." + cacher.Key + ".txt")) {
writer.WriteLine("###INITIALIZER/CACHER###");
writer.WriteLine("info: " + cacher.Value.Method.Name);
writer.WriteLine();
}*/
FLocalException error = null;
try {
cacher.Value();
} catch(FLocalException e) {
error = e;
}
DateTime end = DateTime.Now;
using(StreamWriter writer = new StreamWriter(dir + end.ToString("yyyy-MM-dd_HH-mm-ss") + ".initend." + cacher.Key + ".txt")) {
writer.WriteLine("###INITIALIZER/CACHER###");
writer.WriteLine("info: " + cacher.Value.Method.Name);
writer.WriteLine("Start: " + start);
writer.WriteLine();
if(error != null) {
writer.WriteLine("Exception: " + error.GetType().FullName);
writer.WriteLine("Guid: " + error.GetGuid().ToString());
writer.WriteLine(error.Message);
if(error is FLocalException) {
writer.WriteLine(((FLocalException)error).FullStackTrace);
} else {
writer.WriteLine(error.StackTrace);
}
}
}
};
}
private KeyValuePair GetTableCacher(Func, List> objectsLoader, ITableSpec tableSpec)
where SqlObjectType : SqlObject, new()
{
return new KeyValuePair(
typeof(SqlObjectType).FullName,
() => {
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.Max(maxPostId - 10000, 0);
for(int i=maxPostId; i>minPostId; i--) {
try {
CachePost(Post.LoadById(i));
} catch(NotFoundInDBException) {
}
}
}
}
private void CachePost(Post post) {
post.LoadIfNotLoaded();
post.thread.LoadIfNotLoaded();
post.poster.LoadIfNotLoaded();
if(post.poster.avatarId != null) {
post.poster.avatar.LoadIfNotLoaded();
}
if(post.revision != null) {
post.latestRevision.LoadIfNotLoaded();
}
if(post.parentPostId != null) {
post.parentPost.LoadIfNotLoaded();
if(post.parentPost.revision != null) {
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);
}
}
}
}