Download presentation
Presentation is loading. Please wait.
Published byBerniece Price Modified over 6 years ago
1
Customizable Operating Systems with Aspect-Oriented Programming
RTOSLAB, SNU. Jiyong Park
2
Contents Overview AOP Real Example
A Survey of Customizability in Operating Systems Research AOP Aspect-Oriented Programming An Overview of AspectJ Real Example Using AspectC to Improve the Modularity of Path-Specific Customization in Operating System Code
3
A Survey of Customizability in Operating Systems Research
Overview A Survey of Customizability in Operating Systems Research G.Denys – CoWare F.Piessens and F.Matthijs – Katholieke Universiteit Leuven ACM Computing Surveys (CSUR) December 2002
4
Our Goal Operating system that is For Domain Component-based Adaptable
Application-specific Customizable For Better fit to specific application Better performance, smaller memory foot-print Easy integration Easy to understand and to evolve Domain Embedded systems Very tiny device ~ Mobile appliance
5
Our Goal More specifically
Add, remove and replace components or subsystems Filesystem, HAL, Network subsystem, Device driver … Change policies Scheduling algorithm, Page replacement policy, … Modify parameters Number of priorities, TCP timeout value, … Coarse Fine
6
Taxonomy Time of adaptation Initiator of adaptation
Design, build, or installation-time Boot or run-time Initiator of adaptation Human (designer or administrator) Application Operating system itself
7
Human Initiated Adaptation
Static By designer Application domain is known in advance Built by customizing the framework Mainly for embedded system Dynamic By administator Boot-time, kernel paramters Run-time, kernel modules, performance parameters (/proc)
8
Application Initiated Adaptation
Static Impossible Dynamic Mainly for general-purpose operating systems Application know its needs and usage patterns e.g. Memory access pattern, scheduling need Cause some overhead (not much problem) For PDA, set-top boxes Application changes, but not abruptly Application select predefined policy Application give ‘user code’ to OS
9
Automatic Adaptation Static Dynamic
Portability – detecting on which platform the OS is built Dynamic For general-purpose operating system Beyond our interest
10
Design Choices Static Dynamic Human Application Operating system
By initiator Human Application Operating system Static Our goal General framework needed Impossible Portability Dynamic Administrator Boot parameter Kernel modules Performance parameter Choose predefined policies Application give code Beyond our scope By time of adaptation
11
Design Choices Component or subsystem Policies Parameters
Static, Designer initiated Policies Static, Designer initiated (memory allocation algorithm, …) Dynamic, Application initiated (scheduling policies, …) Parameters Dynamic, Application initiated (/proc like)
12
Related Research Projects
Human Application Operating system Static OSKit Choices Scout Pebble Impossible (Portability through conditional compilation) Dynamic Production operating systems (Linux, …) Exokernel, L4, Kea Pebble, SPACE EROS, Fluke, V++ MetaOS, SPIN VINO Synthetix (VINO)
13
My Problems 1. How to organize the framework? 2. Cross-cutting problem
Path-specific optimization Prefatch, pace-replacement, scheduling, … Network, Disk related work, … Layer violation Hard to understand and modularize subsystem policy
14
Example of Path-Specific Optimization
HW flow control in Linux ip_rcv xxx_rcv xxx_rcv Network Layer (IP, …) net_rx_action sar_disable_int sar_enable_int stimuli netif_rx Generic Network Procotol Processing Layer Network Device sar_done_int
15
Example of Path-Specific Optimization
HW flow control code Scattered between two layers Not modular (#ifdef) Another example Fast route Routing decision is done in interrupt context Device driver, Network layer modified
16
Aspect-Oriented Programming
AOP (1/2) Aspect-Oriented Programming Gregor Kiczales, … Xerox Palo Alto Research Center European Conference on Object-Oriented Programming June 1997
17
Example of Bad Modularity
/* * * ==================================================================== * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * reserved. * Copyright (c) 1999 The Apache Software Foundation. All rights * The Apache Software License, Version 1.1 * 1. Redistributions of source code must retain the above copyright * are met: * the documentation and/or other materials provided with the * distribution. * notice, this list of conditions and the following disclaimer in * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer. itself, * if and wherever such third-party acknowlegements normally appear. * Apache Software Foundation ( * Alternately, this acknowlegement may appear in the software * "This product includes software developed by the * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * Foundation" must not be used to endorse or promote products * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * 5. Products derived from this software may not be called "Apache" * permission, please contact derived * from this software without prior written permission. For written * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * This software consists of voluntary contributions made by many * SUCH DAMAGE. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * information on the Apache Software Foundation, please see * individuals on behalf of the Apache Software Foundation. For more * [Additional notices, if required by prior licensing conditions] */ * < package org.apache.tomcat.session; import java.net.*; import java.util.*; import java.io.*; import org.apache.tomcat.util.StringManager; import org.apache.tomcat.core.*; * Core implementation of an application level session James Duncan Davidson /** import javax.servlet.http.*; import javax.servlet.*; James Todd Jason Hunter private String id; private Hashtable values = new Hashtable(); private StringManager sm = public class ApplicationSession implements HttpSession { StringManager.getManager("org.apache.tomcat.session"); private ServerSession serverSession; private boolean valid = true; private int inactiveInterval = -1; private long lastAccessed = creationTime; private Context context; private long creationTime = System.currentTimeMillis();; private long thisAccessTime = creationTime; this.inactiveInterval = context.getSessionTimeOut(); this.context = context; this.id = id; Context context) { ApplicationSession(String id, ServerSession serverSession, this.serverSession = serverSession; } this.inactiveInterval *= 60; if (this.inactiveInterval != -1) { return serverSession; ServerSession getServerSession() { * inactivities can be dealt with accordingly. * Called by context when request comes in so that accesses and void accessed() { thisAccessTime = System.currentTimeMillis(); lastAccessed = thisAccessTime; // set last accessed to thisAccessTime as it will be left over // from the previous access int thisInterval = if (inactiveInterval != -1) { void validate() { validate(); invalidate(); if (thisInterval > inactiveInterval) { (int)(System.currentTimeMillis() - lastAccessed) / 1000; // if we have an inactive interval, check to see if we've exceeded it if (valid) { // HTTP SESSION IMPLEMENTATION METHODS String msg = sm.getString("applicationSession.session.ise"); public String getId() { throw new IllegalStateException(msg); } else { return id; return creationTime; public long getCreationTime() { public long getLastAccessedTime() { return new SessionContextImpl(); public HttpSessionContext getSessionContext() { return lastAccessed; public void invalidate() { // remove everything in the session serverSession.removeApplicationSession(context); removeValue(name); String name = (String)enum.nextElement(); Enumeration enum = values.keys(); while (enum.hasMoreElements()) { public boolean isNew() { valid = false; if (! valid) { return true; return false; if (thisAccessTime == creationTime) { public void setAttribute(String name, Object value) { setAttribute(name, value); public void putValue(String name, Object value) { removeValue(name); // remove any existing binding throw new IllegalArgumentException(msg); String msg = sm.getString("applicationSession.value.iae"); if (name == null) { new HttpSessionBindingEvent(this, name); ((HttpSessionBindingListener)value).valueBound(e); HttpSessionBindingEvent e = if (value != null && value instanceof HttpSessionBindingListener) { values.put(name, value); public Object getAttribute(String name) { return getAttribute(name); public Object getValue(String name) { return values.get(name); public String[] getValueNames() { names.addElement(e.nextElement()); while (e.hasMoreElements()) { Vector names = new Vector(); Enumeration e = getAttributeNames(); names.copyInto(valueNames); String[] valueNames = new String[names.size()]; public Enumeration getAttributeNames() { return valueNames; return (Enumeration)valuesClone.keys(); Hashtable valuesClone = (Hashtable)values.clone(); public void removeAttribute(String name) { removeAttribute(name); public void removeValue(String name) { Object o = values.get(name); ((HttpSessionBindingListener)o).valueUnbound(e); new HttpSessionBindingEvent(this,name); if (o instanceof HttpSessionBindingListener) { public void setMaxInactiveInterval(int interval) { values.remove(name); public int getMaxInactiveInterval() { inactiveInterval = interval; return inactiveInterval; // ; * Standard implementation of the <b>Session</b> interface. This object is /** * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the * <p> * to a different JVM for distributable session support. * serializable, so that it can be stored in persistent storage or transferred * internal (Session) and application level (HttpSession) view of the session. Craig R. McClanahan * * HttpSession view of this instance back to a Session view. * However, because the class itself is not declared public, Java logic outside * of the <code>org.apache.tomcat.session</code> package cannot cast an $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ // Constructors implements HttpSession, Session { */ final class StandardSession manager The manager with which this Session is associated * Construct a new Session associated with the specified Manager. this.manager = manager; } super(); public StandardSession(Manager manager) { private long lastAccessedTime = creationTime; * The last accessed time for this Session. * The maximum time interval, in seconds, between client requests before private Manager manager = null; * The Manager with which this Session is associated. private int maxInactiveInterval = -1; * indicates that the session should never time out. * the servlet container may invalidate this session. A negative time private boolean isNew = true; * Flag indicating whether this session is new or not. * Flag indicating whether this session is valid or not. private boolean isValid = false; private StringManager sm = StringManager.getManager("org.apache.tomcat.session"); * The string manager for this package. private static HttpSessionContext sessionContext = null; * The HTTP session context associated with this session. private long thisAccessedTime = creationTime; * The current accessed time for this session. // Session Properties * Set the creation time for this session. This method is called by the time The new creation time * Manager when an existing Session instance is reused. this.thisAccessedTime = time; this.lastAccessedTime = time; public void setCreationTime(long time) { this.creationTime = time; public String getId() { * Return the session identifier for this session. return (this.id); id The new session identifier * Set the session identifier for this session. public void setId(String id) { if ((this.id != null) && (manager != null) && if ((manager != null) && (manager instanceof ManagerBase)) this.id = id; (manager instanceof ManagerBase)) ((ManagerBase) manager).remove(this); ((ManagerBase) manager).add(this); * Return descriptive information about this Session implementation and public String getInfo() { * <code><description>/<version></code>. * the corresponding version number, in the format return (this.info); * Return the last time the client sent a request associated with this * a value associated with the session, do not affect the access time. * GMT. Actions that your application takes, such as getting or setting * session, as the number of milliseconds since midnight, January 1, 1970 return (this.lastAccessedTime); public long getLastAccessedTime() { * Return the Manager within which this Session is valid. return (this.manager); public Manager getManager() { public void setManager(Manager manager) { manager The new Manager * Set the Manager within which this Session is valid. * time indicates that the session should never time out. * before the servlet container will invalidate the session. A negative * Return the maximum time interval, in seconds, between client requests public int getMaxInactiveInterval() { * an invalidated session IllegalStateException if this method is called on return (this.maxInactiveInterval); * Update the accessed time information for this session. This method * should be called by the context when a request comes in for a particular this.thisAccessedTime = System.currentTimeMillis(); this.lastAccessedTime = this.thisAccessedTime; public void access() { * session, even if the application does not reference it. this.isNew=false; public void expire() { * without triggering an exception if the session has already expired. * Perform the internal processing required to invalidate this session, // Remove this session from our manager's active sessions String attr = (String) attrs.nextElement(); while (attrs.hasMoreElements()) { Enumeration attrs = getAttributeNames(); // Unbind any objects associated with this session Vector results = new Vector(); while (names.hasMoreElements()) { removeAttribute(name); String name = (String) names.nextElement(); Enumeration names = results.elements(); results.addElement(attr); setValid(false); // Mark this session as invalid isNew The new value for the <code>isNew</code> flag * Set the <code>isNew</code> flag for this session. void setNew(boolean isNew) { this.isNew = isNew; void setValid(boolean isValid) { isValid The new value for the <code>isValid</code> flag * Set the <code>isValid</code> flag for this session. // HttpSession Properties this.isValid = isValid; IllegalStateException if this method is called on an * midnight, January 1, 1970 GMT. * Return the time when this session was created, in milliseconds since return (this.creationTime); public long getCreationTime() { * invalidated session * replacement. It will be removed in a future version of the As of Version 2.1, this method is deprecated and has no * Return the session context with which this session is associated. * Java Servlet API. sessionContext = new StandardSessionContext(); return (sessionContext); if (sessionContext == null) public HttpSessionContext getSessionContext() { // HttpSession Public Methods * Return the object bound with the specified name in this session, or name Name of the attribute to be returned * <code>null</code> if no object is bound with that name. return (attributes.get(name)); public Object getAttribute(String name) { * containing the names of the objects bound to this session. * Return an <code>Enumeration</code> of <code>String</code> objects return (attributes.keys()); public Enumeration getAttributeNames() { name Name of the value to be returned As of Version 2.2, this method is replaced by return (getAttribute(name)); public Object getValue(String name) { * <code>getAttribute()</code> * are no such objects, a zero-length array is returned. * Return the set of names of objects bound to this session. If there public String[] getValueNames() { * <code>getAttributeNames()</code> return (names); names[i] = (String) results.elementAt(i); for (int i = 0; i < names.length; i++) String names[] = new String[results.size()]; * Invalidates this session and unbinds any objects bound to it. expire(); // Cause this session to expire public void invalidate() { * example, if the server used only cookie-based sessions, and the client * session, or if the client chooses not to join the session. For * Return <code>true</code> if the client does not yet know about the * request. * has disabled the use of cookies, then a session would be new on each return (this.isNew); public boolean isNew() { * Remove the object bound with the specified name from this session. If * After this method executes, and if the object implements * does nothing. * the session does not have an object bound with this name, this method * <code>valueUnbound()</code> on the object. name Name of the object to remove from this session. * <code>HttpSessionBindingListener</code>, the container calls synchronized (attributes) { Object object = attributes.get(name); public void removeAttribute(String name) { ((HttpSessionBindingListener) object).valueUnbound (new HttpSessionBindingEvent((HttpSession) this, name)); if (object instanceof HttpSessionBindingListener) { // System.out.println( "Removing attribute " + name ); if (object == null) return; attributes.remove(name); * replaced. * Bind an object to this session, using the specified name. If an object * of the same name is already bound to this session, the object is value Object to be bound, cannot be null * <code>valueBound()</code> on the object. name Name to which the object is bound, cannot be null * non-serializable object in an environment marked distributable. IllegalArgumentException if an attempt is made to add a throw new IllegalArgumentException public void setAttribute(String name, Object value) { attributes.put(name, value); (sm.getString("standardSession.setAttribute.iae")); if ((manager != null) && manager.getDistributable() && !(value instanceof Serializable)) ((HttpSessionBindingListener) value).valueBound if (value instanceof HttpSessionBindingListener) // HttpSession Private Methods stream The input stream to read from * is not restored by this method, and must be set explicitly. * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager * object input stream. * Read a serialized version of this session object from the specified IOException if an input/output error occurs ClassNotFoundException if an unknown class is specified id = (String) stream.readObject(); lastAccessedTime = ((Long) stream.readObject()).longValue(); creationTime = ((Long) stream.readObject()).longValue(); // Deserialize the scalar instance variables (except Manager) private void readObject(ObjectInputStream stream) throws ClassNotFoundException, IOException { isNew = ((Boolean) stream.readObject()).booleanValue(); maxInactiveInterval = ((Integer) stream.readObject()).intValue(); String name = (String) stream.readObject(); Object value = (Object) stream.readObject(); for (int i = 0; i < n; i++) { int n = ((Integer) stream.readObject()).intValue(); // Deserialize the attribute count and attribute values isValid = ((Boolean) stream.readObject()).booleanValue(); * object output stream. * Write a serialized version of this session object to the specified * explicitly. * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable * <code>readObject()</code>, you must set the associated Manager * in the serialized representation of this Session. After calling * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored * Manager is set to <code>true</code>. stream The output stream to write to * be sure the <code>distributable</code> property of our associated * will be silently ignored. If you do not want any such attributes, stream.writeObject(new Long(creationTime)); stream.writeObject(id); // Write the scalar instance variables (except Manager) private void writeObject(ObjectOutputStream stream) throws IOException { stream.writeObject(new Boolean(isNew)); // Accumulate the names of serializable attributes stream.writeObject(new Boolean(isValid)); stream.writeObject(new Integer(maxInactiveInterval)); stream.writeObject(new Long(lastAccessedTime)); if (value instanceof Serializable) Object value = attributes.get(attr); stream.writeObject(new Integer(results.size())); // Serialize the attribute count and the attribute values stream.writeObject(attributes.get(name)); stream.writeObject(name); Enumeration getAttributeNames() | String[] getValueNames() | Object getAttribute(String) | long getCreationTime() | crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | static advice(StandardSession s): invalidate(s) { before { void setAttribute(String, Object)); void removeAttribute(String) | void invalidate() | boolean isNew() | + ".ise")); (s.sm.getString("standardSession." + thisJoinPoint.methodName throw new IllegalStateException if (!s.isValid()) // Private Class * when <code>HttpSession.getSessionContext()</code> is called. * This class is a dummy implementation of the <code>HttpSessionContext</code> * interface, to conform to the requirement that such an object be returned As of Java Servlet API 2.1 with no replacement. The private Vector dummy = new Vector(); final class StandardSessionContext implements HttpSessionContext { * interface will be removed in a future version of this API. * This method must return an empty <code>Enumeration</code> As of Java Servlet API 2.1 with no replacement. * within this context. * Return the session identifiers of all sessions defined * and will be removed in a future version of the API. return (dummy.elements()); public Enumeration getIds() { * This method must return null and will be removed in a id Session identifier for which to look up a session * specified session identifier. * Return the <code>HttpSession</code> associated with the public HttpSession getSession(String id) { * future version of the API. return (null); scattering – spread around tangling – code in one region addresses multiple concerns scattering and tangling (S&T) tend to appear together; they describe different facets of the same problem package org.apache.tomcat.session; import org.apache.tomcat.core.*; import javax.servlet.http.*; import javax.servlet.*; import java.util.*; import org.apache.tomcat.util.StringManager; import java.io.*; import java.net.*; James Duncan Davidson public class ServerSession { */ James Todd * /** * Core implementation of a server session private String id; private long thisAccessTime = creationTime; private long creationTime = System.currentTimeMillis();; private Hashtable appSessions = new Hashtable(); private Hashtable values = new Hashtable(); private StringManager sm = StringManager.getManager("org.apache.tomcat.session"); ServerSession(String id) { private long lastAccessed = creationTime; private int inactiveInterval = -1; return id; public String getId() { } this.id = id; public long getLastAccessedTime() { return creationTime; public long getCreationTime() { (ApplicationSession)appSessions.get(context); ApplicationSession appSession = public ApplicationSession getApplicationSession(Context context, return lastAccessed; boolean create) { // XXX if (appSession == null && create) { appSession = new ApplicationSession(id, this, context); appSessions.put(context, appSession); // sync to ensure valid? return appSession; // a new appSession // make sure that we haven't gone over the end of our // inactive interval -- if so, invalidate and create appSessions.remove(context); void removeApplicationSession(Context context) { * inactivities can be dealt with accordingly. * Called by context when request comes in so that accesses and thisAccessTime = System.currentTimeMillis(); lastAccessed = thisAccessTime; // from the previous access void accessed() { // set last accessed to thisAccessTime as it will be left over void validate() void validate() { (int)(System.currentTimeMillis() - lastAccessed) / 1000; int thisInterval = if (inactiveInterval != -1) { // if we have an inactive interval, check to see if // we've exceeded it if (thisInterval > inactiveInterval) { ssm.removeSession(this); ServerSessionManager.getManager(); invalidate(); ServerSessionManager ssm = (ApplicationSession)appSessions.get(key); Object key = enum.nextElement(); while (enum.hasMoreElements()) { Enumeration enum = appSessions.keys(); synchronized void invalidate() { appSession.invalidate(); String msg = sm.getString("serverSession.value.iae"); throw new IllegalArgumentException(msg); if (name == null) { public void putValue(String name, Object value) { removeValue(name); // remove any existing binding public Object getValue(String name) { values.put(name, value); return values.keys(); public Enumeration getValueNames() { return values.get(name); public void setMaxInactiveInterval(int interval) { values.remove(name); public void removeValue(String name) { public int getMaxInactiveInterval() { inactiveInterval = interval; // solution for this, but we'll determine something else later. // from this while we are reaping. This isn't the most optimal // sync'd for safty -- no other thread should be getting something return inactiveInterval; synchronized void reap() { appSession.validate(); page taken from kiczales’ slide
18
Example of Good Modularity
separated – implementation of a concern can be treated as relatively separate entity localized – implementation of a concern appears in one part of program modular – above + has a clear, well defined interface to rest of system /* * * ==================================================================== * modification, are permitted provided that the following conditions * Redistribution and use in source and binary forms, with or without * reserved. * Copyright (c) 1999 The Apache Software Foundation. All rights * The Apache Software License, Version 1.1 * are met: * the documentation and/or other materials provided with the * distribution. * notice, this list of conditions and the following disclaimer in * 2. Redistributions in binary form must reproduce the above copyright * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * Alternately, this acknowlegement may appear in the software * Apache Software Foundation ( * "This product includes software developed by the * any, must include the following acknowlegement: * 3. The end-user documentation included with the redistribution, if derived * from this software without prior written permission. For written * Foundation" must not be used to endorse or promote products * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software itself, * if and wherever such third-party acknowlegements normally appear. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * permission of the Apache Group. * nor may "Apache" appear in their names without prior written * 5. Products derived from this software may not be called "Apache" * permission, please contact * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * SUCH DAMAGE. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * information on the Apache Software Foundation, please see * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * [Additional notices, if required by prior licensing conditions] */ * < package org.apache.tomcat.session; import javax.servlet.*; import java.util.*; import javax.servlet.http.*; import java.net.*; import org.apache.tomcat.core.*; import org.apache.tomcat.util.StringManager; import java.io.*; /** James Todd Jason Hunter James Duncan Davidson * Core implementation of an application level session public class ApplicationSession implements HttpSession { private Context context; private long creationTime = System.currentTimeMillis();; private ServerSession serverSession; private String id; private StringManager sm = StringManager.getManager("org.apache.tomcat.session"); private Hashtable values = new Hashtable(); this.serverSession = serverSession; this.context = context; Context context) { ApplicationSession(String id, ServerSession serverSession, private boolean valid = true; private long thisAccessTime = creationTime; this.id = id; } this.inactiveInterval *= 60; if (this.inactiveInterval != -1) { this.inactiveInterval = context.getSessionTimeOut(); return serverSession; ServerSession getServerSession() { * inactivities can be dealt with accordingly. * Called by context when request comes in so that accesses and if (valid) { // HTTP SESSION IMPLEMENTATION METHODS public String getId() { String msg = sm.getString("applicationSession.session.ise"); throw new IllegalStateException(msg); return id; } else { return creationTime; public long getCreationTime() { return new SessionContextImpl(); public HttpSessionContext getSessionContext() { public void invalidate() { // remove everything in the session serverSession.removeApplicationSession(context); removeValue(name); String name = (String)enum.nextElement(); Enumeration enum = values.keys(); while (enum.hasMoreElements()) { public boolean isNew() { valid = false; if (! valid) { return true; return false; if (thisAccessTime == creationTime) { public void setAttribute(String name, Object value) { setAttribute(name, value); public void putValue(String name, Object value) { removeValue(name); // remove any existing binding throw new IllegalArgumentException(msg); String msg = sm.getString("applicationSession.value.iae"); if (name == null) { new HttpSessionBindingEvent(this, name); ((HttpSessionBindingListener)value).valueBound(e); HttpSessionBindingEvent e = if (value != null && value instanceof HttpSessionBindingListener) { values.put(name, value); public Object getAttribute(String name) { return getAttribute(name); public Object getValue(String name) { return values.get(name); public String[] getValueNames() { names.addElement(e.nextElement()); while (e.hasMoreElements()) { Vector names = new Vector(); Enumeration e = getAttributeNames(); names.copyInto(valueNames); String[] valueNames = new String[names.size()]; public Enumeration getAttributeNames() { return valueNames; return (Enumeration)valuesClone.keys(); Hashtable valuesClone = (Hashtable)values.clone(); public void removeAttribute(String name) { removeAttribute(name); public void removeValue(String name) { Object o = values.get(name); ((HttpSessionBindingListener)o).valueUnbound(e); new HttpSessionBindingEvent(this,name); if (o instanceof HttpSessionBindingListener) { public void setMaxInactiveInterval(int interval) { values.remove(name); public int getMaxInactiveInterval() { inactiveInterval = interval; return inactiveInterval; // * Core implementation of a server session public class ServerSession { private Hashtable appSessions = new Hashtable(); ServerSession(String id) { private int inactiveInterval = -1; private long lastAccessed = creationTime; return lastAccessed; public long getLastAccessedTime() { if (appSession == null && create) { ApplicationSession appSession = (ApplicationSession)appSessions.get(context); boolean create) { public ApplicationSession getApplicationSession(Context context, appSessions.put(context, appSession); appSession = new ApplicationSession(id, this, context); // sync to ensure valid? // XXX return appSession; // a new appSession // make sure that we haven't gone over the end of our // inactive interval -- if so, invalidate and create appSessions.remove(context); void removeApplicationSession(Context context) { void validate() ynchronized void invalidate() { Enumeration enum = appSessions.keys(); appSession.invalidate(); (ApplicationSession)appSessions.get(key); Object key = enum.nextElement(); String msg = sm.getString("serverSession.value.iae"); return values.keys(); public Enumeration getValueNames() { synchronized void reap() { // sync'd for safty -- no other thread should be getting something // solution for this, but we'll determine something else later. // from this while we are reaping. This isn't the most optimal appSession.validate(); ; * Standard implementation of the <b>Session</b> interface. This object is * <b>IMPLEMENTATION NOTE</b>: An instance of this class represents both the * <p> * to a different JVM for distributable session support. * serializable, so that it can be stored in persistent storage or transferred * internal (Session) and application level (HttpSession) view of the session. * HttpSession view of this instance back to a Session view. * of the <code>org.apache.tomcat.session</code> package cannot cast an * However, because the class itself is not declared public, Java logic outside $Revision: 1.2 $ $Date: 2000/05/15 17:54:10 $ Craig R. McClanahan // Constructors implements HttpSession, Session { final class StandardSession * Construct a new Session associated with the specified Manager. this.manager = manager; super(); public StandardSession(Manager manager) { manager The manager with which this Session is associated private long lastAccessedTime = creationTime; * The last accessed time for this Session. private Manager manager = null; * The Manager with which this Session is associated. * the servlet container may invalidate this session. A negative time * The maximum time interval, in seconds, between client requests before private int maxInactiveInterval = -1; * indicates that the session should never time out. private boolean isNew = true; * Flag indicating whether this session is new or not. * The string manager for this package. private boolean isValid = false; * Flag indicating whether this session is valid or not. private static HttpSessionContext sessionContext = null; * The HTTP session context associated with this session. private long thisAccessedTime = creationTime; * The current accessed time for this session. // Session Properties time The new creation time * Manager when an existing Session instance is reused. * Set the creation time for this session. This method is called by the this.lastAccessedTime = time; this.thisAccessedTime = time; public void setCreationTime(long time) { this.creationTime = time; * Return the session identifier for this session. return (this.id); id The new session identifier * Set the session identifier for this session. ((ManagerBase) manager).remove(this); (manager instanceof ManagerBase)) if ((this.id != null) && (manager != null) && public void setId(String id) { ((ManagerBase) manager).add(this); if ((manager != null) && (manager instanceof ManagerBase)) * Return descriptive information about this Session implementation and public String getInfo() { * <code><description>/<version></code>. * the corresponding version number, in the format return (this.info); * Return the Manager within which this Session is valid. return (this.manager); public Manager getManager() { public void setManager(Manager manager) { manager The new Manager * Set the Manager within which this Session is valid. * before the servlet container will invalidate the session. A negative * Return the maximum time interval, in seconds, between client requests * an invalidated session IllegalStateException if this method is called on * time indicates that the session should never time out. return (this.maxInactiveInterval); * Perform the internal processing required to invalidate this session, // Remove this session from our manager's active sessions public void expire() { * without triggering an exception if the session has already expired. results.addElement(attr); String attr = (String) attrs.nextElement(); while (attrs.hasMoreElements()) { // Unbind any objects associated with this session Vector results = new Vector(); Enumeration attrs = getAttributeNames(); String name = (String) names.nextElement(); while (names.hasMoreElements()) { Enumeration names = results.elements(); setValid(false); // Mark this session as invalid isNew The new value for the <code>isNew</code> flag * Set the <code>isNew</code> flag for this session. void setNew(boolean isNew) { this.isNew = isNew; isValid The new value for the <code>isValid</code> flag * Set the <code>isValid</code> flag for this session. void setValid(boolean isValid) { // HttpSession Properties this.isValid = isValid; * Return the time when this session was created, in milliseconds since * invalidated session IllegalStateException if this method is called on an * midnight, January 1, 1970 GMT. return (this.creationTime); * Return the session context with which this session is associated. * Java Servlet API. * replacement. It will be removed in a future version of the As of Version 2.1, this method is deprecated and has no return (sessionContext); sessionContext = new StandardSessionContext(); if (sessionContext == null) // HttpSession Public Methods name Name of the attribute to be returned * <code>null</code> if no object is bound with that name. * Return the object bound with the specified name in this session, or return (attributes.get(name)); * containing the names of the objects bound to this session. * Return an <code>Enumeration</code> of <code>String</code> objects return (attributes.keys()); name Name of the value to be returned As of Version 2.2, this method is replaced by return (getAttribute(name)); * <code>getAttribute()</code> * are no such objects, a zero-length array is returned. * Return the set of names of objects bound to this session. If there * <code>getAttributeNames()</code> return (names); names[i] = (String) results.elementAt(i); for (int i = 0; i < names.length; i++) String names[] = new String[results.size()]; * Invalidates this session and unbinds any objects bound to it. // Cause this session to expire expire(); * example, if the server used only cookie-based sessions, and the client * session, or if the client chooses not to join the session. For * Return <code>true</code> if the client does not yet know about the * request. * has disabled the use of cookies, then a session would be new on each return (this.isNew); * Remove the object bound with the specified name from this session. If * does nothing. * the session does not have an object bound with this name, this method name Name of the object to remove from this session. * <code>valueUnbound()</code> on the object. * <code>HttpSessionBindingListener</code>, the container calls * After this method executes, and if the object implements Object object = attributes.get(name); synchronized (attributes) { ((HttpSessionBindingListener) object).valueUnbound (new HttpSessionBindingEvent((HttpSession) this, name)); if (object instanceof HttpSessionBindingListener) { // System.out.println( "Removing attribute " + name ); if (object == null) return; attributes.remove(name); * replaced. * Bind an object to this session, using the specified name. If an object * of the same name is already bound to this session, the object is value Object to be bound, cannot be null * <code>valueBound()</code> on the object. name Name to which the object is bound, cannot be null * non-serializable object in an environment marked distributable. IllegalArgumentException if an attempt is made to add a throw new IllegalArgumentException attributes.put(name, value); (sm.getString("standardSession.setAttribute.iae")); if ((manager != null) && manager.getDistributable() && !(value instanceof Serializable)) ((HttpSessionBindingListener) value).valueBound if (value instanceof HttpSessionBindingListener) // HttpSession Private Methods * <b>IMPLEMENTATION NOTE</b>: The reference to the owning Manager * is not restored by this method, and must be set explicitly. * object input stream. * Read a serialized version of this session object from the specified IOException if an input/output error occurs ClassNotFoundException if an unknown class is specified stream The input stream to read from creationTime = ((Long) stream.readObject()). isValid = ((Boolean) stream.readObject()).booleanValue(); // Deserialize the scalar instance variables (except Manager) throws ClassNotFoundException, IOException { private void readObject(ObjectInputStream stream) String name = (String) stream.readObject(); for (int i = 0; i < n; i++) { Object value = (Object) stream.readObject(); int n = ((Integer) stream.readObject()).intValue(); // Deserialize the attribute count and attribute values * in the serialized representation of this Session. After calling * <code>readObject()</code>, you must set the associated Manager * <b>IMPLEMENTATION NOTE</b>: The owning Manager will not be stored * object output stream. * Write a serialized version of this session object to the specified * be sure the <code>distributable</code> property of our associated * Manager is set to <code>true</code>. * will be silently ignored. If you do not want any such attributes, * explicitly. * <b>IMPLEMENTATION NOTE</b>: Any attribute that is not Serializable private void writeObject(ObjectOutputStream stream) throws IOException { stream The output stream to write to stream.writeObject(new Integer(maxInactiveInterval)); stream.writeObject(new Boolean(isNew)); stream.writeObject(new Long(lastAccessedTime)); stream.writeObject(id); // Write the scalar instance variables (except Manager) stream.writeObject(new Long(creationTime)); // Accumulate the names of serializable attributes stream.writeObject(new Boolean(isValid)); // Serialize the attribute count and the attribute values if (value instanceof Serializable) Object value = attributes.get(attr); stream.writeObject(new Integer(results.size())); stream.writeObject(attributes.get(name)); stream.writeObject(name); String[] getValueNames() | void invalidate() | Enumeration getAttributeNames() | Object getAttribute(String) | long getCreationTime() | crosscut invalidate(StandardSession s): s & (int getMaxInactiveInterval() | boolean isNew() | before { if (!s.isValid()) throw new IllegalStateException static advice(StandardSession s): invalidate(s) { void setAttribute(String, Object)); void removeAttribute(String) | + ".ise")); + thisJoinPoint.methodName (s.sm.getString("standardSession." // Private Class * when <code>HttpSession.getSessionContext()</code> is called. * This class is a dummy implementation of the <code>HttpSessionContext</code> * interface, to conform to the requirement that such an object be returned final class StandardSessionContext implements HttpSessionContext { * interface will be removed in a future version of this API. As of Java Servlet API 2.1 with no replacement. The * within this context. As of Java Servlet API 2.1 with no replacement. * Return the session identifiers of all sessions defined private Vector dummy = new Vector(); public Enumeration getIds() { * and will be removed in a future version of the API. * This method must return an empty <code>Enumeration</code> return (dummy.elements()); id Session identifier for which to look up a session * Return the <code>HttpSession</code> associated with the * specified session identifier. public HttpSession getSession(String id) { * future version of the API. * This method must return null and will be removed in a return (null); private long lastAccessed = creationTime; private int inactiveInterval = -1; validate(); thisAccessTime = System.currentTimeMillis(); lastAccessed = thisAccessTime; void accessed() { // set last accessed to thisAccessTime as it will be left over // from the previous access int thisInterval = (int)(System.currentTimeMillis() - lastAccessed) / 1000; if (inactiveInterval != -1) { // if we have an inactive interval, check to see if we've exceeded it void validate() { } invalidate(); if (thisInterval > inactiveInterval) { } else { return lastAccessed; public long getLastAccessedTime() { throw new IllegalStateException(msg); String msg = sm.getString("applicationSession.session.ise"); if (valid) { ServerSessionManager ssm = ssm.removeSession(this); ServerSessionManager.getManager(); private long lastAccessedTime = creationTime; * session, as the number of milliseconds since midnight, January 1, 1970 * Return the last time the client sent a request associated with this /** */ * a value associated with the session, do not affect the access time. * GMT. Actions that your application takes, such as getting or setting return (this.lastAccessedTime); this.lastAccessedTime = time; page taken from kiczales’ slide
19
Example – Image Processing
Black & White image processing program Procedural programming easy to understand, inefficient Procedural programming with optimization hard to understand, efficient Aspect-oriented programming easy to understand, efficient
20
1. Using Procedural Programming
top-edge OR bottom-edge horizontal-edge
21
2. Using Procedural Programming with Optimization
Without optimization many loops, large memory, frequent memory reference, … performance is bad With optimization efficient, but hard to understand and maintain (tangling)
22
Functional decomposition
Cross-Cutting optimized or horizontal-edge and and top-edge bottom-edge not not down remove up up down or not and a input image Functional decomposition Data flow diagram
23
Cross-Cutting Cross-cutting Component Aspect
two properties must compose differently two properties must be croordinated GP language only provide on composition mechanism Programmer must do the co-composition manualy Component can be cleanly encapsulated in a GP Aspect cannot be cleanly encapsulated in a GP Goal of AOP: provide mechanism to describe aspect
24
How AOP Can Solve Cross-Cutting?
Minor change to component language filter is not explicitly procedure loop is written explicitly Aspect language provide operations on nodes in the dataflow graph check if loop should be fused, then fuse
25
How AOP Can Solve Cross-Cutting?
unfolding aspect program runs!
26
Structure of the AOP-based implementation
GP-based AOP-based lamguage compiler (interpreter) program component language aspect weaver compiler program aspect language
27
Join points Join points Example Role of aspect weaver
interaction point between component language and aspect language Example Edge in data flow diagram Method invocation Principled places in the source code Method bodies … Role of aspect weaver generate ‘join point representation’ of the component prog. execute (or compile) the aspect prog. on each join point
28
AOP (2/2) An Overview of AspectJ
Gregor Kiczales – University of British Columbia Erik Hilsdale, … - Xerox Palo Alto Research Center William G. Griswold – University of California, San Diego European Conference on Object-Oriented Programming June 2001
29
What is AspectJ Extends Java
join points Extends Java Additional implementation to run at certain well-defined points in the execution of the program legal Java program is legal AspectJ program legal AspectJ program can run on standard JVM
30
page taken from kiczales’ slide
AspectJ is not needed 1 every call to foo is preceded by a log call : System.out.println("foo called"); Helper.foo(n/3); class Helper { : public static void foo(int n) { … } : } : System.out.println("foo called"); Helper.foo(i+j+k); : System.out.println("foo called"); Helper.foo(x); page taken from kiczales’ slide
31
page taken from kiczales’ slide
AspectJ is not needed procedures can modularize this case class Helper { : public static void foo(int n) { System.out.println("foo called."); … } : } : Helper.foo(n/3); Helper.foo(i+j+k); Helper.foo(x); : System.out.println("foo called"); Helper.foo(…); class Helper { : public static void foo(int n) { … } : } unless logs use calling context, we don’t control source of Helper… page taken from kiczales’ slide
32
page taken from kiczales’ slide
AspectJ is not needed 2 all subclasses have an identical method 2 Point getX() getY() setX(int) setY(int) moveBy(int, int) draw() refresh() Line getP1() getP2() setP1(Point) setP2(Point) moveBy(int, int) draw() refresh() FigureElement moveBy(int, int) page taken from kiczales’ slide
33
page taken from kiczales’ slide
AspectJ is not needed 2 inheritance can modularize this 2 Point getX() getY() setX(int) setY(int) moveBy(int, int) draw() Line getP1() getP2() setP1(Point) setP2(Point) moveBy(int, int) draw() FigureElement moveBy(int, int) refresh() 2 Point getX() getY() setX(int) setY(int) moveBy(int, int) draw() refresh() Line getP1() getP2() setP1(Point) setP2(Point) moveBy(int, int) draw() refresh() FigureElement moveBy(int, int) page taken from kiczales’ slide
34
page taken from kiczales’ slide
AspectJ is needed these methods all end with call to: Display.update(); 2 Point getX() getY() setX(int) setY(int) moveBy(int, int) draw() Line getP1() getP2() setP1(Point) setP2(Point) moveBy(int, int) draw() FigureElement moveBy(int, int) refresh() page taken from kiczales’ slide
35
page taken from kiczales’ slide
AspectJ is needed after(): call(void FigureElement+.set*(..)) || call(void FigureElement.moveBy(int, int)) { Display.update(); } 2 Point getX() getY() setX(int) setY(int) moveBy(int, int) draw() Line getP1() getP2() setP1(Point) setP2(Point) moveBy(int, int) draw() FigureElement moveBy(int, int) refresh() DisplayUpdating after(): call(void FigureElement+.set*(..)) || call(void FigureElement.moveBy(int, int)) { Display.update(); } page taken from kiczales’ slide
36
Join Points method call / return field access …
37
Join Points
38
Terms pointcut: set of join points advice aspect
primitive pointcut designators: system default user-defined pointcut designators advice Code that is executed at pointcut aspect Modular unit (like class) pointcuts + advices
39
user-defined pointcut
predefined pointcut receptions(void Point.setX(int)) !instanceof(FigureElement) && calls(void FigureElement.incrXY(int, int)) pointcut moves(): receptions(void FigureElement.incrXY(int, int)) || receptions(void *.set*(..)); pointcut topLevelMoves(FigureElement fe): moves(fe) && !cflow(moves(FigureElement)); user-defined pointcut dynamic context
40
2. Advice before, after, around pointcut
after(): moves() { flags = true; } around() returns void: MoveTracking.moves() { if(enableMoves) { proceed(); } } after(Point p) returning (int x): receptions(int p.getX()){ System.out.println(p + ” returned “ x + ” from getX().”); } pointcut
41
3. Aspect pointcut advice
42
Implementation If there is pointcut gets(int Point._x)
p._x Point.$jp$0(p) private static int $jp$0(Point obj) { return obj._x; }
43
Tool Support
44
Real Example Using AspectC to Improve the Modularity of Path-Specific Customization in Operating System Code Yvonne Coady, Gregor Kiczales, … University of British Columbia ACM SIGSOFT Software Engineering Notes European Conference on Object-Oriented Programming September 2001
45
Motivation OS code does not have clean layered structure OS/360
release 2 ~ release 6: 14.6% changed release 12 ~ release 16: 31.9% changed Path-specific customization Dynamic context information From where is this called? Why is this called? Layering violation
46
Example: Prefetch Crosscutting concerns FreeBSD, memory mapped file
Path-specific customization prefetch in page fault handling FreeBSD, memory mapped file Without prefetch VMsystem Filesystem Disk driver No layer violation With prefetch Predic future request Layer violation
47
Example: Prefetch
48
AspectC Implementation
Normal mode prefetch
49
AspectC Implementation
Sequential mode prefetch
50
Benefits Pluggable functionality Independent development
localized in a single aspect make single file for each aspect use makefile to include or exclude combinations of modes Independent development main code and aspects can be developed independently non-aspect: 256 line scatterred over 5 functions (1950lines) Comprehensibility Eary to understand
51
Future Direction Hand-on experience with aspect-oriented programming
Search known issues about AOP
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.