public TagsLoader(PIServer server, string[] queries, int tagChunkSize, Orchestrator orchestrator)
 {
     _server = server;
     _queries = queries;
     _tagChunkSize = tagChunkSize;
     _orchestrator = orchestrator;
 }
        private static void Main(string[] args)
        {
            PIConnection piConnection;
            var _logger = LogManager.GetLogger(typeof (Program));

            try
            {
                var options = new CommandLineOptions();

                if (Parser.Default.ParseArguments(args, options))
                {

                    ValidateSettings(options);

                    var readerSettings = new DataReaderSettings();

                    if(options.Server.Length==1)
                        piConnection = new PIConnection(options.Server[0]);
                    else
                        piConnection = new PIConnection(options.Server[0], options.Server[1]);

                    if (options.testTagSearch != null && options.testTagSearch.Length > 0)
                    {
                        _logger.Info("Search test started...");

                        piConnection.Connect();

                        var search = new TagsLoader(piConnection.GetPiServer());
                        foreach (var s in options.testTagSearch)
                        {
                            var tags = search.Search(s).ToList();
                            _logger.WarnFormat("Found {0} tags with query {1}", tags.Count, s);

                            if (options.testTagSearchPrintAllTags)
                            {
                                tags.ForEach(t => _logger.InfoFormat("Tag: {0}, PointClass: {1}", t.Name, t.PointClass));
                            }
                        }
                    }

                    if (options.TagQueries != null && options.TagQueries.Length > 0)
                    {
                        _logger.Info("Data reader starting...");

                        piConnection.Connect();

                        if (options.EventsPerDay > 0 && options.TagsCount > 0)
                        {
                            // var type = options.UseParallel? DataReaderSettings.ReadingType.Parallel: DataReaderSettings.ReadingType.Bulk;
                            var type = DataReaderSettings.ReadingType.Bulk;
                            readerSettings.AutoTune(type, options.EventsPerDay, options.TagsCount, options.EventsPerRead);
                        }

                        // starts the data writer

                        // defines rejected states to filter out
                        var rejectedStates = new[]
                                                {
                            "pt created",
                            "snapfix",
                            "shutdown",
                            "no data",
                            "bad",
                            "No Alarm",
                            "High Alarm",
                            "Low Alarm",
                            "Hi Alarm/Ack",
                            "Lo Alarm/Ack",
                            "NoAlrm/UnAck",
                            "Bad Quality",
                            "Rate Alarm",
                            "Rate Alm/Ack",
                            "Dig Alarm",
                            "Dig Alm/Ack",
                            "?204",
                            "?205",
                            "?206",
                            "?207",
                            "?208",
                            "?209",
                            "AccessDenied",
                            "No Sample",
                            "No Result",
                            "Unit Down",
                            "Sample Bad",
                            "Equip Fail",
                            "No Lab Data",
                            "Trace",
                            "GreaterMM",
                            "Bad Lab Data",
                            "Good-Off",
                            "Good-On",
                            "Alarm-Off",
                            "Alarm-On",
                            "Bad_Quality",
                            "BadQ-On",
                            "BadQ-Alrm-Of",
                            "BadQ-Alrm-On",
                            "?228",
                            "?229",
                            "Manual",
                            "Auto",
                            "Casc/Ratio",
                            "DCS failed",
                            "Manual Lock",
                            "CO Bypassed",
                            "?236",
                            "Bad Output",
                            "Scan Off",
                            "Scan On",
                            "Configure",
                            "Failed",
                            "Error",
                            "Execute",
                            "Filtered",
                            "Calc Off",
                            "I/O Timeout",
                            "Set to Bad",
                            "Calc Failed",
                            "Calc Overflw",
                            "Under Range",
                            "Over Range",
                            "Bad Input",
                            "Bad Total",
                            "No_Alarm",
                            "Over UCL",
                            "Under LCL",
                            "Over WL",
                            "Under WL",
                            "Over 1 Sigma",
                            "Under 1Sigma",
                            "Over Center",
                            "Under Center",
                            "Stratified",
                            "Mixture",
                            "Trend Up",
                            "Trend Down",
                            "No Alarm#",
                            "Over UCL#",
                            "Under LCL#",
                            "Over WL#",
                            "Under WL#",
                            "Over 1Sigma#",
                            "Under 1Sigm#",
                            "Over Center#",
                            "Under Centr#",
                            "Stratified#",
                            "Mixture#",
                            "Trend Up#",
                            "Trend Down#",
                            "?283",
                            "?284",
                            "?285",
                            "?286",
                            "?287",
                            "?288",
                            "ActiveBatch",
                            "Bad Data",
                            "Calc Crash",
                            "Calc Timeout",
                            "Bad Narg",
                            "Inp OutRange",
                            "Not Converge",
                            "DST Forward",
                            "DST Back",
                            "Substituted",
                            "Invalid Data",
                            "Scan Timeout",
                            "No_Sample",
                            "Arc Off-line",
                            "ISU Saw No Data",
                            "-err",
                            "Good",
                            "_SUBStituted",
                            "Doubtful",
                            "Wrong Type",
                            "Overflow_st",
                            "Intf Shut",
                            "Out of Serv",
                            "Comm Fail",
                            "Not Connect",
                            "Coercion Failed",
                            "Invalid Float",
                            "Future Data Unsupported"
                        };

                        var filtersFactory=new FiltersFactory();
                        filtersFactory.SetDigitalStatesFilters(rejectedStates);
                        filtersFactory.SetFilters(FiltersFactory.FiltersTypesEnum.DigitalStatesFilter,FiltersFactory.FiltersTypesEnum.DuplicateValuesFilter);

                        _logger.Info("Creating worker objects...");
                        var dataWriter = new DataWriter(options.OutfileName, options.EventsPerFile, options.WritersCount, filtersFactory);

                       var dataReader = new DataReaderBulk(readerSettings, dataWriter, options.EnableWrite);

                        //dataReader = options.UseParallel
                        //    ? (IDataReader) new DataReaderParallel(readerSettings, dataWriter)
                        //    : new DataReaderBulk(readerSettings, dataWriter);

                        var orchestrator = new Orchestrator(options.StartTime, options.EndTime,
                            readerSettings.TimeIntervalPerDataRequest, dataReader);

                        var tagsLoader = new TagsLoader(piConnection.GetPiServer(), options.TagQueries,
                            readerSettings.TagGroupSize, orchestrator);

                        var statistics = new Statistics();

                        // starts the orchestrator
                        _logger.Info("Starting workers...");
                        var tagsLoaderTask = tagsLoader.Run();
                        var writerTask = dataWriter.Run();
                        // var processorTask = dataProcessor.Run();
                        var orchestratorTask = orchestrator.Run();
                        var dataReaderTask = dataReader.Run();
                        var statsTask = statistics.Run();

                        // starts the data reader
                        Task.WaitAll(orchestratorTask, writerTask, dataReaderTask, tagsLoaderTask);

                        statistics.Stop();

                        Task.WaitAll(statsTask);

                        _logger.Info("All tasks completed successfully");
                    }

                    // DEBUG
                    //  Console.ReadKey();

                    // exit ok
                    Environment.Exit(0);
                }
                else
                {
                    // exit with error
                    Environment.Exit(1);
                }
            }

            catch (Exception ex)
            {

                _logger.Error(ex);
            }
        }