1 /* 2 * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 27 package com.sun.jmx.snmp.daemon; 28 29 30 31 // java import 32 // 33 import java.util.Enumeration; 34 import java.util.logging.Level; 35 // jmx imports 36 // 37 import com.sun.jmx.snmp.SnmpPdu; 38 import com.sun.jmx.snmp.SnmpVarBind; 39 import com.sun.jmx.snmp.SnmpOid; 40 import com.sun.jmx.snmp.SnmpValue; 41 import com.sun.jmx.snmp.SnmpDefinitions; 42 import com.sun.jmx.snmp.SnmpStatusException; 43 import com.sun.jmx.snmp.SnmpEngine; 44 // SNMP Runtime import 45 // 46 import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER; 47 import com.sun.jmx.snmp.agent.SnmpMibAgent; 48 import com.sun.jmx.snmp.internal.SnmpIncomingRequest; 49 import com.sun.jmx.snmp.ThreadContext; 50 51 class SnmpSubBulkRequestHandler extends SnmpSubRequestHandler { 52 private SnmpAdaptorServer server = null; 53 54 /** 55 * The constructor initialize the subrequest with the whole varbind list contained 56 * in the original request. 57 */ 58 protected SnmpSubBulkRequestHandler(SnmpEngine engine, 59 SnmpAdaptorServer server, 60 SnmpIncomingRequest incRequest, 61 SnmpMibAgent agent, 62 SnmpPdu req, 63 int nonRepeat, 64 int maxRepeat, 65 int R) { 66 super(engine, incRequest, agent, req); 67 init(server, req, nonRepeat, maxRepeat, R); 68 } 69 70 /** 71 * The constructor initialize the subrequest with the whole varbind list contained 72 * in the original request. 73 */ 74 protected SnmpSubBulkRequestHandler(SnmpAdaptorServer server, 75 SnmpMibAgent agent, 76 SnmpPdu req, 77 int nonRepeat, 78 int maxRepeat, 79 int R) { 80 super(agent, req); 81 init(server, req, nonRepeat, maxRepeat, R); 82 } 83 84 @Override 85 public void run() { 86 87 size= varBind.size(); 88 89 try { 90 // Invoke a getBulk operation 91 // 92 /* NPCTE fix for bugId 4492741, esc 0, 16-August-2001 */ 93 final ThreadContext oldContext = 94 ThreadContext.push("SnmpUserData",data); 95 try { 96 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { 97 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(), 98 "run", "[" + Thread.currentThread() + 99 "]:getBulk operation on " + agent.getMibName()); 100 } 101 agent.getBulk(createMibRequest(varBind,version,data), 102 nonRepeat, maxRepeat); 103 } finally { 104 ThreadContext.restore(oldContext); 105 } 106 /* end of NPCTE fix for bugId 4492741 */ 107 108 } catch(SnmpStatusException x) { 109 errorStatus = x.getStatus() ; 110 errorIndex= x.getErrorIndex(); 111 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { 112 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpSubRequestHandler.class.getName(), 113 "run", "[" + Thread.currentThread() + 114 "]:an Snmp error occurred during the operation", x); 115 } 116 } 117 catch(Exception x) { 118 errorStatus = SnmpDefinitions.snmpRspGenErr ; 119 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { 120 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpSubRequestHandler.class.getName(), 121 "run", "[" + Thread.currentThread() + 122 "]:a generic error occurred during the operation", x); 123 } 124 } 125 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { 126 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(), 127 "run", "[" + Thread.currentThread() + 128 "]:operation completed"); 129 } 130 } 131 132 private void init(SnmpAdaptorServer server, 133 SnmpPdu req, 134 int nonRepeat, 135 int maxRepeat, 136 int R) { 137 this.server = server; 138 this.nonRepeat= nonRepeat; 139 this.maxRepeat= maxRepeat; 140 this.globalR= R; 141 142 final int max= translation.length; 143 final SnmpVarBind[] list= req.varBindList; 144 final NonSyncVector<SnmpVarBind> nonSyncVarBind = 145 ((NonSyncVector<SnmpVarBind>)varBind); 146 for(int i=0; i < max; i++) { 147 translation[i]= i; 148 // we need to allocate a new SnmpVarBind. Otherwise the first 149 // sub request will modify the list... 150 // 151 final SnmpVarBind newVarBind = 152 new SnmpVarBind(list[i].oid, list[i].value); 153 nonSyncVarBind.addNonSyncElement(newVarBind); 154 } 155 } 156 157 /** 158 * The method updates find out which element to use at update time. Handle oid overlapping as well 159 */ 160 private SnmpVarBind findVarBind(SnmpVarBind element, 161 SnmpVarBind result) { 162 163 if (element == null) return null; 164 165 if (result.oid == null) { 166 return element; 167 } 168 169 if (element.value == SnmpVarBind.endOfMibView) return result; 170 171 if (result.value == SnmpVarBind.endOfMibView) return element; 172 173 final SnmpValue val = result.value; 174 175 int comp = element.oid.compareTo(result.oid); 176 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { 177 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(), 178 "findVarBind","Comparing OID element : " + element.oid + 179 " with result : " + result.oid); 180 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(), 181 "findVarBind","Values element : " + element.value + 182 " result : " + result.value); 183 } 184 if (comp < 0) { 185 // Take the smallest (lexicographically) 186 // 187 return element; 188 } 189 else { 190 if(comp == 0) { 191 // Must compare agent used for reply 192 // Take the deeper within the reply 193 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { 194 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(), 195 "findVarBind"," oid overlapping. Oid : " + 196 element.oid + "value :" + element.value); 197 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(), 198 "findVarBind","Already present varBind : " + 199 result); 200 } 201 SnmpOid oid = result.oid; 202 SnmpMibAgent deeperAgent = server.getAgentMib(oid); 203 204 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { 205 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(), 206 "findVarBind","Deeper agent : " + deeperAgent); 207 } 208 if(deeperAgent == agent) { 209 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { 210 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(), 211 "findVarBind","The current agent is the deeper one. Update the value with the current one"); 212 } 213 return element; 214 } else { 215 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { 216 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(), 217 "findVarBind","The current agent is not the deeper one. return the previous one."); 218 } 219 return result; 220 } 221 222 /* 223 Vector v = new Vector(); 224 SnmpMibRequest getReq = createMibRequest(v, 225 version, 226 null); 227 SnmpVarBind realValue = new SnmpVarBind(oid); 228 getReq.addVarBind(realValue); 229 try { 230 deeperAgent.get(getReq); 231 } catch(SnmpStatusException e) { 232 e.printStackTrace(); 233 } 234 235 if(isDebugOn()) 236 trace("findVarBind", "Biggest priority value is : " + 237 realValue.value); 238 239 return realValue; 240 */ 241 242 } 243 else { 244 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { 245 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(), 246 "findVarBind","The right varBind is the already present one"); 247 } 248 return result; 249 } 250 } 251 } 252 /** 253 * The method updates a given var bind list with the result of a 254 * previsouly invoked operation. 255 * Prior to calling the method, one must make sure that the operation was 256 * successful. As such the method getErrorIndex or getErrorStatus should be 257 * called. 258 */ 259 @Override 260 protected void updateResult(SnmpVarBind[] result) { 261 // we can assume that the run method is over ... 262 // 263 264 final Enumeration<SnmpVarBind> e= varBind.elements(); 265 final int max= result.length; 266 267 // First go through all the values once ... 268 for(int i=0; i < size; i++) { 269 // May be we should control the position ... 270 // 271 if (e.hasMoreElements() == false) 272 return; 273 274 // bugId 4641694: must check position in order to avoid 275 // ArrayIndexOutOfBoundException 276 final int pos=translation[i]; 277 if (pos >= max) { 278 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { 279 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpSubRequestHandler.class.getName(), 280 "updateResult","Position '"+pos+"' is out of bound..."); 281 } 282 continue; 283 } 284 285 final SnmpVarBind element= e.nextElement(); 286 287 if (element == null) continue; 288 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { 289 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(), 290 "updateResult","Non repeaters Current element : " + 291 element + " from agent : " + agent); 292 } 293 final SnmpVarBind res = findVarBind(element,result[pos]); 294 295 if(res == null) continue; 296 297 result[pos] = res; 298 } 299 300 // Now update the values which have been repeated 301 // more than once. 302 int localR= size - nonRepeat; 303 for (int i = 2 ; i <= maxRepeat ; i++) { 304 for (int r = 0 ; r < localR ; r++) { 305 final int pos = (i-1)* globalR + translation[nonRepeat + r] ; 306 if (pos >= max) 307 return; 308 if (e.hasMoreElements() ==false) 309 return; 310 final SnmpVarBind element= e.nextElement(); 311 312 if (element == null) continue; 313 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { 314 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(), 315 "updateResult","Repeaters Current element : " + 316 element + " from agent : " + agent); 317 } 318 final SnmpVarBind res = findVarBind(element, result[pos]); 319 320 if(res == null) continue; 321 322 result[pos] = res; 323 } 324 } 325 } 326 327 // PROTECTED VARIABLES 328 //------------------ 329 330 /** 331 * Specific to the sub request 332 */ 333 protected int nonRepeat=0; 334 335 protected int maxRepeat=0; 336 337 /** 338 * R as defined in RCF 1902 for the global request the sub-request is associated to. 339 */ 340 protected int globalR=0; 341 342 protected int size=0; 343 }