<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Fredrik Haglund's blog &#187; LazyIndexer</title>
	<atom:link href="http://blog.fredrikhaglund.se/blog/tag/lazyindexer/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.fredrikhaglund.se</link>
	<description>Chatter about EPiServer, ASP.NET, CSS and Web Development.</description>
	<lastBuildDate>Tue, 28 Jun 2011 13:37:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Tool to re-index all EPiServer pages</title>
		<link>http://blog.fredrikhaglund.se/blog/2010/02/19/tool-to-re-index-all-episerver-pages/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2010/02/19/tool-to-re-index-all-episerver-pages/#comments</comments>
		<pubDate>Fri, 19 Feb 2010 18:19:55 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[EPiServer CMS]]></category>
		<category><![CDATA[LazyIndexer]]></category>
		<category><![CDATA[SoftLink]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2010/02/19/tool-to-re-index-all-episerver-pages/</guid>
		<description><![CDATA[You get a warning when you try to delete a file or EPiServer page if it is referenced form another page. EPiServer uses EPiServer.DataAbstraction.SoftLink for this feature and all links to files, other EPiServer pages and external urls are stored here every time you publish a page. It is also worth to notice that EPiServer [...]]]></description>
			<content:encoded><![CDATA[<p>You get a warning when you try to delete a file or EPiServer page if it is referenced form another page.</p>
<p>EPiServer uses <em>EPiServer.DataAbstraction.SoftLink</em> for this feature and all links to files, other EPiServer pages and external urls are stored here every time you publish a page.</p>
<p>It is also worth to notice that EPiServer built-in keyword table that is used for text searching pages also is updated during publish.</p>
<h3>Corrupt data = Broken Links</h3>
<p>The index can be corrupt or out of sync and then it is <strong>possible to delete a file or a page without getting a warning that it has incoming links</strong>. Text search can also fail or return wrong data.</p>
<p>I have seen this very often after a migration from EPiServer CMS 4. EPiServer CMS 4 databases tends to have really poor data for soft links.</p>
<p>The index is updated when you publish a page with a delay controled by <em>indexingDelayAfterPublish</em> setting. If the delay it is very large and the application restarts before the page is indexed, neither soft links or keywords will be updated.</p>
<h3>How to repair EPiServer CMS soft link and keyword index</h3>
<p>I have created an admin tool that we always run after migration from EPiServer 4 and also if we want to repair the index if the settings has been strange.</p>
<p>You sould set <em>indexingDelayAfterPublish</em> to a very large delay during the time you run the tool because if you try to use <em>LaxyIndexer.IndexPage()</em> in more than one thread at the same time you are guaranteed to get deadlocks or get other strange SQL exceptions sooner or later.</p>
<blockquote><p>System.Data.SqlClient.SqlException:Violation of PRIMARY KEY constraint &#8216;PK_tblPageKeyword&#8217;. Cannot insert duplicate key in object &#8216;dbo.tblPageKeyword&#8217;.</p>
</blockquote>
<h3>Example code</h3>
<pre class="code">[GuiPlugIn(DisplayName = <span style="color: #a31515">&quot;Reindex pages&quot;</span>, Description = <span style="color: #a31515">&quot;Tool to index keywords and soft links&quot;</span>, Area = PlugInArea.AdminMenu, Url = <span style="color: #a31515">&quot;~/Common/FixIndexing.aspx&quot;</span>)]
<span style="color: blue">public partial class </span><span style="color: #2b91af">FixIndexing </span>: System.Web.UI.Page
{
    <span style="color: blue">private static readonly </span>ILog log;
    <span style="color: blue">private static long </span>QueueLength;
    <span style="color: blue">private static long </span>IndexedPages;
    <span style="color: blue">private static </span><span style="color: #2b91af">DateTime </span>Started = <span style="color: #2b91af">DateTime</span>.MinValue;
    <span style="color: blue">private static readonly </span>Queue&lt;PageData&gt; Queue = <span style="color: blue">new </span>Queue&lt;PageData&gt;();
    <span style="color: blue">private static object </span>LockRoot = <span style="color: blue">new object</span>();

    <span style="color: blue">static </span>FixIndexing()
    {
        log = LogManager.GetLogger(<span style="color: blue">typeof</span>(FixIndexing));
    }

    <span style="color: blue">protected override void </span>OnLoad(<span style="color: #2b91af">EventArgs </span>e)
    {
        <span style="color: blue">base</span>.OnLoad(e);
        UpdateStatus();
    }

    <span style="color: blue">private void </span>UpdateStatus()
    {
        <span style="color: blue">long </span>q = <span style="color: #2b91af">Interlocked</span>.Read(<span style="color: blue">ref </span>QueueLength);
        <span style="color: blue">long </span>n = <span style="color: #2b91af">Interlocked</span>.Read(<span style="color: blue">ref </span>IndexedPages);
        <span style="color: blue">if </span>(Started != <span style="color: #2b91af">DateTime</span>.MinValue)
        {
            StatusLabel.Text = <span style="color: blue">string</span>.Format(<span style="color: #a31515">&quot;Started: {0}  Indexed pages: {1}  Queue: {2}&quot;</span>, Started, n, q);
        }
        FixPageSoftLinkButton.Enabled = q &lt;= 0;
    }

    <span style="color: blue">protected void </span>FixPageSoftLinkButton_Click(<span style="color: blue">object </span>sender, <span style="color: #2b91af">EventArgs </span>e)
    {
        log.Info(<span style="color: #a31515">&quot;Start LazyIndex of all pages!&quot;</span>);
        Started = <span style="color: #2b91af">DateTime</span>.Now;
        <span style="color: #2b91af">ThreadPool</span>.QueueUserWorkItem(ThreadProc);
        UpdateStatus();
    }

    <span style="color: green">// This thread procedure performs the task.
    </span><span style="color: blue">static void </span>ThreadProc(<span style="color: #2b91af">Object </span>stateInfo)
    {
        <span style="color: blue">if </span>(!<span style="color: #2b91af">Monitor</span>.TryEnter(LockRoot)) <span style="color: blue">return</span>; <span style="color: green">//Job was already running
        </span><span style="color: blue">try
        </span>{
            IndexedPages = 0;
            PageData page;
            Queue.Enqueue(DataFactory.Instance.GetPage(PageReference.RootPage, LanguageSelector.MasterLanguage()));
            <span style="color: #2b91af">Interlocked</span>.Increment(<span style="color: blue">ref </span>QueueLength);
            <span style="color: blue">while </span>((page = Queue.Dequeue()) != <span style="color: blue">null</span>)
            {
                <span style="color: #2b91af">Interlocked</span>.Decrement(<span style="color: blue">ref </span>QueueLength);
                <span style="color: blue">try
                </span>{
                    log.Debug(<span style="color: blue">string</span>.Format(<span style="color: #a31515">&quot;Indexing page {0}:{1}...&quot;</span>, page.PageLink.ID, page.PageName));
                    LazyIndexer.IndexPage(page.PageLink.ID);
                    <span style="color: #2b91af">Interlocked</span>.Increment(<span style="color: blue">ref </span>IndexedPages);
                }
                <span style="color: blue">catch </span>(<span style="color: #2b91af">Exception </span>ex)
                {
                    <span style="color: blue">int </span>id = (stateInfo <span style="color: blue">as </span>PageData) != <span style="color: blue">null </span>? ((PageData)stateInfo).PageLink.ID : -1;
                    log.Error(<span style="color: blue">string</span>.Format(<span style="color: #a31515">&quot;Error while indexing {0}&quot;</span>, id), ex);
                }
                <span style="color: blue">try
                </span>{
                    PageDataCollection pages = DataFactory.Instance.GetChildren(page.PageLink, LanguageSelector.MasterLanguage());
                    log.Debug(<span style="color: blue">string</span>.Format(<span style="color: #a31515">&quot;Done indexing page {0}. Adding {1} children to Queue...&quot;</span>, page.PageLink.ID, pages.Count));
                    <span style="color: blue">foreach </span>(PageData data <span style="color: blue">in </span>pages)
                    {
                        Queue.Enqueue(data);
                        <span style="color: #2b91af">Interlocked</span>.Increment(<span style="color: blue">ref </span>QueueLength);
                    }
                }
                <span style="color: blue">catch </span>(<span style="color: #2b91af">Exception </span>ex)
                {
                    <span style="color: blue">int </span>id = (stateInfo <span style="color: blue">as </span>PageData) != <span style="color: blue">null </span>? ((PageData)stateInfo).PageLink.ID : -1;
                    log.Error(<span style="color: blue">string</span>.Format(<span style="color: #a31515">&quot;Error while adding children for {0}&quot;</span>, id), ex);
                }

            }
        }
        <span style="color: blue">finally
        </span>{
            <span style="color: #2b91af">Monitor</span>.Exit(LockRoot);
        }

    }

}</pre>
<h3>Index as Scheduled task</h3>
<p>Another way to use the code above is to just add an <em>Execute()</em> method that calls <em>ThreadProc</em> and register it as a Scheduled Job plug-in. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2010/02/19/tool-to-re-index-all-episerver-pages/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>

