/* * This file is a part of Winix * and is distributed under the 2-Clause BSD licence. * Author: Tomasz Sowa */ /* * 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 #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 * 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_indexsecond.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 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