1 20 21 package org.snmp4j.util; 22 23 import java.util.*; 24 25 import org.snmp4j.log.*; 26 import org.snmp4j.*; 27 import org.snmp4j.event.*; 28 import org.snmp4j.mp.SnmpConstants; 29 import org.snmp4j.smi.*; 30 import java.io.*; 31 32 40 public class TableUtils extends AbstractSnmpUtility { 41 42 private static final LogAdapter logger = 43 LogFactory.getLogger(TableUtils.class); 44 45 public static final int ROWSTATUS_ACTIVE = 1; 47 public static final int ROWSTATUS_NOTINSERVICE = 2; 48 public static final int ROWSTATUS_NOTREADY = 3; 49 public static final int ROWSTATUS_CREATEANDGO = 4; 50 public static final int ROWSTATUS_CREATEANDWAIT = 5; 51 public static final int ROWSTATUS_DESTROY = 6; 52 53 private int maxNumOfRowsPerPDU = 10; 54 private int maxNumColumnsPerPDU = 10; 55 56 68 public TableUtils(Session snmpSession, PDUFactory pduFactory) { 69 super(snmpSession, pduFactory); 70 } 71 72 103 public List getTable(Target target, 104 OID[] columnOIDs, 105 OID lowerBoundIndex, 106 OID upperBoundIndex) { 107 108 if ((columnOIDs == null) || (columnOIDs.length == 0)) { 109 throw new IllegalArgumentException ("No column OIDs specified"); 110 } 111 InternalTableListener listener = new InternalTableListener(); 112 TableRequest req = new TableRequest(target, columnOIDs, listener, 113 null, 114 lowerBoundIndex, 115 upperBoundIndex); 116 synchronized (listener) { 117 if (req.sendNextChunk()) { 118 try { 119 listener.wait(); 120 } 121 catch (InterruptedException ex) { 122 logger.warn(ex); 123 } 124 } 125 } 126 return listener.getRows(); 127 } 128 129 160 public void getTable(Target target, 161 OID[] columnOIDs, 162 TableListener listener, 163 Object userObject, 164 OID lowerBoundIndex, 165 OID upperBoundIndex) { 166 if ((columnOIDs == null) || (columnOIDs.length == 0)) { 167 throw new IllegalArgumentException ("No column OIDs specified"); 168 } 169 TableRequest req = new TableRequest(target, columnOIDs, listener, 170 userObject, 171 lowerBoundIndex, 172 upperBoundIndex); 173 req.sendNextChunk(); 174 } 175 176 213 public void getDenseTable(Target target, 214 OID[] columnOIDs, 215 TableListener listener, 216 Object userObject, 217 OID lowerBoundIndex, 218 OID upperBoundIndex) { 219 if ((columnOIDs == null) || (columnOIDs.length == 0)) { 220 throw new IllegalArgumentException ("No column OIDs specified"); 221 } 222 TableRequest req = new TableRequest(target, columnOIDs, listener, 223 userObject, 224 lowerBoundIndex, 225 upperBoundIndex); 226 req.sendNextChunk(); 227 } 228 229 237 public int getMaxNumRowsPerPDU() { 238 return maxNumOfRowsPerPDU; 239 } 240 241 249 public void setMaxNumRowsPerPDU(int numberOfRowsPerChunk) { 250 if (numberOfRowsPerChunk < 1) { 251 throw new IllegalArgumentException ( 252 "The number of rows per PDU must be > 0"); 253 } 254 this.maxNumOfRowsPerPDU = numberOfRowsPerChunk; 255 } 256 257 265 public int getMaxNumColumnsPerPDU() { 266 return maxNumColumnsPerPDU; 267 } 268 269 277 public void setMaxNumColumnsPerPDU(int numberOfColumnsPerChunk) { 278 if (numberOfColumnsPerChunk < 1) { 279 throw new IllegalArgumentException ( 280 "The number of columns per PDU must be > 0"); 281 } 282 this.maxNumColumnsPerPDU = numberOfColumnsPerChunk; 283 } 284 285 class TableRequest implements ResponseListener { 286 287 Target target; 288 OID[] columnOIDs; 289 TableListener listener; 290 Object userObject; 291 OID lowerBoundIndex; 292 OID upperBoundIndex; 293 294 private int sent = 0; 295 private Vector lastSent = null; 296 private LinkedList rowCache = new LinkedList(); 297 protected Vector lastReceived; 298 299 volatile boolean finished = false; 300 301 protected TableRequest(Target target, 302 OID[] columnOIDs, 303 TableListener listener, 304 Object userObject, 305 OID lowerBoundIndex, 306 OID upperBoundIndex) { 307 this.target = target; 308 this.columnOIDs = columnOIDs; 309 this.listener = listener; 310 this.userObject = userObject; 311 this.lastReceived = new Vector(Arrays.asList(columnOIDs)); 312 this.upperBoundIndex = upperBoundIndex; 313 this.lowerBoundIndex = lowerBoundIndex; 314 if (lowerBoundIndex != null) { 315 for (int i = 0; i < lastReceived.size(); i++) { 316 OID oid = new OID(((OID) lastReceived.get(i))); 317 oid.append(lowerBoundIndex); 318 lastReceived.set(i, oid); 319 } 320 } 321 } 322 323 public boolean sendNextChunk() { 324 if (sent >= lastReceived.size()) { 325 return false; 326 } 327 PDU pdu = pduFactory.createPDU(target); 328 if (target.getVersion() == SnmpConstants.version1) { 329 pdu.setType(PDU.GETNEXT); 330 } 331 else { 332 pdu.setType(PDU.GETBULK); 333 } 334 int sz = Math.min(lastReceived.size() - sent, maxNumColumnsPerPDU); 335 if (pdu.getType() == PDU.GETBULK) { 336 if (maxNumOfRowsPerPDU > 0) { 337 pdu.setMaxRepetitions(maxNumOfRowsPerPDU); 338 pdu.setNonRepeaters(0); 339 } 340 else { 341 pdu.setNonRepeaters(sz); 342 pdu.setMaxRepetitions(0); 343 } 344 } 345 lastSent = new Vector(sz + 1); 346 for (int i = sent; i < sent + sz; i++) { 347 OID col = (OID) lastReceived.get(i); 348 VariableBinding vb = new VariableBinding(col); 349 pdu.add(vb); 350 if (pdu.getBERLength() > target.getMaxSizeRequestPDU()) { 351 pdu.trim(); 352 break; 353 } 354 else { 355 lastSent.add(lastReceived.get(i)); 356 } 357 } 358 try { 359 Integer startCol = new Integer (sent); 360 sent += pdu.size(); 361 session.send(pdu, target, startCol, this); 362 } 363 catch (Exception ex) { 364 logger.error(ex); 365 if (logger.isDebugEnabled()) { 366 ex.printStackTrace(); 367 } 368 listener.finished(new TableEvent(this, userObject, ex)); 369 return false; 370 } 371 return true; 372 } 373 374 public synchronized void onResponse(ResponseEvent event) { 375 session.cancel(event.getRequest(), this); 377 if (finished) { 378 return; 379 } 380 if (checkResponse(event)) { 381 boolean anyMatch = false; 382 int startCol = ((Integer ) event.getUserObject()).intValue(); 383 PDU request = event.getRequest(); 384 PDU response = event.getResponse(); 385 int cols = request.size(); 386 int rows = response.size() / cols; 387 OID lastMinIndex = null; 388 for (int r = 0; r < rows; r++) { 389 Row row = null; 390 for (int c = 0; c < request.size(); c++) { 391 anyMatch = false; 392 int pos = startCol + c; 393 VariableBinding vb = response.get(r * cols + c); 394 if (vb.isException()) { 395 continue; 396 } 397 OID id = vb.getOid(); 398 OID col = columnOIDs[pos]; 399 if (id.startsWith(col)) { 400 OID index = 401 new OID(id.getValue(), col.size(), id.size() - col.size()); 402 if ((upperBoundIndex != null) && 403 (index.compareTo(upperBoundIndex) > 0)) { 404 continue; 405 } 406 if ((lastMinIndex == null) || 407 (index.compareTo(lastMinIndex) < 0)) { 408 lastMinIndex = index; 409 } 410 anyMatch = true; 411 if ((row == null) || (!row.getRowIndex().equals(index))) { 412 row = null; 413 for (ListIterator it = rowCache.listIterator(rowCache.size()); 414 it.hasPrevious(); ) { 415 Row lastRow = (Row) it.previous(); 416 int compareResult = index.compareTo(lastRow.getRowIndex()); 417 if (compareResult == 0) { 418 row = lastRow; 419 break; 420 } 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 } 431 else if (((Row) rowCache.getFirst()).getRowIndex().compareTo( 432 index) >= 0) { 433 rowCache.addFirst(row); 434 } 435 else { 436 for (ListIterator it = rowCache.listIterator(rowCache.size()); 437 it.hasPrevious(); ) { 438 Row lastRow = (Row) it.previous(); 439 if (index.compareTo(lastRow.index) >= 0) { 440 it.set(row); 441 it.add(lastRow); 442 break; 443 } 444 } 445 } 446 } 447 if (((!row.setNumComplete(pos)) || 448 (row.size() > pos)) && (row.get(pos) != null)) { 449 finished = true; 450 listener.finished(new TableEvent(this, userObject, 451 TableEvent.STATUS_WRONG_ORDER)); 452 return; 453 } 454 row.setNumComplete(pos); 455 if (pos < row.getNumComplete()) { 456 row.set(pos, vb); 457 } 458 else { 459 row.add(vb); 460 } 461 lastReceived.set(pos, vb.getOid()); 462 } 463 } 464 } 465 while ((rowCache.size() > 0) && 466 (((Row) rowCache.getFirst()).getNumComplete() == 467 columnOIDs.length) && 468 ((lastMinIndex == null) || 469 (((Row) rowCache.getFirst()).getRowIndex().compareTo( 470 lastMinIndex) < 0))) { 471 if (!listener.next(getTableEvent())) { 472 finished = true; 473 listener.finished(new TableEvent(this, userObject)); 474 return; 475 } 476 } 477 if (!sendNextChunk()) { 478 if (anyMatch) { 479 sent = 0; 480 sendNextChunk(); 481 } 482 else { 483 emptyCache(); 484 finished = true; 485 listener.finished(new TableEvent(this, userObject)); 486 } 487 } 488 } 489 } 490 491 protected boolean checkResponse(ResponseEvent event) { 492 if (event.getError() != null) { 493 finished = true; 494 emptyCache(); 495 listener.finished(new TableEvent(this, userObject, event.getError())); 496 } 497 else if (event.getResponse() == null) { 498 finished = true; 499 emptyCache(); 501 listener.finished(new TableEvent(this, userObject, 502 TableEvent.STATUS_TIMEOUT)); 503 } 504 else if (event.getResponse().getType() == PDU.REPORT) { 505 finished = true; 506 emptyCache(); 507 listener.finished(new TableEvent(this, userObject, 508 event.getResponse())); 509 } 510 else if (event.getResponse().getErrorStatus() != PDU.noError) { 511 finished = true; 512 emptyCache(); 513 listener.finished(new TableEvent(this, userObject, 514 event.getResponse().getErrorStatus())); 515 } 516 else { 517 return true; 518 } 519 return false; 520 } 521 522 private void emptyCache() { 523 while (rowCache.size() > 0) { 524 if (!listener.next(getTableEvent())) { 525 break; 526 } 527 } 528 } 529 530 private TableEvent getTableEvent() { 531 Row r = (Row) rowCache.removeFirst(); 532 r.setNumComplete(columnOIDs.length); 533 VariableBinding[] vbs = new VariableBinding[r.size()]; 534 r.copyInto(vbs); 535 return new TableEvent(this, userObject, r.getRowIndex(), vbs); 536 } 537 538 public Row getRow(OID index) { 539 for (ListIterator it = rowCache.listIterator(rowCache.size() + 1); 540 it.hasPrevious(); ) { 541 Row r = (Row) it.previous(); 542 if (index.equals(r.getRowIndex())) { 543 return r; 544 } 545 } 546 return null; 547 } 548 } 549 550 558 class DenseTableRequest extends TableRequest { 559 protected DenseTableRequest(Target target, 560 OID[] columnOIDs, 561 TableListener listener, 562 Object userObject, 563 OID lowerBoundIndex, 564 OID upperBoundIndex) { 565 super(target, columnOIDs, listener, userObject, lowerBoundIndex, 566 upperBoundIndex); 567 } 568 569 public synchronized void onResponse(ResponseEvent event) { 570 session.cancel(event.getRequest(), this); 572 if (finished) { 573 return; 574 } 575 if (checkResponse(event)) { 576 int startCol = ((Integer ) event.getUserObject()).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 = 594 new OID(id.getValue(), col.size(), id.size() - col.size()); 595 if ((upperBoundIndex != null) && 596 (index.compareTo(upperBoundIndex) > 0)) { 597 continue; 598 } 599 if ((lastMinIndex == null) || 600 (index.compareTo(lastMinIndex) < 0)) { 601 lastMinIndex = index; 602 } 603 if (row == null) { 604 row = new Row(index); 605 } 606 row.setNumComplete(pos); 607 if (pos < row.getNumComplete()) { 608 row.set(pos, vb); 609 } 610 else { 611 row.add(vb); 612 } 613 lastReceived.set(pos, vb.getOid()); 614 } 615 } 616 if (row != null) { 617 if (!listener.next(new TableEvent(this, userObject, row.getRowIndex(), 618 (VariableBinding[]) 619 row.toArray(new VariableBinding[0])))) { 620 finished = true; 621 listener.finished(new TableEvent(this, userObject)); 622 return; 623 } 624 } 625 } 626 if (!sendNextChunk()) { 627 finished = true; 628 listener.finished(new TableEvent(this, userObject)); 629 } 630 } 631 } 632 } 633 634 660 public ResponseEvent createRow(Target target, 661 OID rowStatusColumnOID, OID rowIndex, 662 VariableBinding[] values) { 663 PDU pdu = pduFactory.createPDU(target); 664 OID rowStatusID = new OID(rowStatusColumnOID); 665 rowStatusID.append(rowIndex); 666 VariableBinding rowStatus = new VariableBinding(rowStatusID); 667 if (values != null) { 668 rowStatus.setVariable(new Integer32(ROWSTATUS_CREATEANDGO)); 670 } 671 else { 672 rowStatus.setVariable(new Integer32(ROWSTATUS_CREATEANDWAIT)); 673 } 674 pdu.add(rowStatus); 675 if (values != null) { 676 for (int i = 0; i < values.length; i++) { 678 OID columnOID = new OID(values[i].getOid()); 679 columnOID.append(rowIndex); 680 values[i].setOid(columnOID); 681 } 682 pdu.addAll(values); 683 } 684 pdu.setType(PDU.SET); 685 try { 686 ResponseEvent responseEvent = session.send(pdu, target); 687 return responseEvent; 688 } 689 catch (IOException ex) { 690 logger.error(ex); 691 } 692 return null; 693 } 694 695 713 public ResponseEvent destroyRow(Target target, 714 OID rowStatusColumnOID, OID rowIndex) { 715 PDU pdu = pduFactory.createPDU(target); 716 OID rowStatusID = new OID(rowStatusColumnOID); 717 rowStatusID.append(rowIndex); 718 VariableBinding rowStatus = new VariableBinding(rowStatusID); 719 rowStatus.setVariable(new Integer32(ROWSTATUS_DESTROY)); 720 pdu.add(rowStatus); 721 pdu.setType(PDU.SET); 722 try { 723 ResponseEvent responseEvent = session.send(pdu, target); 724 return responseEvent; 725 } 726 catch (IOException ex) { 727 logger.error(ex); 728 } 729 return null; 730 } 731 732 class Row extends Vector { 733 734 private static final long serialVersionUID = -2297277440117636627L; 735 736 private OID index; 737 738 public Row(OID index) { 739 super(); 740 this.index = index; 741 } 742 743 public OID getRowIndex() { 744 return index; 745 } 746 747 public int getNumComplete() { 748 return super.size(); 749 } 750 751 public boolean setNumComplete(int numberOfColumnsComplete) { 752 int sz = numberOfColumnsComplete - getNumComplete(); 753 for (int i = 0; i < sz; i++) { 754 super.add(null); 755 } 756 return (sz >= 0); 757 } 758 } 759 760 class InternalTableListener implements TableListener { 761 762 private List rows = new LinkedList(); 763 764 public boolean next(TableEvent event) { 765 rows.add(event); 766 return true; 767 } 768 769 public synchronized void finished(TableEvent event) { 770 if ((event.getStatus() != TableEvent.STATUS_OK) || 771 (event.getIndex() != null)) { 772 rows.add(event); 773 } 774 notify(); 775 } 776 777 public List getRows() { 778 return rows; 779 } 780 } 781 } 782 | Popular Tags |