View Javadoc

1   /**
2      This file is part of GoldenGate Project (named also GoldenGate or GG).
3   
4      Copyright 2009, Frederic Bregier, 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 GoldenGate Project is free software: you can redistribute it and/or 
9      modify it under the terms of the GNU General Public License as published 
10     by the Free Software Foundation, either version 3 of the License, or
11     (at your option) any later version.
12  
13     GoldenGate is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17  
18     You should have received a copy of the GNU General Public License
19     along with GoldenGate .  If not, see <http://www.gnu.org/licenses/>.
20   */
21  package openr66.client;
22  
23  
24  import goldengate.common.database.data.AbstractDbData.UpdatedInfo;
25  import goldengate.common.database.exception.GoldenGateDatabaseException;
26  import goldengate.common.logging.GgInternalLoggerFactory;
27  import openr66.commander.ClientRunner;
28  import openr66.context.ErrorCode;
29  import openr66.context.R66Result;
30  import openr66.context.task.exception.OpenR66RunnerErrorException;
31  import openr66.database.data.DbTaskRunner;
32  import openr66.protocol.configuration.Configuration;
33  import openr66.protocol.exception.OpenR66ProtocolNoConnectionException;
34  import openr66.protocol.exception.OpenR66ProtocolNotYetConnectionException;
35  import openr66.protocol.exception.OpenR66ProtocolPacketException;
36  import openr66.protocol.localhandler.LocalChannelReference;
37  import openr66.protocol.networkhandler.NetworkTransaction;
38  import openr66.protocol.utils.R66Future;
39  
40  /**
41   * Through API Transfer from a client with or without database connection,
42   * and enabling access to statistic of the transfer (unblocking transfer)
43   *
44   * @author Frederic Bregier
45   *
46   */
47  public abstract class ProgressBarTransfer extends AbstractTransfer {
48      protected final NetworkTransaction networkTransaction;
49      protected long INTERVALCALLBACK = 100;
50      protected long filesize = 0;
51  
52      public ProgressBarTransfer(R66Future future, String remoteHost,
53              String filename, String rulename, String fileinfo, boolean isMD5, int blocksize, long id,
54              NetworkTransaction networkTransaction, long callbackdelay) {
55          // no delay so starttime = null
56          super(ProgressBarTransfer.class,
57                  future, filename, rulename, fileinfo, isMD5, remoteHost, blocksize, id, null);
58          this.networkTransaction = networkTransaction;
59          this.INTERVALCALLBACK = callbackdelay;
60      }
61  
62      /**
63       * This function will be called every 100ms (or other fixed value in INTERVALCALLBACK). 
64       * Note that final rank is unknown. 
65       * @param currentBlock the current block rank (from 0 to n-1)
66       * @param blocksize blocksize of 1 block
67       */
68      abstract public void callBack(int currentBlock, int blocksize);
69      /**
70       * This function will be called only once when the transfer is over 
71       * @param success True if the transfer is successful
72       * @param currentBlock
73       * @param blocksize
74       */
75      abstract public void lastCallBack(boolean success, int currentBlock, int blocksize);
76      /**
77       * Prior to call this method, the pipeline and NetworkTransaction must have been initialized.
78       * It is the responsibility of the caller to finish all network resources.
79       */
80      public void run() {
81          if (logger == null) {
82              logger = GgInternalLoggerFactory.getLogger(ProgressBarTransfer.class);
83          }
84          DbTaskRunner taskRunner = this.initRequest();
85          ClientRunner runner = new ClientRunner(networkTransaction, taskRunner, future);
86          OpenR66ProtocolNotYetConnectionException exc = null;
87          for (int i = 0; i < Configuration.RETRYNB; i++) {
88              try {
89                  LocalChannelReference localChannelReference = runner.initRequest();
90                  try {
91                      localChannelReference.getFutureValidRequest().await();
92                  } catch (InterruptedException e) {
93                  }
94                  if ((! localChannelReference.getFutureValidRequest().isSuccess()) &&
95                          (localChannelReference.getFutureValidRequest().getResult().code ==
96                      ErrorCode.ServerOverloaded)) {
97                      switch (taskRunner.getUpdatedInfo()) {
98                          case DONE:
99                          case INERROR:
100                         case INTERRUPTED:
101                             break;
102                         default:
103                             runner.changeUpdatedInfo(UpdatedInfo.INERROR, ErrorCode.ServerOverloaded);
104                     }
105                     // redo if possible
106                     if (runner.incrementTaskRunerTry(taskRunner, Configuration.RETRYNB)) {
107                         try {
108                             Thread.sleep(Configuration.configuration.constraintLimitHandler.getSleepTime());
109                         } catch (InterruptedException e) {
110                         }
111                         i--;
112                         continue;
113                     } else {
114                         throw new OpenR66ProtocolNotYetConnectionException("End of retry on ServerOverloaded");
115                     }
116                 }
117                 this.filesize = future.filesize;
118                 while (!future.awaitUninterruptibly(INTERVALCALLBACK)) {
119                     if (future.isDone()) {
120                         break;
121                     }
122                     callBack(future.runner.getRank(), future.runner.getBlocksize());
123                 }
124                 runner.finishTransfer(false, localChannelReference);
125                 lastCallBack(future.isSuccess(), 
126                         future.runner.getRank(), future.runner.getBlocksize());
127                 exc = null;
128                 break;
129             } catch (OpenR66RunnerErrorException e) {
130                 logger.error("Cannot Transfer", e);
131                 future.setResult(new R66Result(e, null, true,
132                         ErrorCode.Internal, taskRunner));
133                 future.setFailure(e);
134                 lastCallBack(false, taskRunner.getRank(), taskRunner.getBlocksize());
135                 return;
136             } catch (OpenR66ProtocolNoConnectionException e) {
137                 logger.error("Cannot Connect", e);
138                 future.setResult(new R66Result(e, null, true,
139                         ErrorCode.ConnectionImpossible, taskRunner));
140                 // since no connection : just forget it
141                 if (nolog) {
142                     try {
143                         taskRunner.delete();
144                     } catch (GoldenGateDatabaseException e1) {
145                     }
146                 }
147                 future.setFailure(e);
148                 lastCallBack(false, taskRunner.getRank(), taskRunner.getBlocksize());
149                 return;
150             } catch (OpenR66ProtocolPacketException e) {
151                 logger.error("Bad Protocol", e);
152                 future.setResult(new R66Result(e, null, true,
153                         ErrorCode.TransferError, taskRunner));
154                 future.setFailure(e);
155                 lastCallBack(false, taskRunner.getRank(), taskRunner.getBlocksize());
156                 return;
157             } catch (OpenR66ProtocolNotYetConnectionException e) {
158                 logger.debug("Not Yet Connected", e);
159                 exc = e;
160                 continue;
161             }
162         }
163         if (exc!= null) {
164             taskRunner.setLocalChannelReference(new LocalChannelReference());
165             logger.error("Cannot Connect", exc);
166             future.setResult(new R66Result(exc, null, true,
167                     ErrorCode.ConnectionImpossible, taskRunner));
168             lastCallBack(false, taskRunner.getRank(), taskRunner.getBlocksize());
169             // since no connection : just forget it
170             if (nolog) {
171                 try {
172                     taskRunner.delete();
173                 } catch (GoldenGateDatabaseException e1) {
174                 }
175             }
176             future.setFailure(exc);
177             return;
178         }
179     }
180 }