View Javadoc
1   /*
2    * This file is part of Waarp Project (named also Waarp or GG).
3    *
4    *  Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
5    *  tags. See the COPYRIGHT.txt in the distribution for a full listing of
6    * individual contributors.
7    *
8    *  All Waarp Project is free software: you can redistribute it and/or
9    * modify it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License, or (at your
11   * option) any later version.
12   *
13   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
14   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License along with
18   * Waarp . If not, see <http://www.gnu.org/licenses/>.
19   */
20  package org.waarp.openr66.client;
21  
22  import org.waarp.common.database.exception.WaarpDatabaseException;
23  import org.waarp.common.logging.SysErrLogger;
24  import org.waarp.common.logging.WaarpLoggerFactory;
25  import org.waarp.common.logging.WaarpSlf4JLoggerFactory;
26  import org.waarp.common.utility.WaarpSystemUtil;
27  import org.waarp.openr66.client.utils.OutputFormat;
28  import org.waarp.openr66.commander.ClientRunner;
29  import org.waarp.openr66.context.ErrorCode;
30  import org.waarp.openr66.context.R66Result;
31  import org.waarp.openr66.context.task.exception.OpenR66RunnerErrorException;
32  import org.waarp.openr66.database.data.DbTaskRunner;
33  import org.waarp.openr66.protocol.configuration.Configuration;
34  import org.waarp.openr66.protocol.configuration.Messages;
35  import org.waarp.openr66.protocol.exception.OpenR66ProtocolNoConnectionException;
36  import org.waarp.openr66.protocol.exception.OpenR66ProtocolNotYetConnectionException;
37  import org.waarp.openr66.protocol.exception.OpenR66ProtocolPacketException;
38  import org.waarp.openr66.protocol.localhandler.LocalChannelReference;
39  import org.waarp.openr66.protocol.networkhandler.NetworkTransaction;
40  import org.waarp.openr66.protocol.utils.R66Future;
41  
42  import static org.waarp.common.database.DbConstant.*;
43  
44  /**
45   * Direct Transfer from a client with or without database connection
46   */
47  public class DirectTransfer extends AbstractTransfer {
48    protected final NetworkTransaction networkTransaction;
49  
50    protected boolean limitRetryConnection = true;
51  
52    public DirectTransfer(final R66Future future, final String remoteHost,
53                          final String filename, final String rulename,
54                          final String transferInfo, final boolean isMD5,
55                          final int blocksize, final long id,
56                          final NetworkTransaction networkTransaction) {
57      // no starttime since it is direct (blocking request, no delay)
58      super(DirectTransfer.class, future, filename, rulename, transferInfo, isMD5,
59            remoteHost, blocksize, id, null);
60      this.networkTransaction = networkTransaction;
61    }
62  
63    /**
64     * @return True if this DirectTransfer should limit the retry of connection
65     */
66    public boolean isLimitRetryConnection() {
67      return limitRetryConnection;
68    }
69  
70    /**
71     * @param limitRetryConnection True (default) for limited retry on
72     *     connection, False to have no limit
73     */
74    public void setLimitRetryConnection(final boolean limitRetryConnection) {
75      this.limitRetryConnection = limitRetryConnection;
76    }
77  
78    /**
79     * Prior to call this method, the pipeline and NetworkTransaction must have
80     * been initialized. It is the
81     * responsibility of the caller to finish all network resources.
82     */
83    @Override
84    public void run() {
85      if (logger == null) {
86        logger = WaarpLoggerFactory.getLogger(DirectTransfer.class);
87      }
88      final DbTaskRunner taskRunner = initRequest();
89      if (taskRunner == null) {
90        // already an error from there
91        return;
92      }
93      final ClientRunner runner =
94          new ClientRunner(networkTransaction, taskRunner, future);
95      // If retry indefinitely is useful
96      runner.setLimitRetryConnection(isLimitRetryConnection());
97      OpenR66ProtocolNotYetConnectionException exc = null;
98      for (int i = 0; i < Configuration.RETRYNB; i++) {
99        try {
100         runner.runTransfer();
101         exc = null;
102         break;
103       } catch (final OpenR66RunnerErrorException e) {
104         logger.info("Cannot Transfer", e);
105         future.setResult(
106             new R66Result(e, null, true, ErrorCode.Internal, taskRunner));
107         future.setFailure(e);
108         return;
109       } catch (final OpenR66ProtocolNoConnectionException e) {
110         logger.info("Cannot Connect", e);
111         future.setResult(
112             new R66Result(e, null, true, ErrorCode.ConnectionImpossible,
113                           taskRunner));
114         finalizeInErrorTransferRequest(runner, taskRunner,
115                                        ErrorCode.ConnectionImpossible);
116         // since no connection : just forget it
117         if (nolog || taskRunner.shallIgnoreSave()) {
118           try {
119             taskRunner.delete();
120           } catch (final WaarpDatabaseException ignored) {
121             // nothing
122           }
123         }
124         future.setFailure(e);
125         return;
126       } catch (final OpenR66ProtocolPacketException e) {
127         logger.info("Bad Protocol", e);
128         future.setResult(
129             new R66Result(e, null, true, ErrorCode.TransferError, taskRunner));
130         future.setFailure(e);
131         return;
132       } catch (final OpenR66ProtocolNotYetConnectionException e) {
133         logger.debug("Not Yet Connected", e);
134         exc = e;
135       }
136     }
137     if (exc != null) {
138       taskRunner.setLocalChannelReference(new LocalChannelReference());
139       logger.info("Cannot Connect", exc);
140       future.setResult(
141           new R66Result(exc, null, true, ErrorCode.ConnectionImpossible,
142                         taskRunner));
143       // since no connection : just forget it
144       if (nolog || taskRunner.shallIgnoreSave()) {
145         try {
146           taskRunner.delete();
147         } catch (final WaarpDatabaseException ignored) {
148           // nothing
149         }
150       }
151       future.setFailure(exc);
152     }
153   }
154 
155   public static void main(final String[] args) {
156     WaarpLoggerFactory.setDefaultFactoryIfNotSame(
157         new WaarpSlf4JLoggerFactory(null));
158     if (logger == null) {
159       logger = WaarpLoggerFactory.getLogger(DirectTransfer.class);
160     }
161     if (!getParams(args, false)) {
162       logger.error(Messages.getString("Configuration.WrongInit")); //$NON-NLS-1$
163       if (!OutputFormat.isQuiet()) {
164         SysErrLogger.FAKE_LOGGER.sysout(
165             Messages.getString("Configuration.WrongInit")); //$NON-NLS-1$
166       }
167       if (admin != null) {
168         admin.close();
169       }
170       WaarpSystemUtil.systemExit(2);
171       return;
172     }
173     final long time1 = System.currentTimeMillis();
174     final R66Future future = new R66Future(true);
175 
176     Configuration.configuration.pipelineInit();
177     final NetworkTransaction networkTransaction = new NetworkTransaction();
178     try {
179       final DirectTransfer transaction =
180           new DirectTransfer(future, rhost, localFilename, rule, transferInfo,
181                              ismd5, block, idt, networkTransaction);
182       transaction.transferArgs.setFollowId(sFollowId);
183       transaction.normalInfoAsWarn = snormalInfoAsWarn;
184       logger.debug("rhost: {}:{}", rhost,
185                    transaction.transferArgs.getRemoteHost());
186       transaction.run();
187       future.awaitOrInterruptible();
188       final long time2 = System.currentTimeMillis();
189       logger.debug("finish transfer: {}", future.isSuccess());
190       final long delay = time2 - time1;
191       final R66Result result = future.getResult();
192       final OutputFormat outputFormat =
193           new OutputFormat(DirectTransfer.class.getSimpleName(), args);
194       if (future.isSuccess()) {
195         prepareOkOutputFormat(delay, result, outputFormat);
196         if (transaction.normalInfoAsWarn) {
197           logger.warn(outputFormat.loggerOut());
198         } else if (logger.isInfoEnabled()) {
199           logger.info(outputFormat.loggerOut());
200         }
201         if (!OutputFormat.isQuiet()) {
202           outputFormat.sysout();
203         }
204         if (nolog) {
205           // In case of success, delete the runner
206           try {
207             result.getRunner().delete();
208           } catch (final WaarpDatabaseException e) {
209             logger.warn("Cannot apply nolog to     " +
210                         result.getRunner().toShortString() + " : {}",
211                         e.getMessage());
212           }
213         }
214         if (WaarpSystemUtil.isJunit()) {
215           return;
216         }
217         networkTransaction.closeAll();
218         WaarpSystemUtil.systemExit(0);
219       } else {
220         if (result == null || result.getRunner() == null) {
221           prepareKoOutputFormat(future, outputFormat);
222           if (!OutputFormat.isQuiet()) {
223             outputFormat.sysout();
224           }
225           if (WaarpSystemUtil.isJunit()) {
226             return;
227           }
228           networkTransaction.closeAll();
229           WaarpSystemUtil.systemExit(ErrorCode.Unknown.ordinal());
230           return;
231         }
232         prepareKoOutputFormat(future, result, outputFormat);
233         if (!OutputFormat.isQuiet()) {
234           outputFormat.sysout();
235         }
236         if (WaarpSystemUtil.isJunit()) {
237           return;
238         }
239         networkTransaction.closeAll();
240         WaarpSystemUtil.systemExit(result.getCode().ordinal());
241       }
242     } catch (final Throwable e) {
243       logger.error("Exception", e);
244     } finally {
245       logger.debug("finish transfer: {}:{}", future.isDone(),
246                    future.isSuccess());
247       if (!WaarpSystemUtil.isJunit()) {
248         networkTransaction.closeAll();
249         // In case something wrong append
250         if (future.isDone() && future.isSuccess()) {
251           WaarpSystemUtil.systemExit(0);
252         } else {
253           WaarpSystemUtil.systemExit(66);
254         }
255       }
256     }
257   }
258 
259 }