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.server;
22  
23  import goldengate.common.database.exception.GoldenGateDatabaseNoConnectionException;
24  import goldengate.common.logging.GgInternalLogger;
25  import goldengate.common.logging.GgInternalLoggerFactory;
26  import goldengate.common.logging.GgSlf4JLoggerFactory;
27  
28  import java.net.SocketAddress;
29  import java.sql.Timestamp;
30  import java.text.ParseException;
31  import java.text.SimpleDateFormat;
32  import java.util.Date;
33  import java.util.GregorianCalendar;
34  
35  import openr66.configuration.FileBasedConfiguration;
36  import openr66.context.ErrorCode;
37  import openr66.context.R66FiniteDualStates;
38  import openr66.context.R66Result;
39  import openr66.database.DbConstant;
40  import openr66.database.data.DbHostAuth;
41  import openr66.database.data.DbTaskRunner;
42  import openr66.protocol.configuration.Configuration;
43  import openr66.protocol.exception.OpenR66ProtocolNoConnectionException;
44  import openr66.protocol.exception.OpenR66ProtocolPacketException;
45  import openr66.protocol.localhandler.LocalChannelReference;
46  import openr66.protocol.localhandler.packet.LocalPacketFactory;
47  import openr66.protocol.localhandler.packet.ValidPacket;
48  import openr66.protocol.networkhandler.NetworkTransaction;
49  import openr66.protocol.utils.ChannelUtils;
50  import openr66.protocol.utils.R66Future;
51  
52  import org.jboss.netty.channel.Channels;
53  import org.jboss.netty.logging.InternalLoggerFactory;
54  
55  /**
56   * Log Export from a local client without database connection
57   *
58   * @author Frederic Bregier
59   *
60   */
61  public class LogExport implements Runnable {
62      /**
63       * Internal Logger
64       */
65      static volatile GgInternalLogger logger;
66  
67      protected final R66Future future;
68      protected final boolean purgeLog;
69      protected final Timestamp start;
70      protected final Timestamp stop;
71      protected final boolean clean;
72      protected final NetworkTransaction networkTransaction;
73  
74      public LogExport(R66Future future, boolean purgeLog, boolean clean,
75              Timestamp start, Timestamp stop,
76              NetworkTransaction networkTransaction) {
77          this.future = future;
78          this.purgeLog = purgeLog;
79          this.clean = clean;
80          this.start = start;
81          this.stop = stop;
82          this.networkTransaction = networkTransaction;
83      }
84      /**
85       * Prior to call this method, the pipeline and NetworkTransaction must have been initialized.
86       * It is the responsibility of the caller to finish all network resources.
87       */
88      public void run() {
89          if (logger == null) {
90              logger = GgInternalLoggerFactory.getLogger(LogExport.class);
91          }
92          String lstart = (start != null) ? start.toString() : null;
93          String lstop  = (stop != null) ? stop.toString() : null;
94          byte type = (purgeLog) ? LocalPacketFactory.LOGPURGEPACKET : LocalPacketFactory.LOGPACKET;
95          ValidPacket valid = new ValidPacket(lstart, lstop, type);
96          DbHostAuth host = Configuration.configuration.HOST_SSLAUTH;
97          SocketAddress socketAddress = host.getSocketAddress();
98          boolean isSSL = host.isSsl();
99  
100         // first clean if ask
101         if (clean) {
102             // Update all UpdatedInfo to DONE
103             // where GlobalLastStep = ALLDONETASK and status = CompleteOk
104             try {
105                 DbTaskRunner.changeFinishedToDone(DbConstant.admin.session);
106             } catch (GoldenGateDatabaseNoConnectionException e) {
107                 logger.warn("Clean cannot be done {}", e.getMessage());
108             }
109         }
110         LocalChannelReference localChannelReference = networkTransaction
111             .createConnectionWithRetry(socketAddress, isSSL, future);
112         socketAddress = null;
113         if (localChannelReference == null) {
114             host = null;
115             logger.error("Cannot Connect");
116             future.setResult(new R66Result(
117                     new OpenR66ProtocolNoConnectionException("Cannot connect to server"),
118                     null, true, ErrorCode.Internal, null));
119             future.setFailure(future.getResult().exception);
120             return;
121         }
122         localChannelReference.sessionNewState(R66FiniteDualStates.VALIDOTHER);
123         try {
124             ChannelUtils.writeAbstractLocalPacket(localChannelReference, valid, false);
125         } catch (OpenR66ProtocolPacketException e) {
126             logger.error("Bad Protocol", e);
127             Channels.close(localChannelReference.getLocalChannel());
128             localChannelReference = null;
129             host = null;
130             valid = null;
131             future.setResult(new R66Result(e, null, true,
132                     ErrorCode.TransferError, null));
133             future.setFailure(e);
134             return;
135         }
136         host = null;
137         future.awaitUninterruptibly();
138         logger.info("Request done with "+(future.isSuccess()?"success":"error"));
139         Channels.close(localChannelReference.getLocalChannel());
140         localChannelReference = null;
141     }
142 
143     protected static boolean spurgeLog = false;
144     protected static Timestamp sstart = null;
145     protected static Timestamp sstop = null;
146     protected static boolean sclean = false;
147 
148     private static SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmssSSS");
149     private static Timestamp fixDate(String sdate) {
150         Timestamp tdate = null;
151         String date = sdate.replaceAll("/|:|\\.| |-", "");
152         if (date.length() > 0) {
153             if (date.length() < 15) {
154                 int len = date.length();
155                 date += "000000000000000".substring(len);
156             }
157             try {
158                 Date ddate = format.parse(date);
159                 tdate = new Timestamp(ddate.getTime());
160             } catch (ParseException e) {
161                 logger.debug("start {}",e.getMessage());
162             }
163         }
164         return tdate;
165     }
166     private static Timestamp fixDate(String sdate, Timestamp before) {
167         Timestamp tdate = null;
168         String date = sdate.replaceAll("/|:|\\.| |-", "");
169         if (date.length() > 0) {
170             if (date.length() < 15) {
171                 int len = date.length();
172                 date += "000000000000000".substring(len);
173             }
174             try {
175                 Date ddate = format.parse(date);
176                 if (before != null) {
177                     Date bef = new Date(before.getTime());
178                     if (bef.compareTo(ddate) >= 0) {
179                         ddate = new Date(bef.getTime()+1000*3600*24-1);
180                     }
181                 }
182                 tdate = new Timestamp(ddate.getTime());
183             } catch (ParseException e) {
184                 logger.debug("start {}",e.getMessage());
185             }
186         }
187         return tdate;
188     }
189     private static Timestamp getTodayMidnight() {
190         GregorianCalendar calendar = new GregorianCalendar();
191         calendar.set(GregorianCalendar.HOUR_OF_DAY, 0);
192         calendar.set(GregorianCalendar.MINUTE, 0);
193         calendar.set(GregorianCalendar.SECOND, 0);
194         calendar.set(GregorianCalendar.MILLISECOND, 0);
195         return new Timestamp(calendar.getTimeInMillis());
196     }
197     protected static boolean getParams(String [] args) {
198         if (args.length < 1) {
199             logger.error("Need at least the configuration file as first argument then optionally\n" +
200             		"    -purge\n" +
201             		"    -clean\n" +
202             		"    -start timestamp in format yyyyMMddHHmmssSSS possibly truncated and where one of ':-. ' can be separators\n" +
203             		"    -stop timestamp in same format than start\n" +
204             		"If not start and no stop are given, stop is Today Midnight (00:00:00)\n" +
205             		"If start is equals or greater than stop, stop is start+24H");
206             return false;
207         }
208         if (! FileBasedConfiguration
209                 .setClientConfigurationFromXml(Configuration.configuration, args[0])) {
210             logger.error("Need at least the configuration file as first argument then optionally\n" +
211                     "    -purge\n" +
212                     "    -clean\n" +
213                     "    -start timestamp in format yyyyMMddHHmmssSSS possibly truncated and where one of ':-. ' can be separators\n" +
214                     "    -stop timestamp in same format than start\n" +
215                     "If not start and no stop are given, stop is Today Midnight (00:00:00)\n" +
216                     "If start is equals or greater than stop, stop is start+24H");
217             return false;
218         }
219         String ssstart = null;
220         String ssstop = null;
221         for (int i = 1; i < args.length; i++) {
222             if (args[i].equalsIgnoreCase("-purge")) {
223                 spurgeLog = true;
224             } else if (args[i].equalsIgnoreCase("-clean")) {
225                 sclean = true;
226             } else if (args[i].equalsIgnoreCase("-start")) {
227                 i++;
228                 ssstart = args[i];
229             } else if (args[i].equalsIgnoreCase("-stop")) {
230                 i++;
231                 ssstop = args[i];
232             }
233         }
234         if (ssstart != null) {
235             Timestamp tstart = fixDate(ssstart);
236             if (tstart != null) {
237                 sstart = tstart;
238             }
239         }
240         if (ssstop != null) {
241             Timestamp tstop = fixDate(ssstop, sstart);
242             if (tstop != null) {
243                 sstop = tstop;
244             }
245         }
246         if (ssstart == null && ssstop == null) {
247             sstop = getTodayMidnight();
248         }
249         return true;
250     }
251 
252     public static void main(String[] args) {
253         InternalLoggerFactory.setDefaultFactory(new GgSlf4JLoggerFactory(null));
254         if (logger == null) {
255             logger = GgInternalLoggerFactory.getLogger(LogExport.class);
256         }
257         if (! getParams(args)) {
258             logger.error("Wrong initialization");
259             if (DbConstant.admin != null && DbConstant.admin.isConnected) {
260                 DbConstant.admin.close();
261             }
262             System.exit(1);
263         }
264         long time1 = System.currentTimeMillis();
265         R66Future future = new R66Future(true);
266 
267         Configuration.configuration.pipelineInit();
268         NetworkTransaction networkTransaction = new NetworkTransaction();
269         try {
270             LogExport transaction = new LogExport(future,
271                     spurgeLog, sclean, sstart, sstop,
272                     networkTransaction);
273             transaction.run();
274             future.awaitUninterruptibly();
275             long time2 = System.currentTimeMillis();
276             long delay = time2 - time1;
277             R66Result result = future.getResult();
278             if (future.isSuccess()) {
279                 if (result.code == ErrorCode.Warning) {
280                     logger.warn("WARNED on file:\n    " +
281                             (result.other != null? ((ValidPacket)result.other).getSheader() :
282                                 "no file")
283                             +"\n    delay: "+delay);
284                 } else {
285                     logger.warn("SUCCESS on Final file:\n    " +
286                             (result.other != null? ((ValidPacket)result.other).getSheader() :
287                             "no file")
288                             +"\n    delay: "+delay);
289                 }
290             } else {
291                 if (result.code == ErrorCode.Warning) {
292                     logger.warn("Transfer is\n    WARNED", future.getCause());
293                     networkTransaction.closeAll();
294                     System.exit(result.code.ordinal());
295                 } else {
296                     logger.error("Transfer in\n    FAILURE", future.getCause());
297                     networkTransaction.closeAll();
298                     System.exit(result.code.ordinal());
299                 }
300             }
301         } finally {
302             networkTransaction.closeAll();
303         }
304     }
305 
306 }