AbstractProtocol泛型抽象类

该抽象类是ProtocolHandler接口的默认抽象实现

该抽象类实现了ProtocolHandler和MBeanRegistration接口
	/**
	 * 该包的string管理器
	 */
	protected static final StringManager sm = StringManager.getManager(Constants.Package);

	/**
	 * 被使用来为连接器产生唯一JMX名称的计数器
	 * Counter used to generate unique JMX names for connectors using automatic
	 * port binding.
	 */
	private static final AtomicInteger nameCounter = new AtomicInteger(0);

	/**
	 * 全局Request请求处理器的MBean名称
	 */
	protected ObjectName rgOname = null;

	/**
	 * 线程池的MBean的名称
	 */
	protected ObjectName tpOname = null;

	/**
	 * 该连接器的唯一ID。当使用一个随机端口作为connector的端口,并且调用stop,start方法时被改变
	 */
	private int nameIndex = 0;

	/**
	 * Endpoint提供了低级的网络IO操作。
	 */
	protected AbstractEndpoint<S> endpoint = null;

	// ----------------------------------------------- 属性处理

	/**
	 * 被digester来配置属性。当digester在找不到一个合适的setter方法时使用这个方法。这意味着这个属性属于Endpoint,
	 * ServerSocketFactory或其他的一些底层部分。这个方法确保了该属性对所有其他类可见
	 */
	public boolean setProperty(String name, String value) {
		return endpoint.setProperty(name, value);
	}

	/**
	 * 被digester使用的获取属性的方法。
	 * Generic property getter used by the digester. Other code should not need
	 * to use this.
	 */
	public String getProperty(String name) {
		return endpoint.getProperty(name);
	}

	// ------------------------------- Properties managed by the ProtocolHandler

	/**
	 * Aapter提供了ProtocolHandler和连接器之间的关联
	 */
	protected Adapter adapter;

	@Override
	public void setAdapter(Adapter adapter) {
		this.adapter = adapter;
	}

	@Override
	public Adapter getAdapter() {
		return adapter;
	}

	/**
	 * 可以被即将接受到的request使用的在cache中存放并且可被重复使用的最大的预留的处理器数量。默认是200
	 * The maximum number of idle processors that will be retained in the cache
	 * and re-used with a subsequent request. The default is 200. A value of -1
	 * means unlimited. In the unlimited case, the theoretical maximum number of
	 * cached Processor objects is {@link #getMaxConnections()} although it will
	 * usually be closer to {@link #getMaxThreads()}.
	 */
	protected int processorCache = 200;

	public int getProcessorCache() {
		return this.processorCache;
	}

	public void setProcessorCache(int processorCache) {
		this.processorCache = processorCache;
	}

	/**
	 * When client certificate information is presented in a form other than
	 * instances of {@link java.security.cert.X509Certificate} it needs to be
	 * converted before it can be used and this property controls which JSSE
	 * provider is used to perform the conversion. For example it is used with
	 * the AJP connectors, the HTTP APR connector and with the
	 * {@link org.apache.catalina.valves.SSLValve}. If not specified, the
	 * default provider will be used.
	 */
	protected String clientCertProvider = null;

	public String getClientCertProvider() {
		return clientCertProvider;
	}

	public void setClientCertProvider(String s) {
		this.clientCertProvider = s;
	}

	@Override
	public boolean isAprRequired() {
		return false;
	}

	// ---------------------- 通过EendPoint传递的属性

	@Override
	public Executor getExecutor() {
		return endpoint.getExecutor();
	}

	public void setExecutor(Executor executor) {
		endpoint.setExecutor(executor);
	}

	public int getMaxThreads() {
		return endpoint.getMaxThreads();
	}

	public void setMaxThreads(int maxThreads) {
		endpoint.setMaxThreads(maxThreads);
	}

	public int getMaxConnections() {
		return endpoint.getMaxConnections();
	}

	public void setMaxConnections(int maxConnections) {
		endpoint.setMaxConnections(maxConnections);
	}

	public int getMinSpareThreads() {
		return endpoint.getMinSpareThreads();
	}

	public void setMinSpareThreads(int minSpareThreads) {
		endpoint.setMinSpareThreads(minSpareThreads);
	}

	public int getThreadPriority() {
		return endpoint.getThreadPriority();
	}

	public void setThreadPriority(int threadPriority) {
		endpoint.setThreadPriority(threadPriority);
	}

	public int getBacklog() {
		return endpoint.getBacklog();
	}

	public void setBacklog(int backlog) {
		endpoint.setBacklog(backlog);
	}

	public boolean getTcpNoDelay() {
		return endpoint.getTcpNoDelay();
	}

	public void setTcpNoDelay(boolean tcpNoDelay) {
		endpoint.setTcpNoDelay(tcpNoDelay);
	}

	public int getSoLinger() {
		return endpoint.getSoLinger();
	}

	public void setSoLinger(int soLinger) {
		endpoint.setSoLinger(soLinger);
	}

	public int getKeepAliveTimeout() {
		return endpoint.getKeepAliveTimeout();
	}

	public void setKeepAliveTimeout(int keepAliveTimeout) {
		endpoint.setKeepAliveTimeout(keepAliveTimeout);
	}

	public InetAddress getAddress() {
		return endpoint.getAddress();
	}

	public void setAddress(InetAddress ia) {
		endpoint.setAddress(ia);
	}

	public int getPort() {
		return endpoint.getPort();
	}

	public void setPort(int port) {
		endpoint.setPort(port);
	}

	public int getLocalPort() {
		return endpoint.getLocalPort();
	}

	/*
	 * 当tomcat从客户端获取数据的时候,这是在关闭连接前tomcat等待接受数据的时间
	 * When Tomcat expects data from the client, this is the time Tomcat will
	 * wait for that data to arrive before closing the connection.
	 */
	public int getConnectionTimeout() {
		return endpoint.getSoTimeout();
	}

	public void setConnectionTimeout(int timeout) {
		// Note that the endpoint uses the alternative name
		endpoint.setSoTimeout(timeout);
	}

	/*
	 * Alternative name for connectionTimeout property
	 */
	public int getSoTimeout() {
		return getConnectionTimeout();
	}

	public void setSoTimeout(int timeout) {
		setConnectionTimeout(timeout);
	}

	public int getMaxHeaderCount() {
		return endpoint.getMaxHeaderCount();
	}

	public void setMaxHeaderCount(int maxHeaderCount) {
		endpoint.setMaxHeaderCount(maxHeaderCount);
	}

	public long getConnectionCount() {
		return endpoint.getConnectionCount();
	}

	// ---------------------------------------------------------- public method
	
	/**
	 * 利用AtomicInteger获取增量计数
	 * 
	 * @return
	 */
	public synchronized int getNameIndex() {
		if (nameIndex == 0) {
			nameIndex = nameCounter.incrementAndGet();
		}

		return nameIndex;
	}

	/**
	 * The name will be prefix-address-port if address is non-null and
	 * prefix-port if the address is null. The name will be appropriately quoted
	 * so it can be used directly in an ObjectName.
	 */
	public String getName() {
		StringBuilder name = new StringBuilder(getNamePrefix());
		name.append('-');
		if (getAddress() != null) {
			name.append(getAddress().getHostAddress());
			name.append('-');
		}
		int port = getPort();
		if (port == 0) {
			// Auto binding is in use. Check if port is known
			name.append("auto-");
			name.append(getNameIndex());
			port = getLocalPort();
			if (port != -1) {
				name.append('-');
				name.append(port);
			}
		} else {
			name.append(port);
		}
		return ObjectName.quote(name.toString());
	}

	// -------------------------------------------------------- 抽象方法

	/**
	 * Concrete implementations need to provide access to their logger to be
	 * used by the abstract classes.
	 */
	protected abstract Log getLog();

	/**
	 * 获取该protocol handler的前缀名称(name为prefix-address-port)
	 * Obtain the prefix to be used when construction a name for this protocol
	 * handler. The name will be prefix-address-port.
	 */
	protected abstract String getNamePrefix();

	/**
	 * 获取该protocol的name
	 * Obtain the name of the protocol, (Http, Ajp, etc.). Used with JMX.
	 */
	protected abstract String getProtocolName();

	/**
	 * 获取该endpoint所关联的handler
	 * Obtain the handler associated with the underlying Endpoint
	 */
	protected abstract Handler getHandler();

	// ----------------------------------------------------- JMX related methods

	protected String domain;
	protected ObjectName oname;
	protected MBeanServer mserver;

	public ObjectName getObjectName() {
		return oname;
	}

	public String getDomain() {
		return domain;
	}

	@Override
	public ObjectName preRegister(MBeanServer server, ObjectName name)
			throws Exception {
		oname = name;
		mserver = server;
		domain = name.getDomain();
		return name;
	}

	@Override
	public void postRegister(Boolean registrationDone) {
		// NOOP
	}

	@Override
	public void preDeregister() throws Exception {
		// NOOP
	}

	@Override
	public void postDeregister() {
		// NOOP
	}

	/**
	 * 创建一个ObjectName对象
	 * 
	 * @return
	 * @throws MalformedObjectNameException
	 */
	private ObjectName createObjectName() throws MalformedObjectNameException {
		// Use the same domain as the connector
		domain = adapter.getDomain();

		if (domain == null) {
			return null;
		}

		StringBuilder name = new StringBuilder(getDomain());
		name.append(":type=ProtocolHandler,port=");
		int port = getPort();
		if (port > 0) {
			name.append(getPort());
		} else {
			name.append("auto-");
			name.append(getNameIndex());
		}
		InetAddress address = getAddress();
		if (address != null) {
			name.append(",address=");
			name.append(ObjectName.quote(address.getHostAddress()));
		}
		return new ObjectName(name.toString());
	}

	// ------------------------------------------------------- Lifecycle methods

	/*
	 * NOTE: There is no maintenance of state or checking for valid transitions
	 * within this class. It is expected that the connector will maintain state
	 * and prevent invalid state transitions.
	 */
	/**
	 * 初始化
	 */
	@Override
	public void init() throws Exception {

		if (oname == null) {
			/**
			 * 如果oname为null
			 */
			oname = createObjectName();
			/**
			 * 将Oname注册到JMX中
			 */
			if (oname != null) {
				Registry.getRegistry(null, null).registerComponent(this, oname,
						null);
			}
		}

		/**
		 * 实例化tpOname和rgOname并将其注册到JMX中
		 */
		if (this.domain != null) {
			try {
				tpOname = new ObjectName(domain + ":" + "type=ThreadPool,name="
						+ getName());
				Registry.getRegistry(null, null).registerComponent(endpoint,
						tpOname, null);
			} catch (Exception e) {
			}
			rgOname = new ObjectName(domain
					+ ":type=GlobalRequestProcessor,name=" + getName());
			Registry.getRegistry(null, null).registerComponent(
					getHandler().getGlobal(), rgOname, null);
		}

		/**
		 * 设置endpoint的name
		 */
		String endpointName = getName();
		endpoint.setName(endpointName.substring(1, endpointName.length() - 1));
		/**
		 * 调用endpoint的init方法
		 */
		try {
			endpoint.init();
		} catch (Exception ex) {
			throw ex;
		}
	}

	@Override
	public void start() throws Exception {
		if (getLog().isInfoEnabled())
			getLog().info(
					sm.getString("abstractProtocolHandler.start", getName()));
		try {
			endpoint.start();
		} catch (Exception ex) {
			getLog().error(
					sm.getString("abstractProtocolHandler.startError",
							getName()), ex);
			throw ex;
		}
	}

	@Override
	public void pause() throws Exception {
		if (getLog().isInfoEnabled())
			getLog().info(
					sm.getString("abstractProtocolHandler.pause", getName()));
		try {
			endpoint.pause();
		} catch (Exception ex) {
			getLog().error(
					sm.getString("abstractProtocolHandler.pauseError",
							getName()), ex);
			throw ex;
		}
	}

	@Override
	public void resume() throws Exception {
		if (getLog().isInfoEnabled())
			getLog().info(
					sm.getString("abstractProtocolHandler.resume", getName()));
		try {
			endpoint.resume();
		} catch (Exception ex) {
			getLog().error(
					sm.getString("abstractProtocolHandler.resumeError",
							getName()), ex);
			throw ex;
		}
	}
	
	@Override
	public void stop() throws Exception {
		if (getLog().isInfoEnabled())
			getLog().info(
					sm.getString("abstractProtocolHandler.stop", getName()));
		try {
			endpoint.stop();
		} catch (Exception ex) {
			getLog().error(
					sm.getString("abstractProtocolHandler.stopError", getName()),
					ex);
			throw ex;
		}
	}
	
	@Override
	public void destroy() {
		if (getLog().isInfoEnabled()) {
			getLog().info(
					sm.getString("abstractProtocolHandler.destroy", getName()));
		}
		try {
			endpoint.destroy();
		} catch (Exception e) {
			getLog().error(
					sm.getString("abstractProtocolHandler.destroyError",
							getName()), e);
		}

		if (oname != null) {
			Registry.getRegistry(null, null).unregisterComponent(oname);
		}

		if (tpOname != null)
			Registry.getRegistry(null, null).unregisterComponent(tpOname);
		if (rgOname != null)
			Registry.getRegistry(null, null).unregisterComponent(rgOname);
	}

	// ------------------------------------------- Connection handler base class
	/**
	 * AbstractEndpoint.Handler接口的抽象实现
	 * @author songjianc
	 *
	 * @param <S>
	 * @param <P>
	 */
	protected abstract static class AbstractConnectionHandler<S, P extends Processor<S>>
			implements AbstractEndpoint.Handler {

		protected abstract Log getLog();
		
		protected RequestGroupInfo global = new RequestGroupInfo();
		protected AtomicLong registerCount = new AtomicLong(0);

		protected ConcurrentHashMap<S, Processor<S>> connections = new ConcurrentHashMap<S, Processor<S>>();

		protected RecycledProcessors<P, S> recycledProcessors = new RecycledProcessors<P, S>(
				this);

		protected abstract AbstractProtocol<S> getProtocol();

		@Override
		public Object getGlobal() {
			return global;
		}

		@Override
		public void recycle() {
			recycledProcessors.clear();
		}

		@SuppressWarnings("deprecation")
		// Old HTTP upgrade method has been deprecated
		/**
		 * 对请求进行处理 
		 */
		public SocketState process(SocketWrapper<S> wrapper, SocketStatus status) {
			if (wrapper == null) {
				// socket已经被关闭了.
				return SocketState.CLOSED;
			}
			
			S socket = wrapper.getSocket();// 获取wrapper中保存的实体
			if (socket == null) {
				// 若socket为null, 返回SocketState.CLOSE.
				return SocketState.CLOSED;
			}
			
			// 从连接池中获取制定对象的处理器
			Processor<S> processor = connections.get(socket);
			if (status == SocketStatus.DISCONNECT && processor == null) {
				return SocketState.CLOSED;
			}

			wrapper.setAsync(false);
			ContainerThreadMarker.markAsContainerThread();

			try {
				if (processor == null) {
					processor = recycledProcessors.poll();
				}
				if (processor == null) {
					processor = createProcessor();
				}

				initSsl(wrapper, processor);
				
				// 将状态设置为CLOSED
				SocketState state = SocketState.CLOSED;
				do {
					if (status == SocketStatus.CLOSE_NOW) {
						processor.errorDispatch();
						state = SocketState.CLOSED;
					} else if (status == SocketStatus.DISCONNECT
							&& !processor.isComet()) {
						// Do nothing here, just wait for it to get recycled
						// Don't do this for Comet we need to generate an end
						// event (see BZ 54022)
					} else if (processor.isAsync()
							|| state == SocketState.ASYNC_END) {
						state = processor.asyncDispatch(status);
					} else if (processor.isComet()) {
						state = processor.event(status);
					} else if (processor.getUpgradeInbound() != null) {
						state = processor.upgradeDispatch();
					} else if (processor.isUpgrade()) {
						state = processor.upgradeDispatch(status);
					} else {
						state = processor.process(wrapper);
					}

					if (state != SocketState.CLOSED && processor.isAsync()) {
						state = processor.asyncPostProcess();
					}

					if (state == SocketState.UPGRADING) {
						// Get the HTTP upgrade handler
						HttpUpgradeHandler httpUpgradeHandler = processor
								.getHttpUpgradeHandler();
						// Release the Http11 processor to be re-used
						release(wrapper, processor, false, false);
						// Create the upgrade processor
						processor = createUpgradeProcessor(wrapper,
								httpUpgradeHandler);
						// Mark the connection as upgraded
						wrapper.setUpgraded(true);
						// Associate with the processor with the connection
						connections.put(socket, processor);
						// Initialise the upgrade handler (which may trigger
						// some IO using the new protocol which is why the lines
						// above are necessary)
						// This cast should be safe. If it fails the error
						// handling for the surrounding try/catch will deal with
						// it.
						httpUpgradeHandler.init((WebConnection) processor);
					} else if (state == SocketState.UPGRADING_TOMCAT) {
						// Get the UpgradeInbound handler
						org.apache.coyote.http11.upgrade.UpgradeInbound inbound = processor
								.getUpgradeInbound();
						// Release the Http11 processor to be re-used
						release(wrapper, processor, false, false);
						// Create the light-weight upgrade processor
						processor = createUpgradeProcessor(wrapper, inbound);
						inbound.onUpgradeComplete();
					}
					if (getLog().isDebugEnabled()) {
						getLog().debug(
								"Socket: [" + wrapper + "], Status in: ["
										+ status + "], State out: [" + state
										+ "]");
					}
				} while (state == SocketState.ASYNC_END
						|| state == SocketState.UPGRADING
						|| state == SocketState.UPGRADING_TOMCAT);

				if (state == SocketState.LONG) {
					// In the middle of processing a request/response. Keep the
					// socket associated with the processor. Exact requirements
					// depend on type of long poll
					connections.put(socket, processor);
					longPoll(wrapper, processor);
				} else if (state == SocketState.OPEN) {
					// In keep-alive but between requests. OK to recycle
					// processor. Continue to poll for the next request.
					connections.remove(socket);
					release(wrapper, processor, false, true);
				} else if (state == SocketState.SENDFILE) {
					// Sendfile in progress. If it fails, the socket will be
					// closed. If it works, the socket will be re-added to the
					// poller
					connections.remove(socket);
					release(wrapper, processor, false, false);
				} else if (state == SocketState.UPGRADED) {
					// Need to keep the connection associated with the processor
					connections.put(socket, processor);
					// Don't add sockets back to the poller if this was a
					// non-blocking write otherwise the poller may trigger
					// multiple read events which may lead to thread starvation
					// in the connector. The write() method will add this socket
					// to the poller if necessary.
					if (status != SocketStatus.OPEN_WRITE) {
						longPoll(wrapper, processor);
					}
				} else {
					// Connection closed. OK to recycle the processor. Upgrade
					// processors are not recycled.
					connections.remove(socket);
					if (processor.isUpgrade()) {
						processor.getHttpUpgradeHandler().destroy();
					} else if (processor instanceof org.apache.coyote.http11.upgrade.UpgradeProcessor) {
						// NO-OP
					} else {
						release(wrapper, processor, true, false);
					}
				}
				return state;
			} catch (java.net.SocketException e) {
				// SocketExceptions are normal
				getLog().debug(
						sm.getString("abstractConnectionHandler.socketexception.debug"),
						e);
			} catch (java.io.IOException e) {
				// IOExceptions are normal
				getLog().debug(
						sm.getString("abstractConnectionHandler.ioexception.debug"),
						e);
			}
			// Future developers: if you discover any other
			// rare-but-nonfatal exceptions, catch them here, and log as
			// above.
			catch (Throwable e) {
				ExceptionUtils.handleThrowable(e);
				// any other exception or error is odd. Here we log it
				// with "ERROR" level, so it will show up even on
				// less-than-verbose logs.
				getLog().error(sm.getString("abstractConnectionHandler.error"),
						e);
			}
			// Make sure socket/processor is removed from the list of current
			// connections
			connections.remove(socket);
			// Don't try to add upgrade processors back into the pool
			if (!(processor instanceof org.apache.coyote.http11.upgrade.UpgradeProcessor)
					&& !processor.isUpgrade()) {
				release(wrapper, processor, true, false);
			}
			return SocketState.CLOSED;
		}

		protected abstract P createProcessor();

		protected abstract void initSsl(SocketWrapper<S> socket,
				Processor<S> processor);

		protected abstract void longPoll(SocketWrapper<S> socket,
				Processor<S> processor);

		protected abstract void release(SocketWrapper<S> socket,
				Processor<S> processor, boolean socketClosing,
				boolean addToPoller);

		/**
		 * @deprecated Will be removed in Tomcat 8.0.x.
		 */
		@Deprecated
		protected abstract Processor<S> createUpgradeProcessor(
				SocketWrapper<S> socket,
				org.apache.coyote.http11.upgrade.UpgradeInbound inbound)
				throws IOException;

		protected abstract Processor<S> createUpgradeProcessor(
				SocketWrapper<S> socket, HttpUpgradeHandler httpUpgradeProcessor)
				throws IOException;

		protected void register(AbstractProcessor<S> processor) {
			if (getProtocol().getDomain() != null) {
				synchronized (this) {
					try {
						long count = registerCount.incrementAndGet();
						RequestInfo rp = processor.getRequest()
								.getRequestProcessor();
						rp.setGlobalProcessor(global);
						ObjectName rpName = new ObjectName(getProtocol()
								.getDomain()
								+ ":type=RequestProcessor,worker="
								+ getProtocol().getName()
								+ ",name="
								+ getProtocol().getProtocolName()
								+ "Request"
								+ count);
						if (getLog().isDebugEnabled()) {
							getLog().debug("Register " + rpName);
						}
						Registry.getRegistry(null, null).registerComponent(rp,
								rpName, null);
						rp.setRpName(rpName);
					} catch (Exception e) {
						getLog().warn("Error registering request");
					}
				}
			}
		}

		protected void unregister(Processor<S> processor) {
			if (getProtocol().getDomain() != null) {
				synchronized (this) {
					try {
						Request r = processor.getRequest();
						if (r == null) {
							// Probably an UpgradeProcessor
							return;
						}
						RequestInfo rp = r.getRequestProcessor();
						rp.setGlobalProcessor(null);
						ObjectName rpName = rp.getRpName();
						if (getLog().isDebugEnabled()) {
							getLog().debug("Unregister " + rpName);
						}
						Registry.getRegistry(null, null).unregisterComponent(
								rpName);
						rp.setRpName(null);
					} catch (Exception e) {
						getLog().warn("Error unregistering request", e);
					}
				}
			}
		}
	}

	/**
	 * 重置Processor
	 * 
	 * @author songjianc
	 *
	 * @param <P>
	 * @param <S>
	 */
	protected static class RecycledProcessors<P extends Processor<S>, S>
			extends ConcurrentLinkedQueue<Processor<S>> {

		private static final long serialVersionUID = 1L;
		private transient AbstractConnectionHandler<S, P> handler;
		protected AtomicInteger size = new AtomicInteger(0);

		public RecycledProcessors(AbstractConnectionHandler<S, P> handler) {
			this.handler = handler;
		}

		@Override
		public boolean offer(Processor<S> processor) {
			int cacheSize = handler.getProtocol().getProcessorCache();
			boolean offer = cacheSize == -1 ? true : size.get() < cacheSize;
			// avoid over growing our cache or add after we have stopped
			boolean result = false;
			if (offer) {
				result = super.offer(processor);
				if (result) {
					size.incrementAndGet();
				}
			}
			if (!result)
				handler.unregister(processor);
			return result;
		}

		@Override
		public Processor<S> poll() {
			Processor<S> result = super.poll();
			if (result != null) {
				size.decrementAndGet();
			}
			return result;
		}

		@Override
		public void clear() {
			Processor<S> next = poll();
			while (next != null) {
				handler.unregister(next);
				next = poll();
			}
			super.clear();
			size.set(0);
		}
	}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值