001: /*_############################################################################
002: _##
003: _## SNMP4J - TableUtils.java
004: _##
005: _## Copyright (C) 2003-2008 Frank Fock and Jochen Katz (SNMP4J.org)
006: _##
007: _## Licensed under the Apache License, Version 2.0 (the "License");
008: _## you may not use this file except in compliance with the License.
009: _## You may obtain a copy of the License at
010: _##
011: _## http://www.apache.org/licenses/LICENSE-2.0
012: _##
013: _## Unless required by applicable law or agreed to in writing, software
014: _## distributed under the License is distributed on an "AS IS" BASIS,
015: _## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016: _## See the License for the specific language governing permissions and
017: _## limitations under the License.
018: _##
019: _##########################################################################*/
020:
021: package org.snmp4j.util;
022:
023: import java.util.*;
024:
025: import org.snmp4j.log.*;
026: import org.snmp4j.*;
027: import org.snmp4j.event.*;
028: import org.snmp4j.mp.SnmpConstants;
029: import org.snmp4j.smi.*;
030: import java.io.*;
031:
032: /**
033: * The <code>TableUtils</code> class provides utility functions to retrieve
034: * SNMP tabular data.
035: *
036: * @author Frank Fock
037: * @version 1.6e
038: * @since 1.0.2
039: */
040: public class TableUtils extends AbstractSnmpUtility {
041:
042: private static final LogAdapter logger = LogFactory
043: .getLogger(TableUtils.class);
044:
045: // RowStatus TC enumerated values
046: public static final int ROWSTATUS_ACTIVE = 1;
047: public static final int ROWSTATUS_NOTINSERVICE = 2;
048: public static final int ROWSTATUS_NOTREADY = 3;
049: public static final int ROWSTATUS_CREATEANDGO = 4;
050: public static final int ROWSTATUS_CREATEANDWAIT = 5;
051: public static final int ROWSTATUS_DESTROY = 6;
052:
053: private int maxNumOfRowsPerPDU = 10;
054: private int maxNumColumnsPerPDU = 10;
055:
056: /**
057: * Creates a <code>TableUtils</code> instance. The created instance is thread
058: * safe as long as the supplied <code>Session</code> and <code>PDUFactory</code>
059: * are thread safe.
060: *
061: * @param snmpSession
062: * a SNMP <code>Session</code> instance.
063: * @param pduFactory
064: * a <code>PDUFactory</code> instance that creates the PDU that are used
065: * by this instance to retrieve table data using GETBULK/GETNEXT
066: * operations.
067: */
068: public TableUtils(Session snmpSession, PDUFactory pduFactory) {
069: super (snmpSession, pduFactory);
070: }
071:
072: /**
073: * Gets synchronously SNMP tabular data from one or more tables.
074: * The data is returned row-by-row as a list of {@link TableEvent} instances.
075: * Each instance represents a row (or an error condition). Besides the
076: * target agent, the OIDs of the columnar objects have to be specified
077: * for which instances should be retrieved. With a lower bound index and
078: * an upper bound index, the result set can be narrowed to improve
079: * performance. This method can be executed concurrently by multiple threads.
080: *
081: * @param target
082: * a <code>Target</code> instance.
083: * @param columnOIDs
084: * an array of OIDs of the columnar objects whose instances should be
085: * retrieved. The columnar objects may belong to different tables.
086: * Typically they belong to tables that share a common index or sub-index
087: * prefix. Note: The result of this method is not defined if instance OIDs
088: * are supplied in this array!
089: * @param lowerBoundIndex
090: * an optional parameter that specifies the lower bound index.
091: * If not <code>null</code>, all returned rows have an index greater than
092: * <code>lowerBoundIndex</code>.
093: * @param upperBoundIndex
094: * an optional parameter that specifies the upper bound index.
095: * If not <code>null</code>, all returned rows have an index less or equal
096: * than <code>upperBoundIndex</code>.
097: * @return
098: * a <code>List</code> of {@link TableEvent} instances. Each instance
099: * represents successfully retrieved row or an error condition. Error
100: * conditions (any status other than {@link TableEvent#STATUS_OK})
101: * may only appear at the last element of the list.
102: */
103: public List getTable(Target target, OID[] columnOIDs,
104: OID lowerBoundIndex, OID upperBoundIndex) {
105:
106: if ((columnOIDs == null) || (columnOIDs.length == 0)) {
107: throw new IllegalArgumentException(
108: "No column OIDs specified");
109: }
110: InternalTableListener listener = new InternalTableListener();
111: TableRequest req = createTableRequest(target, columnOIDs,
112: listener, null, lowerBoundIndex, upperBoundIndex);
113: synchronized (listener) {
114: if (req.sendNextChunk()) {
115: try {
116: listener.wait();
117: } catch (InterruptedException ex) {
118: logger.warn(ex);
119: }
120: }
121: }
122: return listener.getRows();
123: }
124:
125: protected TableRequest createTableRequest(Target target,
126: OID[] columnOIDs, TableListener listener,
127: Object userObject, OID lowerBoundIndex, OID upperBoundIndex) {
128: return new TableRequest(target, columnOIDs, listener,
129: userObject, lowerBoundIndex, upperBoundIndex);
130: }
131:
132: /**
133: * Gets SNMP tabular data from one or more tables. The data is returned
134: * asynchronously row-by-row through a supplied callback. Besides the
135: * target agent, the OIDs of the columnar objects have to be specified
136: * for which instances should be retrieved. With a lower bound index and
137: * an upper bound index, the result set can be narrowed to improve
138: * performance.
139: *
140: * @param target
141: * a <code>Target</code> instance.
142: * @param columnOIDs
143: * an array of OIDs of the columnar objects whose instances should be
144: * retrieved. The columnar objects may belong to different tables.
145: * Typically they belong to tables that share a common index or sub-index
146: * prefix. Note: The result of this method is not defined if instance OIDs
147: * are supplied in this array!
148: * @param listener
149: * a <code>TableListener</code> that is called with {@link TableEvent}
150: * objects when an error occured, new rows have been retrieved, or when
151: * the table has been retrieved completely.
152: * @param userObject
153: * an user object that is transparently supplied to the above call back.
154: * @param lowerBoundIndex
155: * an optional parameter that specifies the lower bound index.
156: * If not <code>null</code>, all returned rows have an index greater than
157: * <code>lowerBoundIndex</code>.
158: * @param upperBoundIndex
159: * an optional parameter that specifies the upper bound index.
160: * If not <code>null</code>, all returned rows have an index less or equal
161: * than <code>upperBoundIndex</code>.
162: */
163: public void getTable(Target target, OID[] columnOIDs,
164: TableListener listener, Object userObject,
165: OID lowerBoundIndex, OID upperBoundIndex) {
166: if ((columnOIDs == null) || (columnOIDs.length == 0)) {
167: throw new IllegalArgumentException(
168: "No column OIDs specified");
169: }
170: TableRequest req = new TableRequest(target, columnOIDs,
171: listener, userObject, lowerBoundIndex, upperBoundIndex);
172: req.sendNextChunk();
173: }
174:
175: /**
176: * Gets SNMP tabular data from one or more tables. The data is returned
177: * asynchronously row-by-row through a supplied callback. Besides the
178: * target agent, the OIDs of the columnar objects have to be specified
179: * for which instances should be retrieved. With a lower bound index and
180: * an upper bound index, the result set can be narrowed to improve
181: * performance.
182: * <p>
183: * This implementation must not be used with sparese tables, because it
184: * is optimized for dense tables and will not return correct results for
185: * sparse tables.
186: * </p>
187: *
188: * @param target
189: * a <code>Target</code> instance.
190: * @param columnOIDs
191: * an array of OIDs of the columnar objects whose instances should be
192: * retrieved. The columnar objects may belong to different tables.
193: * Typically they belong to tables that share a common index or sub-index
194: * prefix. Note: The result of this method is not defined if instance OIDs
195: * are supplied in this array!
196: * @param listener
197: * a <code>TableListener</code> that is called with {@link TableEvent}
198: * objects when an error occured, new rows have been retrieved, or when
199: * the table has been retrieved completely.
200: * @param userObject
201: * an user object that is transparently supplied to the above call back.
202: * @param lowerBoundIndex
203: * an optional parameter that specifies the lower bound index.
204: * If not <code>null</code>, all returned rows have an index greater than
205: * <code>lowerBoundIndex</code>.
206: * @param upperBoundIndex
207: * an optional parameter that specifies the upper bound index.
208: * If not <code>null</code>, all returned rows have an index less or equal
209: * than <code>lowerBoundIndex</code>.
210: * @since 1.5
211: */
212: public void getDenseTable(Target target, OID[] columnOIDs,
213: TableListener listener, Object userObject,
214: OID lowerBoundIndex, OID upperBoundIndex) {
215: if ((columnOIDs == null) || (columnOIDs.length == 0)) {
216: throw new IllegalArgumentException(
217: "No column OIDs specified");
218: }
219: TableRequest req = new TableRequest(target, columnOIDs,
220: listener, userObject, lowerBoundIndex, upperBoundIndex);
221: req.sendNextChunk();
222: }
223:
224: /**
225: * Gets the maximum number of rows that will be retrieved per SNMP GETBULK
226: * request.
227: *
228: * @return
229: * an integer greater than zero that specifies the maximum number of rows
230: * to retrieve per SNMP GETBULK operation.
231: */
232: public int getMaxNumRowsPerPDU() {
233: return maxNumOfRowsPerPDU;
234: }
235:
236: /**
237: * Sets the maximum number of rows that will be retrieved per SNMP GETBULK
238: * request. The default is 10.
239: *
240: * @param numberOfRowsPerChunk
241: * an integer greater than zero that specifies the maximum number of rows
242: * to retrieve per SNMP GETBULK operation.
243: */
244: public void setMaxNumRowsPerPDU(int numberOfRowsPerChunk) {
245: if (numberOfRowsPerChunk < 1) {
246: throw new IllegalArgumentException(
247: "The number of rows per PDU must be > 0");
248: }
249: this .maxNumOfRowsPerPDU = numberOfRowsPerChunk;
250: }
251:
252: /**
253: * Gets the maximum number of columns that will be retrieved per SNMP GETNEXT
254: * or GETBULK request.
255: *
256: * @return
257: * an integer greater than zero that specifies the maximum columns of rows
258: * to retrieve per SNMP GETNEXT or GETBULK operation.
259: */
260: public int getMaxNumColumnsPerPDU() {
261: return maxNumColumnsPerPDU;
262: }
263:
264: /**
265: * Sets the maximum number of columns that will be retrieved per SNMP GETNEXT
266: * or GETBULK request. The default is 10.
267: *
268: * @param numberOfColumnsPerChunk
269: * an integer greater than zero that specifies the maximum columns of rows
270: * to retrieve per SNMP GETNEXT or GETBULK operation.
271: */
272: public void setMaxNumColumnsPerPDU(int numberOfColumnsPerChunk) {
273: if (numberOfColumnsPerChunk < 1) {
274: throw new IllegalArgumentException(
275: "The number of columns per PDU must be > 0");
276: }
277: this .maxNumColumnsPerPDU = numberOfColumnsPerChunk;
278: }
279:
280: public class TableRequest implements ResponseListener {
281:
282: Target target;
283: OID[] columnOIDs;
284: TableListener listener;
285: Object userObject;
286: OID lowerBoundIndex;
287: OID upperBoundIndex;
288:
289: private int sent = 0;
290: private Vector lastSent = null;
291: private LinkedList rowCache = new LinkedList();
292: protected Vector lastReceived;
293:
294: volatile boolean finished = false;
295:
296: public TableRequest(Target target, OID[] columnOIDs,
297: TableListener listener, Object userObject,
298: OID lowerBoundIndex, OID upperBoundIndex) {
299: this .target = target;
300: this .columnOIDs = columnOIDs;
301: this .listener = listener;
302: this .userObject = userObject;
303: this .lastReceived = new Vector(Arrays.asList(columnOIDs));
304: this .upperBoundIndex = upperBoundIndex;
305: this .lowerBoundIndex = lowerBoundIndex;
306: if (lowerBoundIndex != null) {
307: for (int i = 0; i < lastReceived.size(); i++) {
308: OID oid = new OID(((OID) lastReceived.get(i)));
309: oid.append(lowerBoundIndex);
310: lastReceived.set(i, oid);
311: }
312: }
313: }
314:
315: public boolean sendNextChunk() {
316: if (sent >= lastReceived.size()) {
317: return false;
318: }
319: PDU pdu = pduFactory.createPDU(target);
320: if (target.getVersion() == SnmpConstants.version1) {
321: pdu.setType(PDU.GETNEXT);
322: } else {
323: pdu.setType(PDU.GETBULK);
324: }
325: int sz = Math.min(lastReceived.size() - sent,
326: maxNumColumnsPerPDU);
327: if (pdu.getType() == PDU.GETBULK) {
328: if (maxNumOfRowsPerPDU > 0) {
329: pdu.setMaxRepetitions(maxNumOfRowsPerPDU);
330: pdu.setNonRepeaters(0);
331: } else {
332: pdu.setNonRepeaters(sz);
333: pdu.setMaxRepetitions(0);
334: }
335: }
336: lastSent = new Vector(sz + 1);
337: for (int i = sent; i < sent + sz; i++) {
338: OID col = (OID) lastReceived.get(i);
339: VariableBinding vb = new VariableBinding(col);
340: pdu.add(vb);
341: if (pdu.getBERLength() > target.getMaxSizeRequestPDU()) {
342: pdu.trim();
343: break;
344: } else {
345: lastSent.add(lastReceived.get(i));
346: }
347: }
348: try {
349: Integer startCol = new Integer(sent);
350: sent += pdu.size();
351: sendRequest(pdu, target, startCol);
352: } catch (Exception ex) {
353: logger.error(ex);
354: if (logger.isDebugEnabled()) {
355: ex.printStackTrace();
356: }
357: listener.finished(new TableEvent(this , userObject, ex));
358: return false;
359: }
360: return true;
361: }
362:
363: protected void sendRequest(PDU pdu, Target target,
364: Integer startCol) throws IOException {
365: session.send(pdu, target, startCol, this );
366: }
367:
368: public synchronized void onResponse(ResponseEvent event) {
369: // Do not forget to cancel the asynchronous request! ;-)
370: session.cancel(event.getRequest(), this );
371: if (finished) {
372: return;
373: }
374: if (checkResponse(event)) {
375: boolean anyMatch = false;
376: int startCol = ((Integer) event.getUserObject())
377: .intValue();
378: PDU request = event.getRequest();
379: PDU response = event.getResponse();
380: int cols = request.size();
381: int rows = response.size() / cols;
382: OID lastMinIndex = null;
383: for (int r = 0; r < rows; r++) {
384: Row row = null;
385: for (int c = 0; c < request.size(); c++) {
386: anyMatch = false;
387: int pos = startCol + c;
388: VariableBinding vb = response.get(r * cols + c);
389: if (vb.isException()) {
390: continue;
391: }
392: OID id = vb.getOid();
393: OID col = columnOIDs[pos];
394: if (id.startsWith(col)) {
395: OID index = new OID(id.getValue(), col
396: .size(), id.size() - col.size());
397: if ((upperBoundIndex != null)
398: && (index
399: .compareTo(upperBoundIndex) > 0)) {
400: continue;
401: }
402: if ((lastMinIndex == null)
403: || (index.compareTo(lastMinIndex) < 0)) {
404: lastMinIndex = index;
405: }
406: anyMatch = true;
407: if ((row == null)
408: || (!row.getRowIndex()
409: .equals(index))) {
410: row = null;
411: for (ListIterator it = rowCache
412: .listIterator(rowCache.size()); it
413: .hasPrevious();) {
414: Row lastRow = (Row) it.previous();
415: int compareResult = index
416: .compareTo(lastRow
417: .getRowIndex());
418: if (compareResult == 0) {
419: row = lastRow;
420: break;
421: } else if (compareResult > 0) {
422: break;
423: }
424: }
425: }
426: if (row == null) {
427: row = new Row(index);
428: if (rowCache.size() == 0) {
429: rowCache.add(row);
430: } else if (((Row) rowCache.getFirst())
431: .getRowIndex().compareTo(index) >= 0) {
432: rowCache.addFirst(row);
433: } else {
434: for (ListIterator it = rowCache
435: .listIterator(rowCache
436: .size()); it
437: .hasPrevious();) {
438: Row lastRow = (Row) it
439: .previous();
440: if (index
441: .compareTo(lastRow.index) >= 0) {
442: it.set(row);
443: it.add(lastRow);
444: break;
445: }
446: }
447: }
448: }
449: if (((!row.setNumComplete(pos)) || (row
450: .size() > pos))
451: && (row.get(pos) != null)) {
452: finished = true;
453: listener.finished(new TableEvent(this ,
454: userObject,
455: TableEvent.STATUS_WRONG_ORDER));
456: return;
457: }
458: row.setNumComplete(pos);
459: if (pos < row.getNumComplete()) {
460: row.set(pos, vb);
461: } else {
462: row.add(vb);
463: }
464: lastReceived.set(pos, vb.getOid());
465: }
466: }
467: }
468: while ((rowCache.size() > 0)
469: && (((Row) rowCache.getFirst())
470: .getNumComplete() == columnOIDs.length)
471: && ((lastMinIndex == null) || (((Row) rowCache
472: .getFirst()).getRowIndex().compareTo(
473: lastMinIndex) < 0))) {
474: if (!listener.next(getTableEvent())) {
475: finished = true;
476: listener.finished(new TableEvent(this ,
477: userObject));
478: return;
479: }
480: }
481: if (!sendNextChunk()) {
482: if (anyMatch) {
483: sent = 0;
484: sendNextChunk();
485: } else {
486: emptyCache();
487: finished = true;
488: listener.finished(new TableEvent(this ,
489: userObject));
490: }
491: }
492: }
493: }
494:
495: protected boolean checkResponse(ResponseEvent event) {
496: if (event.getError() != null) {
497: finished = true;
498: emptyCache();
499: listener.finished(new TableEvent(this , userObject,
500: event.getError()));
501: } else if (event.getResponse() == null) {
502: finished = true;
503: // timeout
504: emptyCache();
505: listener.finished(new TableEvent(this , userObject,
506: TableEvent.STATUS_TIMEOUT));
507: } else if (event.getResponse().getType() == PDU.REPORT) {
508: finished = true;
509: emptyCache();
510: listener.finished(new TableEvent(this , userObject,
511: event.getResponse()));
512: } else if (event.getResponse().getErrorStatus() != PDU.noError) {
513: finished = true;
514: emptyCache();
515: listener.finished(new TableEvent(this , userObject,
516: event.getResponse().getErrorStatus()));
517: } else {
518: return true;
519: }
520: return false;
521: }
522:
523: private void emptyCache() {
524: while (rowCache.size() > 0) {
525: if (!listener.next(getTableEvent())) {
526: break;
527: }
528: }
529: }
530:
531: private TableEvent getTableEvent() {
532: Row r = (Row) rowCache.removeFirst();
533: r.setNumComplete(columnOIDs.length);
534: VariableBinding[] vbs = new VariableBinding[r.size()];
535: r.copyInto(vbs);
536: return new TableEvent(this , userObject, r.getRowIndex(),
537: vbs);
538: }
539:
540: public Row getRow(OID index) {
541: for (ListIterator it = rowCache.listIterator(rowCache
542: .size() + 1); it.hasPrevious();) {
543: Row r = (Row) it.previous();
544: if (index.equals(r.getRowIndex())) {
545: return r;
546: }
547: }
548: return null;
549: }
550: }
551:
552: /**
553: * The <code>DenseTableRequest</code> extends TableRequest to implement a
554: * faster table retrieval than the original. Caution:
555: * This version does not correctly retrieve sparse tables!
556: *
557: * @author Frank Fock
558: * @since 1.5
559: */
560: class DenseTableRequest extends TableRequest {
561: protected DenseTableRequest(Target target, OID[] columnOIDs,
562: TableListener listener, Object userObject,
563: OID lowerBoundIndex, OID upperBoundIndex) {
564: super (target, columnOIDs, listener, userObject,
565: lowerBoundIndex, upperBoundIndex);
566: }
567:
568: public synchronized void onResponse(ResponseEvent event) {
569: // Do not forget to cancel the asynchronous request! ;-)
570: session.cancel(event.getRequest(), this );
571: if (finished) {
572: return;
573: }
574: if (checkResponse(event)) {
575: int startCol = ((Integer) event.getUserObject())
576: .intValue();
577: PDU request = event.getRequest();
578: PDU response = event.getResponse();
579: int cols = request.size();
580: int rows = response.size() / cols;
581: OID lastMinIndex = null;
582: for (int r = 0; r < rows; r++) {
583: Row row = null;
584: for (int c = 0; c < request.size(); c++) {
585: int pos = startCol + c;
586: VariableBinding vb = response.get(r * cols + c);
587: if (vb.isException()) {
588: continue;
589: }
590: OID id = vb.getOid();
591: OID col = columnOIDs[pos];
592: if (id.startsWith(col)) {
593: OID index = new OID(id.getValue(), col
594: .size(), id.size() - col.size());
595: if ((upperBoundIndex != null)
596: && (index
597: .compareTo(upperBoundIndex) > 0)) {
598: continue;
599: }
600: if ((lastMinIndex == null)
601: || (index.compareTo(lastMinIndex) < 0)) {
602: lastMinIndex = index;
603: }
604: if (row == null) {
605: row = new Row(index);
606: }
607: row.setNumComplete(pos);
608: if (pos < row.getNumComplete()) {
609: row.set(pos, vb);
610: } else {
611: row.add(vb);
612: }
613: lastReceived.set(pos, vb.getOid());
614: }
615: }
616: if (row != null) {
617: if (!listener
618: .next(new TableEvent(
619: this ,
620: userObject,
621: row.getRowIndex(),
622: (VariableBinding[]) row
623: .toArray(new VariableBinding[0])))) {
624: finished = true;
625: listener.finished(new TableEvent(this ,
626: userObject));
627: return;
628: }
629: }
630: }
631: if (!sendNextChunk()) {
632: finished = true;
633: listener.finished(new TableEvent(this , userObject));
634: }
635: }
636: }
637: }
638:
639: /**
640: * Creates a SNMP table row for a table that support the RowStatus
641: * mechanism for row creation.
642: * @param target
643: * the Target SNMP entity for the operation.
644: * @param rowStatusColumnOID
645: * the column OID of the RowStatus column (without any instance identifier).
646: * @param rowIndex
647: * the OID denoting the index of the table row to create.
648: * @param values
649: * the values of columns to set in the row. If <code>values</code> is
650: * <code>null</code> the row is created via the tripple mode row creation
651: * mechanism (RowStatus is set to createAndWait). Otherwise, each variable
652: * binding has to contain the OID of the columnar object ID (without any
653: * instance identifier) and its value. On return, the variable bindings
654: * will be modified so that the variable binding OIDs will contain the
655: * instance OIDs of the respective columns (thus column OID + rowIndex).
656: * @return ResponseEvent
657: * the ResponseEvent instance returned by the SNMP session on response
658: * of the internally sent SET request. If <code>null</code>, an IO
659: * exception has occurred. Otherwise, if the response PDU is
660: * <code>null</code> a timeout has occured, Otherwise, check the error
661: * status for {@link SnmpConstants#SNMP_ERROR_SUCCESS} to verify that the
662: * row creation was successful.
663: * @since 1.6
664: */
665: public ResponseEvent createRow(Target target,
666: OID rowStatusColumnOID, OID rowIndex,
667: VariableBinding[] values) {
668: PDU pdu = pduFactory.createPDU(target);
669: OID rowStatusID = new OID(rowStatusColumnOID);
670: rowStatusID.append(rowIndex);
671: VariableBinding rowStatus = new VariableBinding(rowStatusID);
672: if (values != null) {
673: // one-shot mode
674: rowStatus.setVariable(new Integer32(ROWSTATUS_CREATEANDGO));
675: } else {
676: rowStatus
677: .setVariable(new Integer32(ROWSTATUS_CREATEANDWAIT));
678: }
679: pdu.add(rowStatus);
680: if (values != null) {
681: // append index to all columnar values
682: for (int i = 0; i < values.length; i++) {
683: OID columnOID = new OID(values[i].getOid());
684: columnOID.append(rowIndex);
685: values[i].setOid(columnOID);
686: }
687: pdu.addAll(values);
688: }
689: pdu.setType(PDU.SET);
690: try {
691: ResponseEvent responseEvent = session.send(pdu, target);
692: return responseEvent;
693: } catch (IOException ex) {
694: logger.error(ex);
695: }
696: return null;
697: }
698:
699: /**
700: * Destroys a SNMP table row from a table that support the RowStatus
701: * mechanism for row creation/deletion.
702: * @param target
703: * the Target SNMP entity for the operation.
704: * @param rowStatusColumnOID
705: * the column OID of the RowStatus column (without any instance identifier).
706: * @param rowIndex
707: * the OID denoting the index of the table row to destroy.
708: * @return ResponseEvent
709: * the ResponseEvent instance returned by the SNMP session on response
710: * of the internally sent SET request. If <code>null</code>, an IO
711: * exception has occurred. Otherwise, if the response PDU is
712: * <code>null</code> a timeout has occured, Otherwise, check the error
713: * status for {@link SnmpConstants#SNMP_ERROR_SUCCESS} to verify that the
714: * row creation was successful.
715: * @since 1.7.6
716: */
717: public ResponseEvent destroyRow(Target target,
718: OID rowStatusColumnOID, OID rowIndex) {
719: PDU pdu = pduFactory.createPDU(target);
720: OID rowStatusID = new OID(rowStatusColumnOID);
721: rowStatusID.append(rowIndex);
722: VariableBinding rowStatus = new VariableBinding(rowStatusID);
723: rowStatus.setVariable(new Integer32(ROWSTATUS_DESTROY));
724: pdu.add(rowStatus);
725: pdu.setType(PDU.SET);
726: try {
727: ResponseEvent responseEvent = session.send(pdu, target);
728: return responseEvent;
729: } catch (IOException ex) {
730: logger.error(ex);
731: }
732: return null;
733: }
734:
735: class Row extends Vector {
736:
737: private static final long serialVersionUID = -2297277440117636627L;
738:
739: private OID index;
740:
741: public Row(OID index) {
742: super ();
743: this .index = index;
744: }
745:
746: public OID getRowIndex() {
747: return index;
748: }
749:
750: public int getNumComplete() {
751: return super .size();
752: }
753:
754: public boolean setNumComplete(int numberOfColumnsComplete) {
755: int sz = numberOfColumnsComplete - getNumComplete();
756: for (int i = 0; i < sz; i++) {
757: super .add(null);
758: }
759: return (sz >= 0);
760: }
761: }
762:
763: class InternalTableListener implements TableListener {
764:
765: private List rows = new LinkedList();
766:
767: public boolean next(TableEvent event) {
768: rows.add(event);
769: return true;
770: }
771:
772: public synchronized void finished(TableEvent event) {
773: if ((event.getStatus() != TableEvent.STATUS_OK)
774: || (event.getIndex() != null)) {
775: rows.add(event);
776: }
777: notify();
778: }
779:
780: public List getRows() {
781: return rows;
782: }
783: }
784: }
|