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.gateway.ftp.snmp;
21  
22  import io.netty.handler.traffic.TrafficCounter;
23  import org.waarp.common.command.ReplyCode;
24  import org.waarp.common.database.DbPreparedStatement;
25  import org.waarp.common.database.DbSession;
26  import org.waarp.common.database.data.AbstractDbData.UpdatedInfo;
27  import org.waarp.common.database.exception.WaarpDatabaseException;
28  import org.waarp.common.database.exception.WaarpDatabaseNoConnectionException;
29  import org.waarp.common.database.exception.WaarpDatabaseSqlException;
30  import org.waarp.common.logging.WaarpLogger;
31  import org.waarp.common.logging.WaarpLoggerFactory;
32  import org.waarp.gateway.ftp.config.FileBasedConfiguration;
33  import org.waarp.gateway.ftp.database.DbConstantFtp;
34  import org.waarp.gateway.ftp.database.data.DbTransferLog;
35  import org.waarp.gateway.ftp.snmp.FtpPrivateMib.MibLevel;
36  import org.waarp.gateway.ftp.snmp.FtpPrivateMib.WaarpDetailedValuesIndex;
37  import org.waarp.gateway.ftp.snmp.FtpPrivateMib.WaarpErrorValuesIndex;
38  import org.waarp.gateway.ftp.snmp.FtpPrivateMib.WaarpGlobalValuesIndex;
39  import org.waarp.snmp.WaarpSnmpAgent;
40  import org.waarp.snmp.interf.WaarpInterfaceMonitor;
41  
42  /**
43   * SNMP Monitoring class for FTP Exec
44   */
45  public class FtpMonitoring implements WaarpInterfaceMonitor {
46    /**
47     * Internal Logger
48     */
49    private static final WaarpLogger logger =
50        WaarpLoggerFactory.getLogger(FtpMonitoring.class);
51  
52    public WaarpSnmpAgent agent;
53  
54    // global informations
55    public long nbNetworkConnection;
56    public long nbThread;
57  
58    // Internal data
59    private final DbSession dbSession;
60    private final TrafficCounter trafficCounter =
61        FileBasedConfiguration.fileBasedConfiguration.getFtpInternalConfiguration()
62                                                     .getGlobalTrafficShapingHandler()
63                                                     .trafficCounter();
64  
65    public long nbCountInfoUnknown;
66    public long nbCountInfoNotUpdated;
67    public long nbCountInfoInterrupted;
68    public long nbCountInfoToSubmit;
69    public long nbCountInfoError;
70    public long nbCountInfoRunning;
71    public long nbCountInfoDone;
72  
73    public long nbInActiveTransfer;
74    public long nbOutActiveTransfer;
75    public long lastInActiveTransfer = System.currentTimeMillis();
76    public long lastOutActiveTransfer = System.currentTimeMillis();
77    public long nbInTotalTransfer;
78    public long nbOutTotalTransfer;
79    public long nbInErrorTransfer;
80    public long nbOutErrorTransfer;
81  
82    public long nbCountAllTransfer;
83  
84    // Info for other reasons than transfers
85    private final long[] replyInfoNotransfers =
86        new long[WaarpDetailedValuesIndex.reply_350.ordinal() + 1];
87    // Error for other reasons than transfers
88    private final long[] replyErrorNotransfers =
89        new long[WaarpErrorValuesIndex.reply_553.ordinal() + 1];
90  
91    {
92      for (int i = 0; i <= WaarpDetailedValuesIndex.reply_350.ordinal(); i++) {
93        replyInfoNotransfers[i] = 0;
94      }
95      for (int i = 0; i <= WaarpErrorValuesIndex.reply_553.ordinal(); i++) {
96        replyErrorNotransfers[i] = 0;
97      }
98    }
99  
100   // Overall status including past, future and current transfers
101   private DbPreparedStatement countInfo;
102 
103   // Current situation of all transfers, running or not
104   private DbPreparedStatement countInActiveTransfer;
105   private DbPreparedStatement countOutActiveTransfer;
106   private DbPreparedStatement countInTotalTransfer;
107   private DbPreparedStatement countOutTotalTransfer;
108   private DbPreparedStatement countInErrorTransfer;
109   private DbPreparedStatement countOutErrorTransfer;
110   private DbPreparedStatement countAllTransfer;
111   // Error Status on all transfers
112   private DbPreparedStatement countStatus;
113 
114   /**
115    * @param session
116    */
117   public FtpMonitoring(final DbSession session) {
118     if (session != null) {
119       dbSession = session;
120     } else {
121       dbSession = DbConstantFtp.gatewayAdmin.getSession();
122     }
123     initialize();
124   }
125 
126   @Override
127   public final void setAgent(final WaarpSnmpAgent agent) {
128     this.agent = agent;
129     lastInActiveTransfer = this.agent.getUptimeSystemTime();
130     lastOutActiveTransfer = this.agent.getUptimeSystemTime();
131   }
132 
133   @Override
134   public final void initialize() {
135     logger.debug("Initialize monitoring");
136     try {
137       // Overall status including past, future and current transfers
138       countInfo = DbTransferLog.getCountInfoPrepareStatement(dbSession);
139       // Count of Active/All In/Out transfers
140       countInActiveTransfer =
141           DbTransferLog.getCountInOutRunningPrepareStatement(dbSession, true,
142                                                              true);
143       countOutActiveTransfer =
144           DbTransferLog.getCountInOutRunningPrepareStatement(dbSession, false,
145                                                              true);
146       countInTotalTransfer =
147           DbTransferLog.getCountInOutRunningPrepareStatement(dbSession, true,
148                                                              false);
149       countOutTotalTransfer =
150           DbTransferLog.getCountInOutRunningPrepareStatement(dbSession, false,
151                                                              false);
152 
153       countInErrorTransfer =
154           DbTransferLog.getCountInOutErrorPrepareStatement(dbSession, true);
155       countOutErrorTransfer =
156           DbTransferLog.getCountInOutErrorPrepareStatement(dbSession, false);
157       // All
158       countAllTransfer = DbTransferLog.getCountAllPrepareStatement(dbSession);
159       // Error Status on all transfers
160       countStatus = DbTransferLog.getCountStatusPrepareStatement(dbSession);
161     } catch (final WaarpDatabaseException ignored) {
162       // nothing
163     }
164   }
165 
166   @Override
167   public final void releaseResources() {
168     try {
169       logger.debug("Release monitoring");
170       // Overall status including past, future and current transfers
171       countInfo.realClose();
172 
173       countInActiveTransfer.realClose();
174       countOutActiveTransfer.realClose();
175       countInTotalTransfer.realClose();
176       countOutTotalTransfer.realClose();
177       countInErrorTransfer.realClose();
178       countOutErrorTransfer.realClose();
179 
180       countAllTransfer.realClose();
181       // Error Status on all transfers
182       countStatus.realClose();
183     } catch (final NullPointerException ignored) {
184       // nothing
185     }
186   }
187 
188   private static final int REF421 =
189       ReplyCode.REPLY_421_SERVICE_NOT_AVAILABLE_CLOSING_CONTROL_CONNECTION.ordinal();
190 
191   /**
192    * Update the reply code counter for other operations than a transfer
193    *
194    * @param code
195    */
196   public final void updateCodeNoTransfer(final ReplyCode code) {
197     int i = code.ordinal();
198     if (i >= REF421) {
199       i -= REF421;
200       replyErrorNotransfers[i]++;
201     } else {
202       replyInfoNotransfers[i]++;
203     }
204   }
205 
206   /**
207    * Update the last InBound connection time
208    */
209   public final void updateLastInBound() {
210     lastInActiveTransfer = System.currentTimeMillis();
211   }
212 
213   /**
214    * Update the last OutBound connection time
215    */
216   public final void updateLastOutBand() {
217     lastOutActiveTransfer = System.currentTimeMillis();
218   }
219 
220   /**
221    * Update the value for one particular MIB entry
222    *
223    * @param type
224    * @param entry
225    */
226   public final void run(final int type, final int entry) {
227     final long nbMs =
228         FileBasedConfiguration.fileBasedConfiguration.getAgentSnmp()
229                                                      .getUptime() + 100;
230     final MibLevel level = MibLevel.values()[type];
231     switch (level) {
232       case globalInfo:// Global
233         if (((FtpPrivateMib) agent.getMib()).rowGlobal != null) {
234           run(nbMs, WaarpGlobalValuesIndex.values()[entry]);
235         }
236         return;
237       case detailedInfo:// Detailed
238         if (((FtpPrivateMib) agent.getMib()).rowDetailed != null) {
239           run(nbMs, WaarpDetailedValuesIndex.values()[entry]);
240         }
241         return;
242       case errorInfo:// Error
243         if (((FtpPrivateMib) agent.getMib()).rowError != null) {
244           run(nbMs, WaarpErrorValuesIndex.values()[entry]);
245         }
246         return;
247       default:
248         break;
249     }
250   }
251 
252   /**
253    * Update a value in Global MIB part
254    *
255    * @param rank
256    * @param value
257    */
258   protected final void updateGlobalValue(final int rank, final long value) {
259     ((FtpPrivateMib) agent.getMib()).rowGlobal.setValue(rank, value);
260   }
261 
262   /**
263    * Update a value in Detailed MIB part
264    *
265    * @param rank
266    * @param value
267    */
268   protected final void updateDetailedValue(final int rank, final long value) {
269     ((FtpPrivateMib) agent.getMib()).rowDetailed.setValue(rank, value);
270   }
271 
272   /**
273    * Update a value in Error MIB part
274    *
275    * @param rank
276    * @param value
277    */
278   protected final void updateErrorValue(final int rank, final long value) {
279     ((FtpPrivateMib) agent.getMib()).rowError.setValue(rank, value);
280   }
281 
282   /**
283    * Update a value in Global MIB part
284    *
285    * @param nbMs
286    * @param entry
287    */
288   protected final void run(final long nbMs,
289                            final WaarpGlobalValuesIndex entry) {
290     synchronized (trafficCounter) {
291       long val;
292       final long limitDate = System.currentTimeMillis() - nbMs;
293       // Global
294       try {
295         switch (entry) {
296           case applUptime:
297           case applOperStatus:
298           case applLastChange:
299           case memoryTotal:
300           case memoryFree:
301           case memoryUsed:
302             return;
303           case applInboundAssociations:
304             DbTransferLog.finishSelectOrCountPrepareStatement(
305                 countInActiveTransfer, limitDate);
306             nbInActiveTransfer = DbTransferLog.getResultCountPrepareStatement(
307                 countInActiveTransfer);
308             updateGlobalValue(entry.ordinal(), nbInActiveTransfer);
309             return;
310           case applOutboundAssociations:
311             DbTransferLog.finishSelectOrCountPrepareStatement(
312                 countOutActiveTransfer, limitDate);
313             nbOutActiveTransfer = DbTransferLog.getResultCountPrepareStatement(
314                 countOutActiveTransfer);
315             updateGlobalValue(entry.ordinal(), nbOutActiveTransfer);
316             return;
317           case applAccumInboundAssociations:
318             DbTransferLog.finishSelectOrCountPrepareStatement(
319                 countInTotalTransfer, limitDate);
320             nbInTotalTransfer = DbTransferLog.getResultCountPrepareStatement(
321                 countInTotalTransfer);
322             updateGlobalValue(entry.ordinal(), nbInTotalTransfer);
323             return;
324           case applAccumOutboundAssociations:
325             DbTransferLog.finishSelectOrCountPrepareStatement(
326                 countOutTotalTransfer, limitDate);
327             nbOutTotalTransfer = DbTransferLog.getResultCountPrepareStatement(
328                 countOutTotalTransfer);
329             updateGlobalValue(entry.ordinal(), nbOutTotalTransfer);
330             return;
331           case applLastInboundActivity:
332             val = (lastInActiveTransfer - agent.getUptimeSystemTime()) / 10;
333             if (val < 0) {
334               val = 0;
335             }
336             updateGlobalValue(entry.ordinal(), val);
337             return;
338           case applLastOutboundActivity:
339             val = (lastOutActiveTransfer - agent.getUptimeSystemTime()) / 10;
340             if (val < 0) {
341               val = 0;
342             }
343             updateGlobalValue(entry.ordinal(), val);
344             return;
345           case applRejectedInboundAssociations:
346             DbTransferLog.finishSelectOrCountPrepareStatement(
347                 countInErrorTransfer, limitDate);
348             nbInErrorTransfer = DbTransferLog.getResultCountPrepareStatement(
349                 countInErrorTransfer);
350             updateGlobalValue(entry.ordinal(), nbInErrorTransfer);
351             return;
352           case applFailedOutboundAssociations:
353             DbTransferLog.finishSelectOrCountPrepareStatement(
354                 countOutErrorTransfer, limitDate);
355             nbOutErrorTransfer = DbTransferLog.getResultCountPrepareStatement(
356                 countOutErrorTransfer);
357             updateGlobalValue(entry.ordinal(), nbOutErrorTransfer);
358             return;
359           case applInboundBandwidthKBS:
360             val = trafficCounter.lastReadThroughput() >> 10;// B/s -> KB/s
361             updateGlobalValue(entry.ordinal(), val);
362             return;
363           case applOutboundBandwidthKBS:
364             val = trafficCounter.lastWriteThroughput() >> 10;
365             updateGlobalValue(entry.ordinal(), val);
366             return;
367           case nbInfoUnknown:
368             nbCountInfoUnknown =
369                 DbTransferLog.getResultCountPrepareStatement(countInfo,
370                                                              UpdatedInfo.UNKNOWN,
371                                                              limitDate);
372             updateGlobalValue(entry.ordinal(), nbCountInfoUnknown);
373             return;
374           case nbInfoNotUpdated:
375             nbCountInfoNotUpdated =
376                 DbTransferLog.getResultCountPrepareStatement(countInfo,
377                                                              UpdatedInfo.NOTUPDATED,
378                                                              limitDate);
379             updateGlobalValue(entry.ordinal(), nbCountInfoNotUpdated);
380             return;
381           case nbInfoInterrupted:
382             nbCountInfoInterrupted =
383                 DbTransferLog.getResultCountPrepareStatement(countInfo,
384                                                              UpdatedInfo.INTERRUPTED,
385                                                              limitDate);
386             updateGlobalValue(entry.ordinal(), nbCountInfoInterrupted);
387             return;
388           case nbInfoToSubmit:
389             nbCountInfoToSubmit =
390                 DbTransferLog.getResultCountPrepareStatement(countInfo,
391                                                              UpdatedInfo.TOSUBMIT,
392                                                              limitDate);
393             updateGlobalValue(entry.ordinal(), nbCountInfoToSubmit);
394             return;
395           case nbInfoError:
396             nbCountInfoError =
397                 DbTransferLog.getResultCountPrepareStatement(countInfo,
398                                                              UpdatedInfo.INERROR,
399                                                              limitDate);
400             updateGlobalValue(entry.ordinal(), nbCountInfoError);
401             return;
402           case nbInfoRunning:
403             nbCountInfoRunning =
404                 DbTransferLog.getResultCountPrepareStatement(countInfo,
405                                                              UpdatedInfo.RUNNING,
406                                                              limitDate);
407             updateGlobalValue(entry.ordinal(), nbCountInfoRunning);
408             return;
409           case nbInfoDone:
410             nbCountInfoDone =
411                 DbTransferLog.getResultCountPrepareStatement(countInfo,
412                                                              UpdatedInfo.DONE,
413                                                              limitDate);
414             updateGlobalValue(entry.ordinal(), nbCountInfoDone);
415             return;
416           case nbAllTransfer:
417             DbTransferLog.finishSelectOrCountPrepareStatement(countAllTransfer,
418                                                               limitDate);
419             nbCountAllTransfer =
420                 DbTransferLog.getResultCountPrepareStatement(countAllTransfer);
421             updateGlobalValue(entry.ordinal(), nbCountAllTransfer);
422             return;
423           case nbThreads:
424             nbThread = Thread.activeCount();
425             updateGlobalValue(entry.ordinal(), nbThread);
426             return;
427           case nbNetworkConnection:
428             nbNetworkConnection =
429                 FileBasedConfiguration.fileBasedConfiguration.getFtpInternalConfiguration()
430                                                              .getNumberSessions();
431             updateGlobalValue(entry.ordinal(), nbNetworkConnection);
432         }
433       } catch (final WaarpDatabaseNoConnectionException ignored) {
434         // nothing
435       } catch (final WaarpDatabaseSqlException ignored) {
436         // nothing
437       }
438     }
439   }
440 
441   /**
442    * Update a value in Detailed MIB part
443    *
444    * @param nbMs
445    * @param entry
446    */
447   protected final void run(final long nbMs,
448                            final WaarpDetailedValuesIndex entry) {
449     synchronized (trafficCounter) {
450       final long limitDate = System.currentTimeMillis() - nbMs;
451       // Detailed
452       final long value =
453           DbTransferLog.getResultCountPrepareStatement(countStatus, entry.code,
454                                                        limitDate);
455       updateDetailedValue(entry.ordinal(),
456                           value + replyInfoNotransfers[entry.ordinal()]);
457     }
458   }
459 
460   /**
461    * Update a value in Error MIB part
462    *
463    * @param nbMs
464    * @param entry
465    */
466   protected final void run(final long nbMs, final WaarpErrorValuesIndex entry) {
467     synchronized (trafficCounter) {
468       final long limitDate = System.currentTimeMillis() - nbMs;
469       // Error
470       final long value =
471           DbTransferLog.getResultCountPrepareStatement(countStatus, entry.code,
472                                                        limitDate);
473       updateErrorValue(entry.ordinal(),
474                        value + replyErrorNotransfers[entry.ordinal()]);
475     }
476   }
477 
478 }