source: java/main/src/main/java/com/framsticks/running/ExternalProcess.java @ 107

Last change on this file since 107 was 107, checked in by psniegowski, 11 years ago

HIGHLIGHTS:

  • add SimultorProviders? hierarchy
  • start Framsticks server over SSH
  • FJF compatible with Framsticks 4.0rc3
  • reading and writing of standard.expt
  • a proof-of-concept implementation of StandardExperiment?

CHANGELOG:
Optionally return FreeAccess? from registry.

Add SimulatorRange?.

StandardExperiment? with genotypes circulation.

Automate registration around StandardState?.

More improvements to StandardExperiment?.

Skeleton version of StandardExperiment?.

Test saving of StandardState?.

Standard experiment state is being loaded.

More development towards StandardState? reading.

Work on reading standard experiment state.

Add classes for standard experiment.

Update example standard.expt

Add FreeAccess? and FreeObject?.

Made compatible with version 4.0rc3

Change deserialization policy.

Improve SSH support.

Working running simulator over SSH.

Fix joining bug in Experiment.

Working version of SimulatorRunner?.

Add more SimulatorProviders?.

Working PrimeExperimentTest? with 4.0rc3

Add references to deserialization.

Add OpaqueObject? and it's serialization.

Add deserialization of dictionaries.

Partial implementation of deserialization.

Add more tests for deserialization.

Prepare tests for deserialization.

Add proper result to prime experiment test.

Minor fixes to simulators providers.

Draft version of SimulatorProvider?.

Add SimulatorProvider? interface.

File size: 6.2 KB
RevLine 
[88]1package com.framsticks.running;
2
3import java.io.BufferedReader;
4import java.io.File;
5import java.io.IOException;
6import java.io.InputStreamReader;
7import java.io.OutputStreamWriter;
8import java.io.PrintWriter;
9import java.util.ArrayList;
[107]10import java.util.Arrays;
[88]11import java.util.List;
12
13
[100]14import org.apache.logging.log4j.Logger;
15import org.apache.logging.log4j.LogManager;
[88]16
[101]17import com.framsticks.params.EventListener;
18import com.framsticks.params.EventListeners;
19import com.framsticks.params.ParamFlags;
[90]20import com.framsticks.params.annotations.AutoAppendAnnotation;
[88]21import com.framsticks.params.annotations.FramsClassAnnotation;
22import com.framsticks.params.annotations.ParamAnnotation;
[105]23import com.framsticks.structure.messages.ValueChange;
[88]24import com.framsticks.util.FramsticksException;
[90]25import com.framsticks.util.dispatching.AbstractJoinable;
26import com.framsticks.util.dispatching.Dispatching;
27import com.framsticks.util.dispatching.Joinable;
28import com.framsticks.util.dispatching.JoinableParent;
29import com.framsticks.util.dispatching.JoinableState;
30import com.framsticks.util.dispatching.RunAt;
[88]31import com.framsticks.util.dispatching.Thread;
[97]32import com.framsticks.util.dispatching.ThrowExceptionHandler;
[88]33import com.framsticks.util.io.Encoding;
[107]34import com.framsticks.util.lang.Strings;
[88]35
36@FramsClassAnnotation
[96]37public class ExternalProcess extends AbstractJoinable implements JoinableParent {
[100]38        private static final Logger log = LogManager.getLogger(ExternalProcess.class);
[88]39
40        protected List<String> arguments = new ArrayList<>();
41        protected Process process;
[90]42        protected Thread<ExternalProcess> readerThread = new Thread<ExternalProcess>();
[88]43
44        protected PrintWriter input;
45        protected BufferedReader output;
46        protected Integer exitCode;
[101]47        protected String echoInput;
[107]48        protected String directory;
49        protected String host;
[88]50
[101]51        protected final EventListeners<ValueChange> listeners = new EventListeners<>();
[88]52
[90]53        @AutoAppendAnnotation
[101]54        @ParamAnnotation(id = "line_output")
55        public void addOutputListener(EventListener<ValueChange> listener) {
[88]56                synchronized (listeners) {
57                        listeners.add(listener);
58                }
59        }
60
[101]61        @ParamAnnotation(id = "line_output")
62        public void removeOutputListener(EventListener<ValueChange> listener) {
63                synchronized (listeners) {
64                        listeners.remove(listener);
65                }
66        }
67
[88]68        /**
69         *
70         */
71        public ExternalProcess() {
72                super();
73                setName("process");
74                arguments.add(null);
75        }
76
77        /**
78         * @return the command
79         */
[101]80        @ParamAnnotation(flags = ParamFlags.USERREADONLY)
[88]81        public String getCommand() {
82                return arguments.get(0);
83        }
84
85        /**
86         * @param command the command to set
87         */
88        @ParamAnnotation
89        public void setCommand(String command) {
90                arguments.set(0, command);
91        }
92
[90]93        protected void readerTask() {
[88]94
[101]95                log.debug("reading output from " + this);
[88]96                String line;
97                try {
98                        try {
99                                while ((line = output.readLine()) != null) {
[100]100                                        log.trace("read line: {}", line);
[88]101                                        synchronized (listeners) {
[101]102                                                listeners.actionForAll(new ValueChange(line));
[88]103                                        }
104                                }
105                        } catch (IOException e) {
106                                throw new FramsticksException().msg("failed to read line from output of process").cause(e);
107                        }
108                        try {
109                                exitCode = process.waitFor();
110                        } catch (InterruptedException e) {
111                                throw new FramsticksException().msg("failed to wait for process").cause(e);
112                        }
[102]113                        log.info("process ended {}", this);
[90]114                        // process = null;
[88]115                } catch (FramsticksException e) {
[100]116                        log.error("exception caught in process {}", this, e);
[88]117                }
[101]118                interruptJoinable();
[90]119                // finish();
[88]120        }
121
[101]122        @ParamAnnotation(flags = ParamFlags.USERREADONLY)
[88]123        public void setDirectory(String directory) {
[107]124                this.directory = directory;
[88]125        }
126
[107]127        /**
128         * @return the host
129         */
130        public String getHost() {
131                return host;
132        }
133
134        /**
135         * @param host the host to set
136         */
137        public void setHost(String host) {
138                this.host = host;
139        }
140
[88]141        @ParamAnnotation
142        public String getDirectory() {
[107]143                return Strings.toStringNullProof(directory, ".");
[88]144        }
145
146        @Override
[90]147        protected void joinableStart() {
[107]148
149                final ProcessBuilder builder = new ProcessBuilder();
150
151                builder.redirectErrorStream(true);
152                if (host == null) {
153                        setDirectory(System.getProperties().get("user.home") + "/" + getDirectory());
154                        setCommand(getDirectory() + "/" + getCommand());
155                        builder.directory(new File(getDirectory()));
156                } else {
157                        StringBuilder b = new StringBuilder();
158                        setCommand("./" + getCommand());
159                        for (String a : arguments) {
160                                b.append(" '").append(a).append("'");
161                        }
162                        arguments = Arrays.asList("ssh", host, "-tt", ("cd " + getDirectory() + " &&" + b.toString()));
163                }
[103]164                log.info("running process {}", this);
[107]165
[88]166                builder.command(arguments);
167                try {
168                        process = builder.start();
169                        input = new PrintWriter(new OutputStreamWriter(process.getOutputStream(), Encoding.getDefaultCharset()));
170                        output = new BufferedReader(new InputStreamReader(process.getInputStream(), Encoding.getDefaultCharset()));
[90]171
[88]172                } catch (IOException e) {
173                        throw new FramsticksException().msg("failed to start process").cause(e);
174                }
175
[97]176                readerThread.dispatch(new RunAt<ExternalProcess>(ThrowExceptionHandler.getInstance()) {
[90]177
178                        @Override
[97]179                        protected void runAt() {
[90]180                                readerTask();
181                        }
182
183                });
184                Dispatching.use(readerThread, this);
[101]185
186                if (echoInput != null) {
187                        input.println(echoInput);
188                        input.flush();
189                }
[88]190        }
191
192        @Override
193        public String toString() {
[102]194                return getName() + arguments;
[88]195        }
196
197        /**
198         * @return the input
199         */
200        public PrintWriter getInput() {
201                return input;
202        }
203
[101]204        /**
205         * @return the echoInput
206         */
207        @ParamAnnotation(flags = ParamFlags.USERREADONLY)
208        public String getEchoInput() {
209                return echoInput;
210        }
211
212        /**
213         * @param echoInput the echoInput to set
214         */
215        @ParamAnnotation
216        public void setEchoInput(String echoInput) {
217                this.echoInput = echoInput;
218        }
219
[88]220        @Override
221        protected void joinableInterrupt() {
[90]222                process.destroy();
223                Dispatching.drop(readerThread, this);
224                // finish();
[88]225        }
226
[90]227        @Override
[101]228        @ParamAnnotation(flags = ParamFlags.USERREADONLY)
[90]229        public String getName() {
230                return readerThread.getName();
231        }
232
233        /**
234         * @param name the name to set
235         */
236        @ParamAnnotation
237        public void setName(String name) {
238                readerThread.setName(name);
239        }
240
241        @Override
242        protected void joinableFinish() {
243
244        }
245
246        @Override
247        protected void joinableJoin() throws InterruptedException {
248                Dispatching.join(readerThread);
249        }
250
251        @Override
252        public void childChangedState(Joinable joinable, JoinableState state) {
253                proceedToState(state);
254        }
255
256
257
[88]258}
Note: See TracBrowser for help on using the repository browser.