winix/winixd/templates/patterncacher.cpp

249 lines
5.6 KiB
C++

/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2008-2021, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <algorithm>
#include "patterncacher.h"
#include "core/log.h"
namespace Winix
{
PatternCacher::PatternCacher()
{
when_delete_patterns = 13;
how_many_delete = 3;
ezc_fun = 0;
ezc_blocks = 0;
ezc_obj = 0;
}
void PatternCacher::SetEzcFunctions(TemplatesFunctions::EzcFun * fun)
{
ezc_fun = fun;
}
void PatternCacher::SetEzcBlocks(Ezc::Blocks * blocks)
{
ezc_blocks = blocks;
}
void PatternCacher::SetEzcObjects(Ezc::Objects<HtmlTextStream> * obj)
{
ezc_obj = obj;
}
void PatternCacher::SetWhenDelete(size_t when_delete, size_t how_many_del)
{
when_delete_patterns = when_delete;
how_many_delete = how_many_del;
}
void PatternCacher::DeleteOldPatterns()
{
if( pattern_tab.size() < when_delete_patterns )
return;
PatternTab::iterator i;
PatternErase pe;
size_t erase_index;
erase_tab.resize(pattern_tab.size());
for( i=pattern_tab.begin(), erase_index=0 ; i!=pattern_tab.end() ; ++i, ++erase_index)
{
pe.used = i->second.used;
pe.iter = i;
erase_tab[erase_index] = pe;
}
// sorting through 'used'
std::sort(erase_tab.begin(), erase_tab.end());
for(erase_index = 0 ; erase_index<how_many_delete && erase_index<erase_tab.size() ; ++erase_index)
{
log << log2 << "PC: deleting ezc pattern from the cache, id: "
<< erase_tab[erase_index].iter->second.item_id
<< ", item used: " << erase_tab[erase_index].used << " time(s)"
<< logend;
pattern_tab.erase(erase_tab[erase_index].iter);
}
}
void PatternCacher::CreatePattern(const Item & item, Ezc::Pattern & pattern)
{
/*
* we do not set pattern_parser.SetBlocks()
* blocks cannot be created in patterns generated from virtual FS
* but we can call other blocks (from normal templates)
*
*/
pattern_parser.AllowInclude(false);
pattern_parser.DeleteWhiteTextItems(false);
pattern_parser.SetLogger(&log);
pattern_parser.ParseString(item.item_content.content_raw, pattern);
RebuildCache(pattern);
}
Ezc::Pattern * PatternCacher::AddPattern(const Item & item)
{
// don't call DeleteOldPatterns() here
// because you can delete a pattern which is in use
// ezc functions such as: item_run, insert_page etc
// are using GetPattern() method which can call this method
PatternUsed pu;
CreatePattern(item, pu.pattern);
pu.used = 1;
pu.item_id = item.id;
std::pair<PatternTab::iterator, bool> res = pattern_tab.insert( std::make_pair(item.id, pu) );
log << log2 << "PC: added ezc pattern, item_id: " << item.id << ", url: " << item.url << logend;
return &(res.first->second.pattern);
}
Ezc::Pattern * PatternCacher::GetPattern(const Item & item)
{
PatternTab::iterator i;
i = pattern_tab.find(item.id);
if( i == pattern_tab.end() )
return AddPattern(item);
else
{
log << log2 << "PC: taking pattern from the cache, id: " << item.id << ", url: " << item.url << logend;
++(i->second.used);
return &(i->second.pattern);
}
}
void PatternCacher::UpdatePattern(const Item & item)
{
PatternTab::iterator i;
i = pattern_tab.find(item.id);
if( i == pattern_tab.end() )
return;
++(i->second.used);
CreatePattern(item, i->second.pattern);
log << log2 << "PC: updated pattern, id: " << item.id << ", url: " << item.url << logend;
}
void PatternCacher::DeletePattern(const Item & item)
{
PatternTab::iterator i;
i = pattern_tab.find(item.id);
if( i == pattern_tab.end() )
return;
log << log2 << "PC: deleted pattern, id: " << item.id << ", url: " << item.url << logend;
pattern_tab.erase(i);
}
size_t PatternCacher::Size()
{
return pattern_tab.size();
}
void PatternCacher::RebuildCache(Ezc::Pattern & pattern)
{
pattern.ClearCache();
if( ezc_obj )
pattern.CacheObjects(*ezc_obj);
if( ezc_fun )
pattern.CacheFunctions(*ezc_fun);
if( ezc_blocks )
pattern.CacheBlocks(*ezc_blocks);
}
void PatternCacher::RebuildCache()
{
PatternTab::iterator i = pattern_tab.begin();
for( ; i != pattern_tab.end() ; ++i)
RebuildCache(i->second.pattern);
}
void PatternCacher::ClearCache()
{
PatternTab::iterator i = pattern_tab.begin();
for( ; i != pattern_tab.end() ; ++i)
i->second.pattern.ClearCache();
}
} // namespace Winix