Beispiel #1
0
 private void HandleFreeMessage(NamedPipe pipe, string msg)
 {
     string[] parts = msg.Split(':');
     if (parts.Length == 2 && compilerBusy.ContainsKey(parts[1]))
     {
         string id     = parts[1];
         var    result = "";
         lock (compilerBusy)
         {
             if (compilerBusy.ContainsKey(id))
             {
                 Compiler c = compilerBusy[id];
                 compilerBusy.Remove(id);
                 compilerFree[id] = c;
                 result           = CompilerServiceClient.JobFinishedMessage;
             }
             else
             {
                 result = $"Error: '<free>guid', specified compiler not found with id='{id}'";
             }
         }
         pipe.WriteMessage(result);
     }
     else
     {
         pipe.WriteMessage("Protocol error: expecting '<free>guid', to free the specified compiler");
     }
 }
Beispiel #2
0
        private void HandleLockMessage(NamedPipe pipe)
        {
            Tuple <string, Compiler> pair = GetFreeCompiler();

            // send the id to the client for use in subsequent jobs.
            pipe.WriteMessage(pair.Item1);
        }
Beispiel #3
0
        public bool Compile(CommandLineOptions options, TextWriter log)
        {
            bool finished = false;
            bool result   = false;

            NamedPipe service = Connect(log);

            CompilerOutputStream output = new CompilerOutputStream(log);

            options.compilerId = id;
            StringWriter  writer     = new StringWriter();
            XmlSerializer serializer = new XmlSerializer(typeof(CommandLineOptions));

            serializer.Serialize(writer, options);
            service.WriteMessage(writer.ToString());

            try
            {
                while (!finished && !service.IsClosed)
                {
                    string msg = service.ReadMessage();
                    DebugWriteLine(msg);
                    int i = msg.IndexOf(':');
                    if (i > 0)
                    {
                        string       sev      = msg.Substring(0, i);
                        SeverityKind severity = SeverityKind.Info;
                        Enum.TryParse <SeverityKind>(sev, out severity);
                        msg = msg.Substring(i + 2);

                        if (msg.StartsWith(JobFinishedMessage))
                        {
                            string tail = msg.Substring(JobFinishedMessage.Length);
                            finished = true;
                            bool.TryParse(tail, out result);
                        }
                        else
                        {
                            output.WriteMessage(msg, severity);
                        }
                    }
                    else
                    {
                        log.WriteLine(msg);
                    }
                }
            }
            catch (Exception)
            {
                result = false;
                output.WriteMessage("PCompilerService is gone, did someone kill it?  Perhaps the P build is happening in parallel?", SeverityKind.Error);
                finished = true;
            }

            return(result);
        }
Beispiel #4
0
        private void OnClientConnected(object sender, NamedPipe pipe)
        {
            while (!pipe.IsClosed)
            {
                // the protocol after client connects is to send a job, we send back results until we
                // send the <job-finished> message, then we expect a "<job-finished>" handshake from client
                // or the client sends another job.
                string msg = pipe.ReadMessage();
                if (msg == null)
                {
                    // pipe is closing.
                }
                else if (msg == CompilerServiceClient.CompilerLockMessage)
                {
                    HandleLockMessage(pipe);
                }
                else if (msg.StartsWith(CompilerServiceClient.CompilerFreeMessage))
                {
                    // this session is done, double handshake.
                    HandleFreeMessage(pipe, msg);
                }
                else if (!string.IsNullOrEmpty(msg))
                {
                    try
                    {
                        doMoreWork = true;
                        var output = new SerializedOutput(pipe);

                        bool result = ProcessJob(msg, output);

                        // now make sure client gets the JobFinishedMessage message!
                        output.WriteMessage(CompilerServiceClient.JobFinishedMessage + result, SeverityKind.Info);
                        output.Flush();
                    }
                    catch (Exception)
                    {
                        // deserialization of the job failed, so ignore it.
                    }
                }
            }

            pipe.Close();
        }
Beispiel #5
0
        private NamedPipe Connect(ICompilerOutput log)
        {
            var processLock = new Mutex(false, "PCompilerService");

            processLock.WaitOne();
            try
            {
                if (service == null)
                {
                    service = new NamedPipe(ServerPipeName);

                    if (!service.Connect())
                    {
                        Process.Start(new ProcessStartInfo
                        {
                            FileName    = typeof(CompilerServiceClient).Assembly.Location,
                            WindowStyle = ProcessWindowStyle.Hidden
                        });
                        if (!service.Connect())
                        {
                            log.WriteMessage("Cannot start the CompilerService?", SeverityKind.Error);
                            service = null;
                            return(null);
                        }
                        else
                        {
                            // now lock a Compiler object until we re disposed so we can get better
                            // performance by sharing the same Compiler across compile, link and test.
                            service.WriteMessage(CompilerLockMessage);
                            id = service.ReadMessage();
                        }
                    }
                }
            }
            finally
            {
                processLock.ReleaseMutex();
            }

            return(service);
        }
Beispiel #6
0
        private void ClientThread(PipeStream pipe)
        {
            try
            {
                NamedPipe client = new NamedPipe(this.pipeName, pipe);

                if (ClientConnected != null)
                {
                    ClientConnected(this, client);
                }
            }
            catch (Exception e)
            {
                IOException io = e as IOException;
                if (io != null)
                {
                    uint hr = (uint)io.HResult;
                    if (hr == 0x800700e7)
                    {
                        // multiple instances, all pipe instances are busy, so go to deep sleep
                        // waiting for other instance to go away.
                        Thread.Sleep(1000);
                    }
                    else if (hr == 0x80131620)
                    {
                        closed = true;
                    }
                    else if (hr == 0x8007006d)
                    {
                        // the pipe has ended, so client went away, we can go back to listening.
                        DebugWriteLine("The pipe has ended: " + this.pipeName);
                    }
                }
                else
                {
                    // on standby, waiting for test to fire up...
                    Thread.Sleep(100);
                }
            }
        }
Beispiel #7
0
        void Run()
        {
            System.Diagnostics.Contracts.Contract.ContractFailed += OnContractFailed;
            Console.WriteLine("Starting compiler service, listening to named pipe");

            // start the server.
            pipe = new NamedPipe(ServerPipeName, true);
            pipe.MessageArrived += OnMessageArrived;
            if (!pipe.Connect())
            {
                Console.WriteLine("Hmmm, is it already running?");
                return;
            }
            doMoreWork = true;

            // stay awake waiting for work
            while (doMoreWork || busyCount > 0)
            {
                doMoreWork = false;
                Thread.Sleep(60 * 60 * 1000); // timeout after 1 hour
            }

            Console.WriteLine("Compiler service terminating due to lack of work");
        }
Beispiel #8
0
        private void Run()
        {
            Contract.ContractFailed += OnContractFailed;
            Console.WriteLine("Starting compiler service, listening to named pipe");

            // start the server.
            var pipe = new NamedPipe(ServerPipeName);

            pipe.ClientConnected += OnClientConnected;

            // we should never use more than Environment.ProcessorCount, the * 2 provides some slop for pipe cleanup from previous jobs.
            pipe.StartServer(Environment.ProcessorCount * 2);

            doMoreWork = true;

            // stay awake waiting for work
            while (doMoreWork || busyCount > 0)
            {
                doMoreWork = false;
                Thread.Sleep(60 * 60 * 1000); // timeout after 1 hour
            }

            Console.WriteLine("Compiler service terminating due to lack of work");
        }
Beispiel #9
0
        private void ProcessJob(string msg)
        {
            Interlocked.Increment(ref busyCount);

            NamedPipe clientPipe = null;

            try
            {
                XmlSerializer      s       = new XmlSerializer(typeof(CommandLineOptions));
                CommandLineOptions options = (CommandLineOptions)s.Deserialize(new StringReader(msg));

                if (!string.IsNullOrEmpty(options.pipeName))
                {
                    clientPipe = new NamedPipe(options.pipeName, false);
                    clientPipe.Connect();
                }

                var output = new SerializedOutput(clientPipe);

                bool retry         = true;
                bool masterCreated = false;

                while (retry)
                {
                    retry = false;
                    // We have to serialize compiler jobs, the Compiler is not threadsafe.
                    lock (compilerlock)
                    {
                        if (master == null)
                        {
                            masterCreated = true;
                            output.WriteMessage("Generating P compiler", SeverityKind.Info);
                            master = new Compiler(false);
                        }

                        // share the compiled P program across compiler instances.
                        Compiler compiler = master; // new Compiler(master);
                        bool     result   = false;
                        try
                        {
                            result = compiler.Compile(options.inputFileName, new SerializedOutput(clientPipe), options);
                        }
                        catch (Exception ex)
                        {
                            if (!masterCreated)
                            {
                                // sometimes the compiler gets out of whack, and rebuilding it solves the problem.
                                retry  = true;
                                master = null;
                            }
                            else
                            {
                                output.WriteMessage("Compile failed: " + ex.ToString(), SeverityKind.Error);
                            }
                        }
                        if (!retry)
                        {
                            compiler.Log.WriteMessage("finished:" + result, SeverityKind.Info);
                        }
                    }
                }

                Thread.Sleep(1000);
            }
            finally
            {
                if (clientPipe != null)
                {
                    clientPipe.Close();
                }
                Interlocked.Decrement(ref busyCount);
            }
        }
Beispiel #10
0
 public SerializedOutput(NamedPipe pipe)
 {
     this.pipe = pipe;
 }
Beispiel #11
0
        public bool Compile(CommandLineOptions options, TextWriter log)
        {
            service = new NamedPipe(ServerPipeName, false);
            Mutex processLock = new Mutex(false, "PCompilerService");

            processLock.WaitOne();
            try
            {
                if (!service.Connect())
                {
                    ProcessStartInfo info = new ProcessStartInfo();
                    info.FileName    = typeof(CompilerServiceClient).Assembly.Location;
                    info.WindowStyle = ProcessWindowStyle.Hidden;
                    Process p = Process.Start(info);
                    if (!service.Connect())
                    {
                        log.WriteLine("Cannot start the CompilerService?");
                        return(false);
                    }
                }
            }
            finally
            {
                processLock.ReleaseMutex();
            }
            Guid   clientPipe     = Guid.NewGuid();
            string clientPipeName = clientPipe.ToString() + "-CompilerServiceClient";

            client = new NamedPipe(clientPipeName, true);
            if (!client.Connect())
            {
                log.WriteLine("weird, the process that launched this job is gone?");
                return(false);
            }
            AutoResetEvent msgEvent = new AutoResetEvent(false);
            bool           finished = false;
            bool           result   = false;

            CompilerOutputStream output = new CompilerOutputStream(log);

            client.MessageArrived += (s2, e2) =>
            {
                string msg = e2.Message;
                int    i   = msg.IndexOf(':');
                if (i > 0)
                {
                    string sev = msg.Substring(0, i);
                    msg = msg.Substring(i + 2);
                    if (msg.StartsWith("finished:"))
                    {
                        i = msg.IndexOf(':');
                        string tail = msg.Substring(i + 1);
                        finished = true;
                        bool.TryParse(tail, out result);
                        msgEvent.Set();
                    }
                    else
                    {
                        SeverityKind severity = SeverityKind.Info;
                        Enum.TryParse <SeverityKind>(sev, out severity);
                        output.WriteMessage(msg, severity);
                    }
                }
                else
                {
                    log.WriteLine(e2.Message);
                }
            };

            options.pipeName = clientPipeName;

            StringWriter  writer     = new StringWriter();
            XmlSerializer serializer = new XmlSerializer(typeof(CommandLineOptions));

            serializer.Serialize(writer, options);
            service.WriteMessage(writer.ToString());

            while (!finished)
            {
                msgEvent.WaitOne(1000);
                if (client.IsClosed)
                {
                    result = false;
                    output.WriteMessage("PCompilerService is gone, did someone kill it?  Perhaps the P build is happening in parallel?", SeverityKind.Error);
                    finished = true;
                }
            }
            service.Close();
            client.Close();
            return(result);
        }