<commit_before>/*******************************************************************************
 * Copyright (c) 2010 Oak Ridge National Laboratory.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 ******************************************************************************/
package org.csstudio.trends.databrowser2.archive;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;

import org.csstudio.apputil.time.BenchmarkTimer;
import org.csstudio.archive.reader.ArchiveReader;
import org.csstudio.archive.reader.ArchiveRepository;
import org.csstudio.archive.reader.ValueIterator;
import org.csstudio.archive.vtype.TimestampHelper;
import org.csstudio.trends.databrowser2.Activator;
import org.csstudio.trends.databrowser2.Messages;
import org.csstudio.trends.databrowser2.model.ArchiveDataSource;
import org.csstudio.trends.databrowser2.model.PVItem;
import org.csstudio.trends.databrowser2.model.RequestType;
import org.csstudio.trends.databrowser2.preferences.Preferences;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.osgi.util.NLS;
import org.epics.vtype.VType;
import org.epics.util.time.Timestamp;

/** Eclipse Job for fetching archived data.
 *  <p>
 *  Actually spawns another thread so that the 'main' job can
 *  poll the progress monitor for cancellation and ask the secondary
 *  thread to cancel.
 *  @author <NAME>
 */
public class ArchiveFetchJob extends Job
{
    /** Poll period in millisecs */
    private static final int POLL_PERIOD_MS = 1000;

    /** Item for which to fetch samples */
    final private PVItem item;

    /** Start/End time */
    final private Timestamp start, end;

    /** Listener that's notified when (if) we completed OK */
    final private ArchiveFetchJobListener listener;

    private static volatile int worker_instance = 0;

    /** Thread that performs the actual background work.
     *
     *  Instead of directly accessing the archive, ArchiveFetchJob launches
     *  a WorkerThread for the actual archive access, so that the Job
     *  can then poll the progress monitor for cancellation and if
     *  necessary interrupt the WorkerThread which might be 'stuck'
     *  in a long running operation.
     */
    class WorkerThread extends Thread
    {
        private String message = ""; //$NON-NLS-1$
        private volatile boolean cancelled = false;
        private volatile boolean done = false;

        /** Archive reader that's currently queried.
         *  Synchronize 'this' on access.
         */
        private ArchiveReader reader = null;

        /** Construct */
        public WorkerThread()
        {
            super("ArchiveFetchJobWorker" + (++worker_instance)); //$NON-NLS-1$
        }

        /** @return Message that somehow indicates progress */
        public synchronized String getMessage()
        {
            return message;
        }

        /** Request thread to cancel its operation */
        public synchronized void cancel()
        {
            cancelled = true;
            synchronized (this)
            {
                if (reader != null)
                    reader.cancel();
            }
        }

        /** @return <code>true</code> when done (success, error, canceled) */
        public synchronized boolean isDone()
        {
            return done;
        }

        /** {@inheritDoc} */
        @Override
        public void run()
        {
            Activator.getLogger().log(Level.FINE, "Starting {0}", ArchiveFetchJob.this); //$NON-NLS-1$
            final int bins = Preferences.getPlotBins();
            final ArchiveDataSource archives[] = item.getArchiveDataSources();
            for (int i=0; i<archives.length && !cancelled; ++i)
            {
                final ArchiveDataSource archive = archives[i];
                final String url = archive.getUrl();
                // Display "N/total", using '1' for the first sub-archive.
                synchronized  (this)
                {
                    message = NLS.bind(Messages.ArchiveFetchDetailFmt,
                            new Object[]
                            {
                                archive.getName(),
                                (i+1),
                                archives.length
                            });
                }
                try
                {
                    final ArchiveReader the_reader;
                    synchronized (this)
                    {
                        the_reader = reader = ArchiveRepository.getInstance().getArchiveReader(url);
                    }
                    final ValueIterator value_iter;
                    if (item.getRequestType() == RequestType.RAW)
                        value_iter = the_reader.getRawValues(archive.getKey(), item.getName(), start, end);
                    else
                        value_iter = the_reader.getOptimizedValues(archive.getKey(), item.getName(), start, end, bins);
                    // Get samples into array
                    final List<VType> result = new ArrayList<VType>();
                    while (value_iter.hasNext())
                        result.add(value_iter.next());
                    item.mergeArchivedSamples(the_reader.getServerName(), result);
                    if (cancelled)
                        break;
                    value_iter.close();
                }
                catch (Exception ex)
                {   // Tell listener unless it's the result of a 'cancel'?
                    if (! cancelled)
                        listener.archiveFetchFailed(ArchiveFetchJob.this, archive, ex);
                    // Continue with the next data source
                }
                finally
                {
                    synchronized (this)<commit_msg>o.c.trends.databrowser2(.opiwidget): Resolve macros for archived data.<commit_after>/*******************************************************************************
 * Copyright (c) 2010 Oak Ridge National Laboratory.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 ******************************************************************************/
package org.csstudio.trends.databrowser2.archive;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;

import org.csstudio.apputil.time.BenchmarkTimer;
import org.csstudio.archive.reader.ArchiveReader;
import org.csstudio.archive.reader.ArchiveRepository;
import org.csstudio.archive.reader.ValueIterator;
import org.csstudio.archive.vtype.TimestampHelper;
import org.csstudio.trends.databrowser2.Activator;
import org.csstudio.trends.databrowser2.Messages;
import org.csstudio.trends.databrowser2.model.ArchiveDataSource;
import org.csstudio.trends.databrowser2.model.PVItem;
import org.csstudio.trends.databrowser2.model.RequestType;
import org.csstudio.trends.databrowser2.preferences.Preferences;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.osgi.util.NLS;
import org.epics.vtype.VType;
import org.epics.util.time.Timestamp;

/** Eclipse Job for fetching archived data.
 *  <p>
 *  Actually spawns another thread so that the 'main' job can
 *  poll the progress monitor for cancellation and ask the secondary
 *  thread to cancel.
 *  @author <NAME>
 */
public class ArchiveFetchJob extends Job
{
    /** Poll period in millisecs */
    private static final int POLL_PERIOD_MS = 1000;

    /** Item for which to fetch samples */
    final private PVItem item;

    /** Start/End time */
    final private Timestamp start, end;

    /** Listener that's notified when (if) we completed OK */
    final private ArchiveFetchJobListener listener;

    private static volatile int worker_instance = 0;

    /** Thread that performs the actual background work.
     *
     *  Instead of directly accessing the archive, ArchiveFetchJob launches
     *  a WorkerThread for the actual archive access, so that the Job
     *  can then poll the progress monitor for cancellation and if
     *  necessary interrupt the WorkerThread which might be 'stuck'
     *  in a long running operation.
     */
    class WorkerThread extends Thread
    {
        private String message = ""; //$NON-NLS-1$
        private volatile boolean cancelled = false;
        private volatile boolean done = false;

        /** Archive reader that's currently queried.
         *  Synchronize 'this' on access.
         */
        private ArchiveReader reader = null;

        /** Construct */
        public WorkerThread()
        {
            super("ArchiveFetchJobWorker" + (++worker_instance)); //$NON-NLS-1$
        }

        /** @return Message that somehow indicates progress */
        public synchronized String getMessage()
        {
            return message;
        }

        /** Request thread to cancel its operation */
        public synchronized void cancel()
        {
            cancelled = true;
            synchronized (this)
            {
                if (reader != null)
                    reader.cancel();
            }
        }

        /** @return <code>true</code> when done (success, error, canceled) */
        public synchronized boolean isDone()
        {
            return done;
        }

        /** {@inheritDoc} */
        @Override
        public void run()
        {
            Activator.getLogger().log(Level.FINE, "Starting {0}", ArchiveFetchJob.this); //$NON-NLS-1$
            final int bins = Preferences.getPlotBins();
            final ArchiveDataSource archives[] = item.getArchiveDataSources();
            for (int i=0; i<archives.length && !cancelled; ++i)
            {
                final ArchiveDataSource archive = archives[i];
                final String url = archive.getUrl();
                // Display "N/total", using '1' for the first sub-archive.
                synchronized  (this)
                {
                    message = NLS.bind(Messages.ArchiveFetchDetailFmt,
                            new Object[]
                            {
                                archive.getName(),
                                (i+1),
                                archives.length
                            });
                }
                try
                {
                    final ArchiveReader the_reader;
                    synchronized (this)
                    {
                        the_reader = reader = ArchiveRepository.getInstance().getArchiveReader(url);
                    }
                    final ValueIterator value_iter;
                    if (item.getRequestType() == RequestType.RAW)
                        value_iter = the_reader.getRawValues(archive.getKey(), item.getResolvedName(), start, end);
                    else
                        value_iter = the_reader.getOptimizedValues(archive.getKey(), item.getResolvedName(), start, end, bins);
                    // Get samples into array
                    final List<VType> result = new ArrayList<VType>();
                    while (value_iter.hasNext())
                        result.add(value_iter.next());
                    item.mergeArchivedSamples(the_reader.getServerName(), result);
                    if (cancelled)
                        break;
                    value_iter.close();
                }
                catch (Exception ex)
                {   // Tell listener unless it's the result of a 'cancel'?
                    if (! cancelled)
                        listener.archiveFetchFailed(ArchiveFetchJob.this, archive, ex);
                    // Continue with the next data source
                }
                finally
                {
                    synchronized (this)
{'fraction_non_alphanumeric': 0.11186082432322575, 'fraction_numerical': 0.004471181204780099, 'mean_word_length': 1.920009494422027, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '24050', 'n_tokens_mistral': 3178, 'n_tokens_neox': 2940, 'n_words': 830}