Esempio n. 1
0
        protected void Flush(bool continue_only)
        {
            IndexerRequest flushed_request;

            if (continue_only)
            {
                // if the request is merely to signal indexhelper to continue indexing,
                // then sent a fake indexerrequest but then use the previous request to retrieve
                // deferred indexables
                flushed_request = new IndexerRequest();
                flushed_request.ContinueIndexing = true;

                // Do not pass this through PreFlushHook since this is a fake request
            }
            else
            {
                lock (request_lock) {
                    if (pending_request.IsEmpty)
                    {
                        return;
                    }

                    flushed_request = pending_request;
                    pending_request = new IndexerRequest();

                    // We hold the request_lock when calling PreFlushHook, so
                    // that no other requests can come in until it exits.
                    PreFlushHook(flushed_request);
                }
            }

            IndexerReceipt [] receipts;
            receipts = indexer.Flush(flushed_request);

            PostFlushHook(flushed_request, receipts);

            if (continue_only)
            {
                flushed_request = pending_request;
            }

            // Silently return if we get a null back.  This is probably
            // a bad thing to do. If IndexHelper is shutdown because of
            // memory blowup or is crashed, then null is returned. Silently
            // returning means ignoring the indexables in the IndexHelper's
            // queue (which could be more than what was sent in the last request,
            // since there could be some deferred-indexables too).
            if (receipts == null)
            {
                return;
            }

            // Nothing happened (except maybe an optimize, which does not
            // generate a receipt).  Also do nothing.
            if (receipts.Length == 0)
            {
                return;
            }

            // Update the cached count of items in the driver
            // FIXME: Verify that this still works after all the deferred-indexable fu
            driver.SetItemCount(indexer.GetItemCount());

            // Something happened, so schedule an optimize just in case.
            ScheduleOptimize();

            if (fa_store != null)
            {
                fa_store.BeginTransaction();
            }

            ArrayList added_uris   = new ArrayList();
            ArrayList removed_uris = new ArrayList();
            bool      indexer_indexable_receipt = false;

            for (int i = 0; i < receipts.Length; ++i)
            {
                if (receipts [i] is IndexerAddedReceipt)
                {
                    IndexerAddedReceipt r;
                    r = (IndexerAddedReceipt)receipts [i];
                    Indexable indexable = flushed_request.RetrieveRequestIndexable(r);

                    if (indexable == null)
                    {
                        Log.Debug("Should not happen! Previously requested indexable with id #{0} has eloped!", r.Id);
                        continue;
                    }

                    // Add the Uri to the list for our change data
                    // *before* doing any post-processing.
                    // This ensures that we have internal uris when
                    // we are remapping.
                    added_uris.Add(indexable.Uri);

                    // Call the appropriate hook
                    Uri notification_uri = indexable.Uri;
                    try {
                        // Map from internal->external Uris in the PostAddHook
                        notification_uri = PostAddHook(indexable, r);
                    } catch (Exception ex) {
                        Logger.Log.Warn(ex, "Caught exception in PostAddHook '{0}' '{1}' '{2}'",
                                        indexable.Uri, r.FilterName, r.FilterVersion);
                    }

                    // Every added Uri also needs to be listed as removed,
                    // to avoid duplicate hits in the query.  Since the
                    // removed Uris need to be external Uris, we add them
                    // to the list *after* post-processing.
                    removed_uris.Add(notification_uri);
                }
                else if (receipts [i] is IndexerRemovedReceipt)
                {
                    IndexerRemovedReceipt r;
                    r = (IndexerRemovedReceipt)receipts [i];

                    Indexable indexable = flushed_request.RetrieveRequestIndexable(r);
                    if (indexable == null)                       // Should never happen
                    {
                        Log.Warn("Unable to match indexable-remove #{0} to any request!", r.Id);
                        continue;
                    }

                    // Call the appropriate hook
                    Uri notification_uri = indexable.Uri;
                    try {
                        notification_uri = PostRemoveHook(indexable, r.NumRemoved);
                    } catch (Exception ex) {
                        Logger.Log.Warn(ex, "Caught exception in PostRemoveHook '{0}'",
                                        indexable.Uri);
                    }

                    // If nothing was removed, no need for change notification
                    if (r.NumRemoved <= 0)
                    {
                        continue;
                    }

                    // Add the removed Uri to the list for our
                    // change data.  This will be an external Uri
                    // when we are remapping.
                    removed_uris.Add(notification_uri);
                }
                else if (receipts [i] is IndexerIndexablesReceipt)
                {
                    indexer_indexable_receipt = true;
                }
            }

            if (!continue_only)
            {
                lock (request_lock) {
                    pending_request.DeferredIndexables = flushed_request.DeferredIndexables;
                }
            }

            if (indexer_indexable_receipt)
            {
                Log.Debug("Indexing of indexer generated indexables is paused. Scheduling job to continue.");
                // Create a task asking the indexer to continue indexing
                Scheduler.Task task;
                task = Scheduler.TaskFromHook(new Scheduler.TaskHook(ContinueIndexerIndexableIndexing));
                // Schedule it so that it is the immediate next task to be scheduled
                task.Priority    = Scheduler.Priority.Immediate;
                task.SubPriority = 100;
                task.Source      = this;
                task.Tag         = "Continue indexing generated indexables from " + IndexName;
                ThisScheduler.Add(task);
            }

            if (fa_store != null)
            {
                fa_store.CommitTransaction();
            }

            // Propagate the change notification to any open queries.
            if (added_uris.Count > 0 || removed_uris.Count > 0)
            {
                ChangeData change_data;
                change_data             = new ChangeData();
                change_data.AddedUris   = added_uris;
                change_data.RemovedUris = removed_uris;

                QueryDriver.QueryableChanged(this, change_data);
            }
        }
Esempio n. 2
0
        // This is mostly a copy of LuceneQueryable.Flush + FSQ.PostAddHooks/PostRemoveHook
        static bool FlushIndexer(IIndexer indexer)
        {
            IndexerRequest flushed_request;

            if (pending_request.IsEmpty)
            {
                return(false);
            }

            flushed_request = pending_request;
            pending_request = new IndexerRequest();

            IndexerReceipt [] receipts;
            receipts = indexer.Flush(flushed_request);

            // Flush will return null if it encounters a shutdown during flushing
            if (receipts == null)
            {
                return(false);
            }

            fa_store.BeginTransaction();
            bool indexer_indexable_receipt = false;

            foreach (IndexerReceipt raw_r in receipts)
            {
                if (raw_r is IndexerAddedReceipt)
                {
                    // Update the file attributes
                    IndexerAddedReceipt r = (IndexerAddedReceipt)raw_r;

                    Indexable indexable = flushed_request.RetrieveRequestIndexable(r);

                    if (indexable == null)
                    {
                        Logger.Log.Debug("Should not happen! Previously requested indexable with id #{0} has eloped!", r.Id);
                        continue;
                    }

                    // We don't need to write out any file attributes for
                    // children.
                    if (indexable.ParentUri != null)
                    {
                        continue;
                    }

                    string path = indexable.Uri.LocalPath;

                    FileAttributes attr;
                    attr = fa_store.ReadOrCreate(path);

                    attr.LastWriteTime = indexable.Timestamp;
                    attr.FilterName    = r.FilterName;
                    attr.FilterVersion = r.FilterVersion;

                    fa_store.Write(attr);
                }
                else if (raw_r is IndexerRemovedReceipt)
                {
                    // Update the file attributes
                    IndexerRemovedReceipt r = (IndexerRemovedReceipt)raw_r;

                    Indexable indexable = flushed_request.RetrieveRequestIndexable(r);
                    if (indexable == null)                       // Should never happen
                    {
                        Log.Warn("Unable to match indexable-remove #{0} to any request!", r.Id);
                        continue;
                    }

                    string path = indexable.Uri.LocalPath;
                    Logger.Log.Debug("Removing: '{0}'", path);
                    fa_store.Drop(path);
                }
                else if (raw_r is IndexerIndexablesReceipt)
                {
                    indexer_indexable_receipt = true;
                }
            }

            pending_request.DeferredIndexables = flushed_request.DeferredIndexables;

            // Reschedule if some indexable generated more indexables
            if (indexer_indexable_receipt)
            {
                pending_request.ContinueIndexing = true;
                return(true);
            }

            fa_store.CommitTransaction();
            return(false);
        }