Пример #1
0
        const String MODULE  = "MAIN: "; // for debug log.
        static void Main(string[] args)
        {
            string baseWorkingDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
                                    + "\\PuzzleOracle\\consolidated";

            MyConsole.Initialize();
            MyConsole.WriteLine("LOG PROCESSOR Version " + VERSION);
            MyConsole.WriteLine(String.Format("Working directory [{0}]", baseWorkingDir));
            MyConsole.WriteLine("Press CTRL-C to quit");

            try
            {
                if (!initializeLogging(baseWorkingDir))
                {
                    // Can't progress...
                    throw new ApplicationException("Cannot initialize logging.");
                }

                // Initialie the blocking work queue - it runs all significant processing operations in sequence on the main thread.
                BlockingWorkQueue workQueue = new BlockingWorkQueue();
                //workQueue.enque(null, null, (o, ea) => { Console.WriteLine("TEST WORK ITEM -A-"); });
                //workQueue.enque(null, null, (o, ea) => { Console.WriteLine("TEST WORK ITEM -B-"); });

                // Register the CTRL-C handler - this lets the user quit the program and potentially enter other commands.
                // TODO: Currently the handler simply causes the work queue to exit after the latter processes current work items. Perhaps add some
                // command processing and request confirmation of this behavior.
                Console.CancelKeyPress += new ConsoleCancelEventHandler((o, ea) => { myCtrlCHandler(ea, workQueue); });

                // Create the file copier - responsible for copying files from thumb drives to a staging directory, verifying the file copy and then moving
                // the source files into an arcive subdir on the thumb drive, and (finally) moving the newly copied files under the "new" directory.
                FileCopier fileCopier = new FileCopier(baseWorkingDir);

                // Create a new-drive notifier and hook it up to the file copier - so that the latter will get notified whenever there is a new removable drive
                // plugged in.
                //NewDriveNotifier ndn = new NewDriveNotifier((o, e) => { bwq.enque(o, e, (o1, ea1) => { Console.WriteLine("WORK ITEM -NEW DRIVE-" + ((NewDriveNotifierEventArgs)ea1).driveName); }); });
                using (NewDriveNotifier driveNotifier = new NewDriveNotifier((o, e) => { workQueue.enque(o, e, fileCopier.newDriveHandler); }))
                {
                    // Create a log consumer - this processes submission requests pulled from individual puzzle oracle log files.
                    LogConsumer logConsumer = new LogConsumer(baseWorkingDir);

                    // Create the log processor - that processes new log files as they show up in the "new" directory. Hook it up to the log consumer so that the latter
                    // processes the submissions requests.
                    String newLogsDir = fileCopier.newDir;
                    using (LogProcessor lp = new LogProcessor(newLogsDir, (o, e) => { workQueue.enque(o, e, logConsumer.logEventHandler); }, workQueue))
                    {
                        lp.startListening();            // start listening for new files in the "new directory"
                        driveNotifier.startListening(); // start listening for new thumb drives
                        workQueue.process();
                    }
                }
            }
            catch (ApplicationException e)
            {
                Trace.TraceError("Caught application exception: " + e);
                MyConsole.WriteError("THE LOG PROCESSOR MUST EXIT.\nPress ENTER to quit.");
                Trace.Flush();
                Console.ReadLine();
            }
        }
Пример #2
0
 private static void myCtrlCHandler(ConsoleCancelEventArgs ea, BlockingWorkQueue workQueue)
 {
     Trace.WriteLine(MODULE + "In CTRL-C handler.");
     ea.Cancel = true;
     workQueue.enque(null, null, (ox, ex) => {
         MyConsole.WriteWarning("CTRL-C received. Ok to quit (y/n)?");
         String s = "" + (char)Console.Read();
         if (s.ToUpperInvariant().IndexOf('Y') == 0)
         {
             workQueue.stopWaiting();
         }
     });
 }
Пример #3
0
 // Write content to the file, overwriting if it exists.
 // This is a dangerous utility function, so we restrict it to writing paths that have PuzzleOracle as one of
 // the sub-dirs
 internal static void writeTextFile(string path, string content)
 {
     // This is a potentially dange
     if (path.IndexOf("\\PuzzleOracle\\") == -1)
     {
         MyConsole.WriteError("INTERNAL ERROR!");
         throw new ApplicationException("We don't write random files!");
     }
     using (TextWriter tr = new StreamWriter(path, false)) // false == do NOT append
     {
         tr.Write(content);
         tr.Close();
     }
 }
Пример #4
0
        private void recordSolve(LogEntry le)
        {
            // Record the fact that a particular team has solved a particular puzzle.
            // The way we do this currently is writing out a file <teamID>-<puzzleID>.txt (if it doesn't already exist)
            String content   = String.Format("{0},{1}", le.transactionId, le.timestamp);
            String solveFile = resultsDir + "\\" + String.Format("{0}-{1}.txt", le.teamId, le.puzzleId);

            try
            {
                if (!File.Exists(solveFile))
                {
                    Utils.writeTextFile(solveFile, content);
                }
            }
            catch (IOException ex)
            {
                MyConsole.WriteError(String.Format("WARNING Could not write file [{0}]", solveFile));
            }
        }
Пример #5
0
        /// <summary>
        /// Check if the two (text) files have the same content.
        /// </summary>
        /// <param name="p"></param>
        /// <param name="destPath"></param>
        /// <returns></returns>
        internal static bool filesHaveSameContent(string f1, string f2)
        {
            bool match = false;

            // We don't attempt to be efficient - simply read the entire text and compare them!
            try
            {
                using (TextReader tr1 = new StreamReader(f1), tr2 = new StreamReader(f2))
                {
                    String allText1 = tr1.ReadToEnd();
                    String allText2 = tr2.ReadToEnd();
                    tr1.Close();
                    tr2.Close();
                    match = allText1.Equals(allText2);
                }
            }
            catch (IOException e)
            {
                MyConsole.WriteError(String.Format("IO Exception attempting to compare two files[{0}] and [{1}]: {2}", f2, f2, e));
            }
            return(match);
        }
Пример #6
0
 public static void createDirIfNeeded(String dir, Boolean critical)
 {
     try
     {
         // If directory do not exist, create it.
         if (!Directory.Exists(dir))
         {
             MyConsole.WriteLine(String.Format("Creating directory [{0}].", dir));
             Directory.CreateDirectory(dir);
         }
     }
     catch (IOException e)
     {
         String msg = String.Format("Error [{0}] attempting to create director [{1}]", e.ToString(), dir);
         MyConsole.WriteError(msg);
         if (critical)
         {
             Trace.WriteLine("Throwing application exception on critical error: " + msg);
             throw new ApplicationException(msg);
         }
     }
 }
Пример #7
0
        private static bool initializeLogging(string baseWorkingDir)
        {
            // Check that the base directory exists...
            if (!Directory.Exists(baseWorkingDir))
            {
                MyConsole.WriteError(String.Format("Working directory [{0}]\ndoes not exist.\nPlease create it and restart the log processor.", baseWorkingDir));
                return(false); // ************ EARLY RETURN **************
            }

            // Create a trace listener
            string debugLogPath = baseWorkingDir + "\\debuglog.txt";

            Trace.Listeners.Add(new TextWriterTraceListener(debugLogPath));
            Trace.WriteLine("Log Started");
            Trace.Flush();

            // Verify that the debug log file exists.
            if (!File.Exists(debugLogPath))
            {
                Trace.TraceWarning(String.Format("Debug log [{0}] is not created.", debugLogPath));
                return(false); // ************ EARLY RETURN **************
            }
            return(true);
        }
Пример #8
0
        public void newDriveHandler(object sender, EventArgs e)
        {
            NewDriveNotifierEventArgs nde = (NewDriveNotifierEventArgs)e;

            MyConsole.WriteLine(String.Format("Processing new drive [{0}].", nde.driveName));
        }
Пример #9
0
        public void logEventHandler(object sender, EventArgs ea)
        {
            LogEventArgs lea = (LogEventArgs)ea;

            MyConsole.WriteLine(String.Format("Processing [{0}] ({1} submission(s))", Path.GetFileName(lea.logPath), lea.entries.Length));
            Boolean hadErrors = false;

            foreach (var le in lea.entries)
            {
                String s = String.Format("{0},{1},{2},{3},{4},{5},{6}",
                                         le.transactionId,
                                         le.timestamp,
                                         le.teamId,
                                         le.teamName,
                                         le.puzzleId,
                                         le.status,
                                         le.extraText
                                         );
                String suffix = "(OK)";
                if (!le.valid)
                {
                    // TODO: Watch for invalid entries! Report these to the user.
                    // Also, if there are any invalid entries, OR some other error
                    // attempting to submit the entry to the database,
                    // make a note here and do NOT move the file to the "processed" folder (see below)
                    // Instead move the file to the "processed-with-errors" folder.
                    suffix    = String.Format("(INVALID - {0})", le.parseError);
                    hadErrors = true;
                }
                else
                {
                    this.processEntry(le);
                }
                MyConsole.WriteLine("\t" + le.rowIndex + ":" + s + suffix);
            }

            //
            // TODO: Actually process / commit the data.
            // If ALL entries have been successfully committed to the database, one can
            // move the file to the processed subdirectory, like so...
            //


            String processedDir = (hadErrors ? processedWithErrorsDir : this.processedDir);

            if (!Directory.Exists(processedDir))
            {
                MyConsole.WriteError("ERROR: Processed dir does not exist: " + processedDir);
            }
            else
            {
                String destPath = processedDir + "\\" + Path.GetFileName(lea.logPath);

                try
                {
                    if (File.Exists(destPath))
                    {
                        Trace.WriteLine(MODULE + String.Format("WARNING: File with same name as\n[{0}]exists in the processed dir.", lea.logPath));
                        if (Utils.filesHaveSameContent(lea.logPath, destPath))
                        {
                            Trace.WriteLine(MODULE + String.Format("Files have same content."));
                            File.Delete(lea.logPath);
                        }
                        else
                        {
                            MyConsole.WriteError(String.Format("\tFile with same name but DIFFERENT content exists in processed directory!"));
                            throw new ArgumentException("Attempting to move file to processed dir when one with different content already exists.");
                        }
                    }
                    else
                    {
                        File.Move(lea.logPath, destPath);
                        Trace.WriteLine(MODULE + "Moved file to " + destPath);
                    }
                }
                catch (Exception ex)
                {
                    if (ex is IOException || ex is ArgumentException)
                    {
                        MyConsole.WriteError("\tERROR: Exception while moving path. ex=" + ex.Message);
                    }
                    else
                    {
                        throw ex;
                    }
                }
            }
        }