Thursday, February 28, 2008

FIX protocol messages latency calculation using awk

#  awk based script to calculate the latency of FIX protocoll messages.
#  usage: awk -f $someroot/ackdelta.awk [VERBOSE=1] [STAT=1] $someroot/FIX.log 

# Author : Sakthivel Kathirvel
# last.modified=Thursday, Mar 28, 2007

#This program is free software; you can redistribute it and/or
#modify it under the terms of the GNU General Public License
#as published by the Free Software Foundation; either version 2
#of the License, or (at your option) any later version.

#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.

#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.#  


# sample output => line format => ,, ,   
#   D,AAA 0002/02222007,50,10:40:13.329,10:40:13.379
#   D,AAA 0003/02222007,47,10:51:22.845,10:51:22.892
#   D,AAA 0004/02222007,4,10:58:46.246,10:58:46.250
#   D,AAA 0005/02222007,5,11:00:31.500,11:00:31.505
#   D,AAA 0006/02222007,4,11:01:35.909,11:01:35.913

#  sample output with VERBOSE ON
#    timeline=>_Feb_22_10:44:38.431068::mesgtype=>35=D::clordid=>11=AAA 0001/02222007
#    timeline=>_Feb_22_10:44:38.452347::mesgtype=>35=8::clordid=>11=AAA 0001/02222007::exetype=>150=0::ordstatus=>39=0
#    

#  sample output with STAT ON
############### Stats ###############
#   Min delay=33 ms.
#   Max delay=211 ms.
#   Aver. delay=79 ms. of 1216 acks
#   No of ClOrdId processed=1216
#   Process Started...Thu Feb 28 08:50:17 CST 2007
#   Process Ended ...Thu Feb 28 08:50:23 CST 2007
#   Processing took 6 Secs

# Preconditions and assumptions
#   assump.1=the trade log timestamp format = Fri Feb 22 10:50:07.604341
#   assump.2= trade log format has the datestamp appears exactly 2 lines above trademesg lines containing order[35=D] and ack[35=8].
#   assump.3= trademesg lines containing FIX tags uses 'SPACE' or '^A' as line delimiter
#   assump.4=ClOrdId tag value contains space. this space should be accounted for while reading 'full' clordid value while tokenzing the lines based on space as delimiter.
#   assump.5= in tradelog files, trademesg lines containing FIX tags may appear in different order
#   assump.6= the execution report 35=8 can have ExecType 150=0 or 150=A

# last.modified=Thursday, Mar 28, 2007

# impls details
# to speed up processing associative array is used. ClordId is used as index.
# lineBuffer is flushed frequently to optimize the memory usage while processing Laaarge log flies, only last 4 lines read are kept in memory. .
# the input line is normalized to use ' ' as delimiter. ^A characters are normalized to space
# dup clordid with 35=D are scrubbed out.
# clordid with 35=D that dont have match 35=8 with 150=0 or A are aggregaged and printed in stat; STAT switch need to be enabled.
# order and ack timestamp are scaled from micro to mill secs [ rounded off to 3 digits ]
BEGIN {
  linePtr=1;
  clordidCtr=1; #unique clordid with msgtype 35=D
  timeformat = "%a %b %d %H:%M:%S %Z %Y";
  startTimeSec=systime();
  startTS=sprintf("Process Started...%s", strftime(timeformat,systime()));
}
{
  gsub(/ /, "|", $0); # handles if the line delimiter is ascii control character ^A (SOH)
  aline[linePtr++]=$0;
}

# catches (In)coming New Order[35=D] line and extracts ClOrdId fields
/.*35=D.*11=.*59=3.*/{
    mesgtype=getMsgType(aline[linePtr-1]);
    orderLineClOrdID=getClordId(aline[linePtr-1]);
    orderTimeLine=getTimeLine(aline[linePtr-1]);
    if (VERBOSE ~ /[0-9]+/) printf("orderTimeLine=>%s::mesgtype=>%s::clordid=>%s\n", orderTimeLine, mesgtype,orderLineClOrdID )
    # convert the seconds part in the orderTimeLine from microsec to millisec [ rounding to 3 digit precision ]
    inSecPart=substr(orderTimeLine, index(orderTimeLine, ".")+1)
    orderLineClOrdIDValue=substr(orderLineClOrdID, index(orderLineClOrdID, "=")+1);
    # check for duplicate ClOrdID with 35=D and take only unique ones.
    if (length(clordid[orderLineClOrdIDValue]) > 0 ) {
        dupclordid[orderLineClOrdIDValue]="";
    } else {
        clordid[orderLineClOrdIDValue]=sprintf("%s,%s%d",
                                                      substr(mesgtype,index(mesgtype,"=")+1), 
                                                      substr(orderTimeLine, 1, index(orderTimeLine, ".")), 
                                                      inSecPart);
    }
    #flushes out lineBuffer
    delete aline;linePtr=1;

}
# scans a line for execution report[35=8] that are [150=0] or [150=A]  new Orders for any of ClordId-with-[35=D] 
/.*35=8.*150=[0A].*59=3.*/ {
    ackLineClOrdID=getClordId(aline[linePtr-1]);
    ackLineClOrdIDValue=substr(ackLineClOrdID, index(ackLineClOrdID, "=")+1);
    if (length(clordid[ackLineClOrdIDValue]) > 0 ) {
        ackTimeLine=getTimeLine(aline[linePtr-1]);
        if (VERBOSE ~ /[0-9]+/) printf("ACKtimeline=>%s::mesgtype=>%s::clordid=>%s::exetype=>%s::ordstatus=>%s\n", ackTimeLine, getMsgType(aline[linePtr-1]),ackLineClOrdID, getExecType(aline[linePtr-1]),getOrderStatus(aline[linePtr-1]))
        split(clordid[ackLineClOrdIDValue], PARTS, ",");
        inTimeLineinMilSec=PARTS[2];
        # convert the seconds part in the ackTimeLine from microsec to millisecs [ rounding to 3 digit precision ]
        ackSecPart=substr(ackTimeLine, index(ackTimeLine, ".")+1);
        ackTimeLineinMilSec=sprintf("%s%d",substr(ackTimeLine, 1, index(ackTimeLine,".")), ackSecPart);
        clordid[ackLineClOrdIDValue]=sprintf("match, %s,%s,%d",
                                                    clordid[ackLineClOrdIDValue],
                                                    ackTimeLineinMilSec,
                                                    getDelta(inTimeLineinMilSec,ackTimeLineinMilSec));
                                                    
    }
    #flushes out lineBuffer
    delete aline;linePtr=1;
}

END {
  min=9999;max=-1;aver=0;
  for (assocIndex in clordid ) {
      split(clordid[assocIndex],PARTS,",");
      if ("match" ~ PARTS[1]) {
          clordidCtr++;
          deltaPart=PARTS[5];
          if (int(deltaPart) >= int(max)) {max=deltaPart; }
          if (int(deltaPart) < int(min)) {min=deltaPart;}
          aver=aver+deltaPart;
          sub(/ /,"",PARTS[2]);
          printf("%s,%s,%s,%s,%s\n", PARTS[2],assocIndex,deltaPart,PARTS[3],PARTS[4]); 
      } else {
         nomatch[assocIndex]="";
      }
  }
  
  
  if (STAT ~ /[0-9]+/) {
      print "############### Stats ###############"
      printf ("Min delay=%d ms.\n", min)
      printf ("Max delay=%d ms.\n", max)
      printf ("Aver. delay=%d ms. of %i acks\n", aver/(clordidCtr-1),(clordidCtr-1) )
      printf ("No of ClOrdId processed=%d\n",clordidCtr-1);
      print startTS 
      endTimeSec=systime();
      printf("Process Ended ...%s\n", strftime(timeformat,systime()));
      printf("Processing took %d Secs\n",  (endTimeSec-startTimeSec));
      
      for (assocIndex in nomatch) {
            print assocIndex;
      }

      for (assocIndex in dupclordid ) {
            print assocIndex;
      }
  }
}

function getTimeLine(aLine) {
    linefields = split(aLine, FIELDS, "|");
    return sprintf("%s",FIELDS[1]);
}

function getClordId(aLine) {
   linefields = split(aLine, FIELDS, "|");
   for(ctr=1; ctr<=linefields; ctr++) {
     if (FIELDS[ctr] ~ "11=") {
       return sprintf("%s %s",  FIELDS[ctr], FIELDS[ctr+1]);
     }
   }
}

function getMsgType(aLine) {
   linefields = split(aLine, FIELDS, "|");
   for(ctr=1; ctr<=linefields; ctr++) {
     if (FIELDS[ctr] ~ "35=") {
       return sprintf("%s",  FIELDS[ctr]);
     }
   }
}

function getOrderStatus(aLine) {
   linefields = split(aLine, FIELDS, "|");
   for(ctr=1; ctr<=linefields; ctr++) {
     if (FIELDS[ctr] ~ "39=") {
       return sprintf("%s",  FIELDS[ctr]);
     }
   }
}

function getExecType(aLine) {
   linefields = split(aLine, FIELDS, "|");
   for(ctr=1; ctr<=linefields; ctr++) {
     if (FIELDS[ctr] ~ "150=") {
       return sprintf("%s",  FIELDS[ctr]);
     }
   }
}

function getStats() {
# todo
#find min, max and average of the deltas
}

function getDelta(inTime,outTime) {

  split(inTime, inTimeParts, ".")
  split(outTime, outTimeParts, ".")
  split(inTimeParts[1],inTimeHMSParts, ":")
  split(outTimeParts[1],outTimeHMSParts, ":")

  inTimeMilsec=(inTimeHMSParts[1]*60*60*1000) + (inTimeHMSParts[2]*60*1000) + (inTimeHMSParts[3]*1000) + inTimeParts[2]
  outTimeMilSec=(outTimeHMSParts[1]*60*60*1000) + (outTimeHMSParts[2]*60*1000) + (outTimeHMSParts[3]*1000) + outTimeParts[2]
  return (outTimeMilSec-inTimeMilsec)
}

Saturday, July 28, 2007

Software Patterns Made Simple


Construction Types:

Abstract factory, Factory, Builder, Prototype, Singleton (5)

Adapter Types: 

Bridge, composite, deco, facade, flyweight, proxy (7)

Behavior Types:

Visitor, observer, interpreter, iterator, mediator (5)

Observer pattern:

  • There are two kinds of object Subject and Observer. Whenever there is change on subject's state observer will receive notification. Common example of observer pattern is Social Network notifications - Facebook, Linkedin - notification mechanism. Subject is you and observers are your friends. 

Execution Types:

command, chain of resp.(2)

Planning Types:
state, strategy, template (3)

  • State design pattern is used to change Object's behavior based on it’s internal state.
  • Context is the class that has a State reference to one of the concrete implementations of the State and forwards the request to the state object for processing. 

Strategy pattern:
  • Comes handy when you want to accomplish the same goal with different strategies. One good example of Strategy pattern is sorting a bunch of objects.  JDK's Collections.sort() method and Comparator interface, which is a strategy interface and defines strategy for comparing objects. Because of this pattern, we don't need to modify sort() method (closed for modification) to compare any object, at same time we can implement Comparator interface to define new comparing strategy (open for extension).
Template Pattern
Reward Types:
 momento,




Monday, July 23, 2007

Chain of Responsibility Pattern

Follow the Chain of Responsibility

Run through server-side and client-side CoR implementations

Jul 29, 2007 1:00 AM PT
I recently switched to Mac OS X from Windows and I'm thrilled with the results. But then again, I only spent a short five-year stint on Windows NT and XP; before that I was strictly a Unix developer for 15 years, mostly on Sun Microsystems machines. I also was lucky enough to develop software under Nextstep, the lush Unix-based predecessor to Mac OS X, so I'm a little biased.
Aside from its beautiful Aqua user interface, Mac OS X is Unix, arguably the best operating system in existence. Unix has many cool features; one of the most well known is the pipe, which lets you create combinations of commands by piping one command's output to another's input. For example, suppose you want to list source files from the Struts source distribution that invoke or define a method namedexecute(). Here's one way to do that with a pipe:
   grep "execute(" `find $STRUTS_SRC_DIR -name "*.java"` | awk -F: '{print }'
The grep command searches files for regular expressions; here, I use it to find occurrences of the stringexecute( in files unearthed by the find command. grep's output is piped into awk, which prints the first token—delimited by a colon—in each line of grep's output (a vertical bar signifies a pipe). That token is a filename, so I end up with a list of filenames that contain the string execute(.
Now that I have a list of filenames, I can use another pipe to sort the list:
  grep "execute(" `find $STRUTS_SRC_DIR -name "*.java"` | awk -F: '{print }' | sort
This time, I've piped the list of filenames to sort. What if you want to know how many files contain the string execute(? It's easy with another pipe:
  grep "execute(" `find $STRUTS_SRC_DIR -name "*.java"` | awk -F: '{print }' | sort -u | wc -l
The wc command counts words, lines, and bytes. In this case, I specified the -l option to count lines, one line for each file. I also added a -u option to sort to ensure uniqueness for each filename (the -u option filters out duplicates).
Pipes are powerful because they let you dynamically compose a chain of operations. Software systems often employ the equivalent of pipes (e.g., email filters or a set of filters for a servlet). At the heart of pipes and filters lies a design pattern: Chain of Responsibility (CoR).
Note: You can download this article's source code from Resources.

CoR introduction

The Chain of Responsibility pattern uses a chain of objects to handle a request, which is typically an event. Objects in the chain forward the request along the chain until one of the objects handles the event. Processing stops after an event is handled.
Figure 1 illustrates how the CoR pattern processes requests.

Figure 1. The Chain of Responsibility pattern
In Design Patterns, the authors describe the Chain of Responsibility pattern like this:
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
The Chain of Responsibility pattern is applicable if:
  • You want to decouple a request's sender and receiver
  • Multiple objects, determined at runtime, are candidates to handle a request
  • You don't want to specify handlers explicitly in your code
If you use the CoR pattern, remember:
  • Only one object in the chain handles a request
  • Some requests might not get handled
Those restrictions, of course, are for a classic CoR implementation. In practice, those rules are bent; for example, servlet filters are a CoR implementation that allows multiple filters to process an HTTP request.
Figure 2 shows a CoR pattern class diagram.

Figure 2. Chain of Responsibility class diagram
Typically, request handlers are extensions of a base class that maintains a reference to the next handler in the chain, known as the successor. The base class might implement handleRequest() like this:
   public abstract class HandlerBase {
         ...
         public void handleRequest(SomeRequestObject sro) {
            if(successor != null)
                  successor.handleRequest(sro);
         }
   }
So by default, handlers pass the request to the next handler in the chain. A concrete extension ofHandlerBase might look like this:
   public class SpamFilter extends HandlerBase {
      public void handleRequest(SomeRequestObject mailMessage) {
         if(isSpam(mailMessage))   { // If the message is spam
            // take spam-related action. Do not forward message.
         }
         else { // Message is not spam.
            super.handleRequest(mailMessage); // Pass message to next filter in the chain.
         }
      }
   }
The SpamFilter handles the request (presumably receipt of new email) if the message is spam, and therefore, the request goes no further; otherwise, trustworthy messages are passed to the next handler, presumably another email filter looking to weed them out. Eventually, the last filter in the chain might store the message after it passes muster by moving through several filters.
Note the hypothetical email filters discussed above are mutually exclusive: Ultimately, only one filter handles a request. You might opt to turn that inside out by letting multiple filters handle a single request, which is a better analogy to Unix pipes. Either way, the underlying engine is the CoR pattern.
In this article, I discuss two Chain of Responsibility pattern implementations: servlet filters, a popular CoR implementation that allows multiple filters to handle a request, and the original Abstract Window Toolkit (AWT) event model, an unpopular classic CoR implementation that was ultimately deprecated.

Servlet filters

In the Java 2 Platform, Enterprise Edition (J2EE)'s early days, some servlet containers provided a handy feature known as servlet chaining, whereby one could essentially apply a list of filters to a servlet. Servlet filters are popular because they're useful for security, compression, logging, and more. And, of course, you can compose a chain of filters to do some or all of those things depending on runtime conditions.
With the advent of the Java Servlet Specification version 2.3, filters became standard components. Unlike classic CoR, servlet filters allow multiple objects (filters) in a chain to handle a request.
Servlet filters are a powerful addition to J2EE. Also, from a design patterns standpoint, they provide an interesting twist: If you want to modify the request or the response, you use the Decorator pattern in addition to CoR. Figure 3 shows how servlet filters work.

Figure 3. Servlet filters at runtime

A simple servlet filter

You must do three things to filter a servlet:
  • Implement a servlet
  • Implement a filter
  • Associate the filter and the servlet
Examples 1-3 perform all three steps in succession:

Example 1. A servlet

import java.io.PrintWriter;
import javax.servlet.*;
import javax.servlet.http.*;
public class FilteredServlet extends HttpServlet {
   public void doGet(HttpServletRequest request, HttpServletResponse response)
                         throws ServletException, java.io.IOException {
      PrintWriter out = response.getWriter();
      out.println("Filtered Servlet invoked");
   }
}

Example 2. A filter

import java.io.PrintWriter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
public class AuditFilter implements Filter {
   private ServletContext app = null;
   public void init(FilterConfig config) { 
      app = config.getServletContext();
   }
   public void doFilter(ServletRequest request, ServletResponse response,
                        FilterChain chain) throws java.io.IOException,
                                               javax.servlet.ServletException {
      app.log(((HttpServletRequest)request).getServletPath());
      chain.doFilter(request, response);
   }
   public void destroy() { }
}

Example 3. The deployment descriptor


   
      auditFilter
      AuditFilter
   
   <filter-mapping>
      auditFilter
      /filteredServlet
   </filter-mapping>
     
     
       filteredServlet
       FilteredServlet
     
     
       filteredServlet
       /filteredServlet
     
   ...

If you access the servlet with the URL /filteredServlet, the auditFilter gets a crack at the request before the servlet. AuditFilter.doFilter writes to the servlet container log file and callschain.doFilter() to forward the request. Servlet filters are not required to call chain.doFilter(); if they don't, the request is not forwarded. I can add more filters, which would be invoked in the order they are declared in the preceding XML file.
Now that you've seen a simple filter, let's look at another filter that modifies the HTTP response.

Filter the response with the Decorator pattern

Unlike the preceding filter, some servlet filters need to modify the HTTP request or response. Interestingly enough, that task involves the Decorator pattern. I discussed the Decorator pattern in two previous Java Design Patterns articles: "Amaze Your Developer Friends with Design Patterns" and "Decorate Your Java Code."
Example 4 lists a filter that performs a simple search and replace in the body of the response. That filter decorates the servlet response and passes the decorator to the servlet. When the servlet finishes writing to the decorated response, the filter performs a search and replace within the response's content.

Example 4. A search and replace filter

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class SearchAndReplaceFilter implements Filter {
   private FilterConfig config;
   public void init(FilterConfig config) { this.config = config; }
   public FilterConfig getFilterConfig() { return config; }
   public void doFilter(ServletRequest request, ServletResponse response,
                        FilterChain chain) throws java.io.IOException,
                                               javax.servlet.ServletException {
      StringWrapper wrapper = new StringWrapper((HttpServletResponse)response);
      chain.doFilter(request, wrapper);
      String responseString = wrapper.toString();
      String search = config.getInitParameter("search");
      String replace = config.getInitParameter("replace");
      if(search == null || replace == null)
         return; // Parameters not set properly
      int index = responseString.indexOf(search);
      if(index != -1) {
         String beforeReplace = responseString.substring(0, index);
         String afterReplace=responseString.substring(index + search.length());
         response.getWriter().print(beforeReplace + replace + afterReplace);
      }
   }
   public void destroy() {
      config = null;
   }
}
The preceding filter looks for filter init parameters named search and replace; if they are defined, the filter replaces the first occurrence of the search parameter value with the replace parameter value.
SearchAndReplaceFilter.doFilter() wraps (or decorates) the response object with a wrapper (decorator) that stands in for the response. When SearchAndReplaceFilter.doFilter() callschain.doFilter() to forward the request, it passes the wrapper instead of the original response. The request is forwarded to the servlet, which generates the response.
When chain.doFilter() returns, the servlet is done with the request, so I go to work. First, I check for the search and replace filter parameters; if present, I obtain the string associated with the response wrapper, which is the response content. Then I make the substitution and print it back to the response.
Example 5 lists the StringWrapper class.

Example 5. A decorator

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class StringWrapper extends HttpServletResponseWrapper {
   StringWriter writer = new StringWriter();
   public StringWrapper(HttpServletResponse response) { super(response); }
   public PrintWriter getWriter() { return new PrintWriter(writer); }
   public String       toString() { return writer.toString(); }
}
StringWrapper, which decorates the HTTP response in Example 4, is an extension ofHttpServletResponseWrapper, which spares us the drudgery of creating a decorator base class for decorating HTTP responses. HttpServletResponseWrapper ultimately implements theServletResponse interface, so instances of HttpServletResponseWrapper can be passed to any method expecting a ServletResponse object. That's why SearchAndReplaceFilter.doFilter()can call chain.doFilter(request, wrapper) instead of chain.doFilter(request,response).
Now that we have a filter and a response wrapper, let's associate the filter with a URL pattern and specify search and replace patterns:
Page 2
Page 2 of 2

Example 6. A deployment descriptor


   ...
   
      searchAndReplaceFilter
      SearchAndReplaceFilter
      
         search
         Blue Road Inc.
      
      
      
         replace
         Red Rocks Inc.
      
   
   
      searchAndReplaceFilter
      /*
   
   ...

I've now wired the search and replace filter to all requests by associating it with the URL pattern /* and specified that Red Rocks Inc. will replace the first occurrence of Blue Road Inc.. Let's try it on this JavaServer Pages (JSP) page:

Example 7. A JSP page

Welcome to Blue Road Inc.
Figure 4 shows the preceding JSP page's output. Notice that Red Rocks Inc. has replaced Blue Road Inc..


Figure 4. Using a search and replace filter. Click on thumbnail to view full-size image.
Of course, my search and replace filter serves little practical use other than demonstrating how filters can modify the response with a wrapper. However, useful freely available servlet filters are easy to find. For example, Tomcat 4.1.X comes with the following filters: a compression filter that zips responses larger than a threshold (that you can set as a filter parameter); an HTML filter; and a filter that dumps information about a request. You can find those filters under Tomcat's examples directory.
Servlet filters represent a popular CoR pattern variation where multiple objects in the chain may handle a request. Let's wrap up the CoR pattern with a brief look at a classic CoR implementation that was deprecated.

The AWT event model

The AWT originally used the CoR pattern for event handling. This is how it worked:
import java.applet.Applet;
import java.awt.*;
public class MouseSensor extends Frame {
   public static void main(String[] args) {
      MouseSensor ms = new MouseSensor();
      ms.setBounds(10,10,200,200);
      ms.show();
   }
   public MouseSensor() {
      setLayout(new BorderLayout());
      add(new MouseSensorCanvas(), "Center");
   }
}
class MouseSensorCanvas extends Canvas {
   public boolean mouseUp(Event event, int x, int y) {
      System.out.println("mouse up");
      return true; // Event has been handled. Do not propagate to container.
   }
   public boolean mouseDown(Event event, int x, int y) {
      System.out.println("mouse down");
      return true; // Event has been handled. Do not propagate to container.
   }
}
The preceding application creates a canvas and adds it to the application. That canvas handles mouse up and down events by overriding mouseUp() and mouseDown(), respectively. Notice those methods return a boolean value: true signifies that the event has been handled, and therefore should not be propagated to the component's container; false means the event was not fully handled and should be propagated. Events bubble up the component hierarchy until a component handles it; or the event is ignored if no component is interested. This is a classic Chain of Responsibility implementation.
Using the CoR pattern for event handling was doomed to failure because event handling requires subclassing components. Because an average graphical user interface (GUI) uses many components, and most components are interested in at least one event (and some are interested in many events), AWT developers had to implement numerous component subclasses. Generally, requiring inheritance to implement a heavily used feature is poor design, because it results in an explosion of subclasses.
The original AWT event model was eventually replaced with the Observer pattern, known as the delegation model, which eliminated the CoR pattern. Here's how it works:
import java.awt.*;
import java.awt.event.*;
public class MouseSensor extends Frame {
   public static void main(String[] args) {
      MouseSensor ms = new MouseSensor();
      ms.setBounds(10,10,200,200);
      ms.show();
   }
   public MouseSensor() {
      Canvas canvas = new Canvas();
      canvas.addMouseListener(new MouseAdapter() {
         public void mousePressed(MouseEvent e) {
            System.out.println("mouse down");
         }
         public void mouseReleased(MouseEvent e) {
            System.out.println("mouse up");
         }
      });
      setLayout(new BorderLayout());
      add(canvas, "Center");
   }
}
The delegation model—where a component delegates event handling to another object—doesn't require extending component classes, which is a much simpler solution. With the delegation event model, event methods return void because events are no longer automatically propagated to a component's container.
The CoR pattern was not applicable for AWT events because GUI events are much too fine-grained; because there are so many events, and components handle them so frequently, the CoR pattern resulted in an explosion of subclasses—an average GUI could easily have upwards of 50 component subclasses for the single purpose of handling events. Finally, propagation of events was rarely used; typically, events are handled by the component in which they originated.
On the other hand, the CoR pattern is a perfect fit for servlet filters. Compared to GUI events, HTTP requests occur infrequently, so the CoR pattern can better handle them. And event propagation is very useful for filters because you can combine them—much like the Unix pipes discussed at the beginning of this article—to produce a myriad of effects.

Last link

The Chain of Responsibility pattern lets you decouple an event's sender from its receiver with a chain of objects that are candidates to handle the event. With the classic CoR pattern, one or none of the objects in the chain handles the event; if an object doesn't handle the event, it forwards it to the next object in the chain. In this article, we examined two CoR pattern implementations: the original AWT event model and servlet filters.
David Geary is the author of Core JSTL Mastering the JSP Standard Tag Library (Prentice Hall, 2002; ISBN: 0131001531), Advanced JavaServer Pages (Prentice Hall, 2001; ISBN: 0130307041), and the Graphic Java series (Prentice Hall). David has been developing object-oriented software with numerous object-oriented languages for almost 20 years. Since reading the GOF Design Patterns book in 1994, David has been an active proponent of design patterns, and has used and implemented design patterns in Smalltalk, C++, and Java. In 1997, David began working full-time as an author and occasional speaker and consultant. David is a member of the expert groups defining the JSP Standard Tag Library and JavaServer Faces, and is a contributor to the Apache Struts JSP framework. David is currently working on Core JavaServer Faces, which will be published in the spring of 2004.

Learn more about this topic


Follow the Chain of Responsibility <!-- Google Analytics

Wednesday, September 20, 2006

My emacs file

 (custom-set-variables
   ;; custom-set-variables was added by Custom -- don't edit or cut/paste it!
   ;; Your init file should contain only one such instance.
  '(auto-compression-mode t nil (jka-compr))
  '(case-fold-search t)
  '(column-number-mode t)
  '(current-language-environment "UTF-8")
  '(default-input-method "rfc1345")
  '(global-font-lock-mode t nil (font-lock))
  '(size-indication-mode t)
  '(transient-mark-mode t)
  '(truncate-lines t))
 (custom-set-faces
   ;; custom-set-faces was added by Custom -- don't edit or cut/paste it!
   ;; Your init file should contain only one such instance.
  '(linum ((t (:inherit (default default) :background "white" :foreground "black")))))

 ;;(top . 20) (left . 20)
 ;;(setq default-frame-alist
 ;;      '((width . 100) (height . 80)
 ;;        (font . "-adobe-courier-medium-r-normal--17-120-100-100-m-100-iso8859-1")))

 (put 'dired-find-alternate-file 'disabled nil)
 ;; Add F12 to toggle line wrap
 (setq line-number-mode t)
 (setq column-number-mode t)
 ; turn off tool bar
 (if (fboundp 'tool-bar-mode) (tool-bar-mode -1))
       (add-hook 'window-configuration-change-hook
               (lambda ()
                     (setq frame-title-format
                         (concat
                                       invocation-name "@" system-name ": "
                                       (replace-regexp-in-string
                                       (concat "/home/" user-login-name) "~"
                                       (or buffer-file-name "%b"))))))

 (put 'upcase-region 'disabled nil)
;;(setq w32-enable-synthesized-fonts t)
 ;;(set-default-font "-outline-Verdana-normal-r-normal-normal-15-112-96-96-p-*-iso8859-1")
 (put 'downcase-region 'disabled nil)
 (setq-default ispell-program-name "aspell")
 (setq-default indent-tabs-mode nil)
 ;; repeat last command
 (global-set-key [(control z)] 'repeat)

 ;; repeat last command
 (global-set-key [(control j)] 'join-line)

 ;; Enable backup files.
 (setq make-backup-files t)

 ;; Enable versioning with default values (keep five last versions, I think!)
 (setq version-control t)

 ;; Save all backup file in this directory.
 (setq backup-directory-alist (quote ((".*" . "/app/skathirvel/emacs_backups/"))))

 ;; ===== Set the highlight current line minor mode =====

 ;; In every buffer, the line which contains the cursor will be fully
 ;; highlighted
 ;;(global-hl-line-mode t)
 ;; show line numbers of left hand side; needs linum.el where .emacs file is
 ;; I was wondering if there is way to change the color of the line numbers e.g change color/change backgroun

 ;;:Try M-x customize-face RET linum. Also try M-x global-linum-mode, or append (add-hook ‘find-file-hook (la

 ;;(add-to-list 'default-frame-alist '(font . "-adobe-courier-bold-r-normal--14-140-75-75-m-90-iso8859-1"))

 ;;Sets the tab size to four spaces
 (setq-default tab-width 2)
 (setq default-truncate-lines t)
 (set-scroll-bar-mode 'right)
 ;; Open a file
(global-set-key [(control o)] 'find-file)
 ;; Close
 (global-set-key [(control w)] 'kill-this-buffer)
 ;; goto-line
 (global-set-key [(control l)] 'goto-line)
 ;; clear buffer
 (global-set-key [f1] 'list-bookmarks)
 ;;close all buffers
 ;;(global-set-key [(control f1)] 'close-all-buffers)
 ;; Save
 (global-set-key [f2] 'bookmark-set)
 (global-set-key [(shift f2)] 'write-file )

 (global-set-key [f3] 'query-replace-regexp)
 (global-set-key [shift f3] 'isearch-backward)

 ;; search regex forward
 (global-set-key [f4] 'isearch-forward-regexp)
 ;; search regex backward
 (global-set-key [(shift f4)] 'isearch-backward-regexp)

 ;; Indent
 ;;(global-set-key [f4] 'indent-region)

 (load-file "~/ibuffer.el")
 (require 'ibuffer)
 ;; Term and shell
 ;; Toggle between two windows
 (global-set-key [f5] 'ibuffer)
 (global-set-key [f6] 'buffer-menu-other-window)
 (global-set-key [f7] 'other-window)
 (global-set-key [f8] 'delete-window)
 (global-set-key [(shift f8)] 'delete-other-windows)

 (global-set-key [f9] 'find-dired)
 (global-set-key [(kbd "C-c-o")] 'occur)

 ;; frames (create and delete)
 (global-set-key [f10] 'make-frame-command)
(global-set-key [(shift f10)] 'delete-frame)
 (global-set-key [(meta f10)] 'other-frame)


 (global-set-key [(shift f7)] 'switch-to-next-buffer)
 (global-set-key [(alt f7)] 'toggle-source-header)

 (global-set-key [delete] 'delete-char)
 (global-set-key [(meta right)] 'forward-word)
 (global-set-key [(meta left)] 'backward-word)
 (global-set-key [(control home)] 'beginning-of-buffer)
 (global-set-key [(control end)] 'end-of-buffer)

 (global-set-key [f12] 'toggle-truncate-lines)
 (global-set-key [f11] 'revert-buffer)
 (global-set-key [(meta ?1)] 'cscope-find-global-definition)
 (global-set-key [(meta ?2)] 'cscope-find-functions-calling-this-function)
 (global-set-key [(meta ?3)] 'cscope-find-this-symbol)
 (global-set-key [(meta ?4)] 'cscope-find-egrep-pattern)
 ;;(global-set-key [(control ?0)]  'bc-clear )



 (defun eshellclear ()
   "Clears the shell buffer ala Unix's clear or DOS' cls"
   (interactive)
   ;; the shell prompts are read-only, so clear that for the duration
   (let ((inhibit-read-only t))
    ;; simply delete the region
    (delete-region (point-min) (point-max))))

 ;; To ease the edition of code. It allows me to indent (or unindent) several lines back and forth pressing t
 ;; (or the Shift and tab key)
 ;;(set-variable <91>my-tab-width 2)
 (defun indent-block()
         (interactive)
         (shift-region 2)
         (setq deactivate-mark nil))


 (defun unindent-block()
         (interactive)
         (shift-region -2)
         (setq deactivate-mark nil))


 (defun shift-region(numcols)
         ; my trick to expand the region to the beginning and end of the area selected
         ; a convenient feature to which I was used, from the Dreamweaver editor
         (if (< (point)(mark))
                         (if (not(bolp))    (progn (beginning-of-line)(exchange-point-and-mark) (end-of-line)
                 (progn (end-of-line)(exchange-point-and-mark)(beginning-of-line)))
         (setq region-start (region-beginning))
         (setq region-finish (region-end))
         (save-excursion
                 (if (< (point) (mark)) (exchange-point-and-mark))
                 (let ((save-mark (mark)))


 ;; book mark keys
 ;;(global-set-key [(control ?1)]  'bookmark-bmenu-list )
 ;;(global-set-key [(control ?2)]  'af-bookmark-toggle )
 ;;(global-set-key [(control ?3)]  'bookmark-write )
 ;;(global-set-key [(control ?4)]  'bookmark-load )
 ;;(global-set-key [(meta ?,)]  'af-bookmark-cycle-forward )
 ;;(global-set-key [(meta ?.)]  'af-bookmark-cycle-reverse )
 ;;(global-set-key [(control ?0)]  'af-bookmark-clear-all )

 ;; book mark keys
 ;;(global-set-key [(control ?1)]  'bc-list )
 ;;(global-set-key [(control ?2)]  'bc-set )
 ;;(global-set-key [(control ?3)]  'bookmark-write )
 ;;(global-set-key [(control ?4)]  'bookmark-load )
 ;;(global-set-key [(meta ?.)]  'bc-local-next)
 ;;(global-set-key [(control meta ?.)]  'bc-next)
 ;;(global-set-key [(control meta ?,)]  'bc-previous)
                         (indent-rigidly region-start region-finish numcols))))


 (defun indent-or-complete ()
         "Indent region selected as a block; if no selection present either indent according to mode,
  or expand the word preceding point. "
         (interactive)
         (if  mark-active
                         (indent-block)
                 (if (looking-at "\\>")
                                 (hippie-expand nil)
                         (insert "\t"))))

 (defun my-unindent()
         "Unindent line, or block if it's a region selected"
         (interactive)
         (if mark-active
                         (unindent-block)
                 (if(not(bolp))(delete-backward-char 2))))

 (add-hook 'find-file-hooks (function (lambda ()


 (define-key global-map [tab] 'indent-or-complete) ;; Now remember to force tab (C-q-tab) if you want to simp
 (define-key global-map [(shift tab)] 'my-unindent)

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 (global-set-key [(control f5)] 'ebrowse-tree-mode)
 (add-to-list 'auto-mode-alist '("BROWSE\\.*" . ebrowse-tree-mode))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Easy bookmarks management
 ;;
 ;; Author: Anthony Fairchild
 ;;

 ;;;; Keymaping examples
;; (global-set-key [(control f2)]  'af-bookmark-toggle )
 ;; (global-set-key [f2]  'af-bookmark-cycle-forward )
 ;; (global-set-key [(shift f2)]  'af-bookmark-cycle-reverse )
 ;; (global-set-key [(control shift f2)]  'af-bookmark-clear-all )

 ;; Include common lisp stuff
 (require 'cl)
 (require 'bookmark)
 (defvar af-current-bookmark nil)

 ;;(defun af-bookmark-make-name ()
 ;;  "makes a bookmark name from the buffer name and cursor position"
 ;;  (concat (buffer-name (current-buffer))
 ;;          " - " (number-to-string (point))))
 ;;  (1+ (count-lines 1 (point)))
 (defun af-bookmark-make-name ()
   "makes a bookmark name from the buffer name and cursor position"
   (concat (buffer-name (current-buffer))
           " - " (number-to-string(1+ (count-lines 1  (point))))))


 (defun af-bookmark-toggle ()
   "remove a bookmark if it exists, create one if it doesnt exist"
   (interactive)
   (let ((bm-name (af-bookmark-make-name)))
     (if (bookmark-get-bookmark bm-name)
         (progn (bookmark-delete bm-name)
                (message "bookmark removed"))
       (progn (bookmark-set bm-name)
              (setf af-current-bookmark bm-name)
              (message "bookmark set")))))

 (defun af-bookmark-cycle (i)
   "Cycle through bookmarks by i.  'i' should be 1 or -1"
   (if bookmark-alist
       (progn (unless af-current-bookmark
                (setf af-current-bookmark (first (first bookmark-alist))))
              (let ((cur-bm (assoc af-current-bookmark bookmark-alist)))
                (setf af-current-bookmark
                     (if cur-bm
                          (first (nth (mod (+ i (position cur-bm bookmark-alist))
                                           (length bookmark-alist))
                                      bookmark-alist))
                        (first (first bookmark-alist))))
                (bookmark-jump af-current-bookmark)
                ;; Update the position and name of the bookmark.  We
                ;; only need to do this when the bookmark has changed
                ;; position, but lets go ahead and do it all the time
                ;; anyway.
                (bookmark-set-position af-current-bookmark (point))
                (let ((new-name (af-bookmark-make-name)))
                  (bookmark-set-name af-current-bookmark new-name)
                  (setf af-current-bookmark new-name))))
     (message "There are no bookmarks set!")))

 (defun af-bookmark-cycle-forward ()
   "find the next bookmark in the bookmark-alist"
   (interactive)
   (af-bookmark-cycle 1))

 (defun af-bookmark-cycle-reverse ()
   "find the next bookmark in the bookmark-alist"
   (interactive)
   (af-bookmark-cycle -1))

 (defun af-bookmark-clear-all()
   "clears all bookmarks"
   (interactive)
   (setf bookmark-alist nil))

 ;;If you put this in your .emacs, you can do M-x close-all-buffers.  To bind it to a key (for example, C-c x

 (defun close-all-buffers ()
   (interactive)
   (mapc 'kill-buffer (buffer-list)))

 (defun sacha/increase-font-size ()
   (interactive)
 (set-face-attribute 'default
                       nil
                       :height
                       (ceiling (* 1.10
                                   (face-attribute 'default :height)))))
 (defun sacha/decrease-font-size ()
   (interactive)
   (set-face-attribute 'default
                       nil
                       :height
                       (floor (* 0.9
                                   (face-attribute 'default :height)))))
 (global-set-key (kbd "C-+") 'sacha/increase-font-size)
 (global-set-key (kbd "C--") 'sacha/decrease-font-size)

 (require 'dired-x)
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Easy bookmarks management ends

 ;;:Append (global-linum-mode 1) to your .emacs.

 ;;(load-file "~/linum.el")
 ;;(require 'linum)
 ;;(global-linum-mode 1)

 (load-file "~/xcscope.el")
 (require 'xcscope)

 (load-file "~/breadcrumb.el")
 (require 'breadcrumb)


 (defun date ()
   (interactive)
   (insert (format-time-string "%A, %B %e, %Y")))


 ;;(add-to-list 'load-path "/app/skathirvel/tramp-2.1.9/lisp/")
 ;;(require 'tramp)
;;(setq tramp-default-method "scp")

 ;;(setq shell-file-name "c:/cygwin/bin/bash.exe")
 ;;(load "linum.el")
 ;;(require 'linum)
 ;;(global-linum-mode 1)

 ;; (load-file "C:\\Program Files\\gnuserv\\gnuserv.el")
 ;; (require 'gnuserv)

 ;;
 ;; (require 'gnuserv)

 ;;   (setq custom-file "/cygdrive/c/moje/_unix/.emacs-cygwin-mine")
 ;;   (load custom-file)

 ;;(global-set-key [(control .)] 'enlarge-window-horizontally)
 ;;(global-set-key [(control ,)] 'shrink-window-horizontally )
 ;;(global-set-key [(control ?6)] 'enlarge-window )
 ;;(global-set-key [(control ?7)] 'shrink-window )

 (defun copy-buffer-file-name-as-kill (choice)
   "Copyies the buffer {name/mode}, file {name/full path/directory} to the kill-ring."
   (interactive "cCopy (b) buffer name, (m) buffer major mode, (f) full buffer-file path, (d) buffer-file dir
   (let ((new-kill-string)
         (name (if (eq major-mode 'dired-mode)
                   (dired-get-filename)
                 (or (buffer-file-name) ""))))
     (cond ((eq choice ?f)
            (setq new-kill-string name))
           ((eq choice ?d)
            (setq new-kill-string (file-name-directory name)))
           ((eq choice ?n)
            (setq new-kill-string (file-name-nondirectory name)))
           ((eq choice ?b)
            (setq new-kill-string (buffer-name)))
           ((eq choice ?m)
            (setq new-kill-string (format "%s" major-mode)))
           (t (message "Quit")))
     (when new-kill-string
       (message "%s copied" new-kill-string)
       (kill-new new-kill-string))))

 ;; When moving to parent directory by `^ Dired by default creates a new buffer for each movement up. The fol

 (add-hook 'dired-mode-hook
  (lambda ()
   (define-key dired-mode-map (kbd "^")
     (lambda () (interactive) (find-alternate-file "..")))
   ; was dired-up-directory
  ))
 (put 'erase-buffer 'disabled nil)
 ;;(load-file "~/dirtree.el")
 (add-to-list 'load-path "/app/skathirvel/.emacs.d/")
 ;;(eval-after-load "tree-widget"
 ;;  '(if (boundp 'tree-widget-themes-load-path)
 ;;       (add-to-list 'tree-widget-themes-load-path "/app/skathirvel/.emacs.d/tree-widget")))
 ;;(autoload 'imenu-tree "imenu-tree" "Imenu tree" t)
 ;;(autoload 'tags-tree "tags-tree" "TAGS tree" t)
 ;;(autoload 'dirtree "dirtree" "Add directory to tree view" t)
 ;;(require 'sr-speedbar)
 ;; Customization examples:
 ;;
 ;; To ignore case by default:
 ;; (setq igrep-options "-i")
 ;; or:
  (setq igrep-case-fold-search t)
 ;; To search subdirectories by default:
  (setq igrep-find t)
 ;; To search files with the GNU (gzip) zgrep script:
 ;; (setq igrep-use-zgrep t)
 ;; or define new igrep commands (this works for zegrep and zfgrep as well):
 ;; (igrep-define zgrep); M-x zgrep
 ;; (igrep-find-define zgrep); M-x zgrep-find
 ;; To search "*.[ch]" files by default in C mode:
  (put 'igrep-files-default 'c-mode
       (lambda () "*.[ch]"))
 ;; To disable the default search regex and/or files pattern, except for
 ;; specific modes:
  (setq igrep-regex-default 'ignore)
  (setq igrep-files-default 'ignore)
 ;; To avoid exceeding some shells' limit on command argument length
 ;; (this only searches files in the current directory):
  (setq igrep-find t
        igrep-find-prune-clause "-type d \\! -name .")
 ;;(load-file "~/savehist-20+.el")
 ;;(savehist-mode 1)
 ;;(setq savehist-additional-variables '(kill-ring search-ring regexp-search-ring))
 ;;(setq savehist-file "/app/skathirvel/2006/emacs.savehist.txt")


Monday, August 28, 2006

semaphore and mutex/pthreads

Diff between semaphore and mutex.
Defn-1. Then a mutex is usually used for mutual exclusion of critical paths, while a semaphore is used for inter-thread synchronization and   event notifications.
Defn-2. A "mutex" (or "mutual exclusion lock") is a signal that two or more
asynchronous processes can use to reserve a shared resource for exclusive use.
 
The first process that obtains ownership of the "mutex" also obtains ownership of the shared resource. Other processes must wait for for the first process to release it's ownership of the "mutex" before they may attempt to obtain it.
 
Finally, a "semaphore" is a sort of "mutex" that is used to signal the availability of a plentiful resource. The source of the resource adds one to the semaphore for each unused resource available. As resources are taken away, the count in the semaphore is decremented (one for each removed resource) until it reaches zero (meaning that no more resources are available). At this
point, any remaining consumers of the resource must wait until the "semaphore" increments above zero, indicating that more resources are available.

Reference:
PThreads Primer
PThreads Manual

Diff between TCP and UDP

diff1=As a connectionless protocol, UDP does not incorporate any connection establishment, teardown, or maintenance logic. For example, a server supporting a UDP application with multiple simultaneous clients will need to allocate less memory to support these clients than would the corresponding TCP application server. Bandwidth throttling and in-order delivery features are properties of TCP, not UDP.

diff2= User Datagram Protocol (UDP)
The User Datagram Protocol (UDP) is a connectionless transport-layer protocol (Layer 4) that belongs to the Internet protocol family. UDP is basically an interface between IP and upper-layer processes. UDP protocol ports distinguish multiple applications running on a single device from one another.

Unlike the TCP, UDP adds no reliability, flow-control, or error-recovery functions to IP. Because of UDP's simplicity, UDP headers contain fewer bytes and consume less network overhead than TCP.

UDP is useful in situations where the reliability mechanisms of TCP are not necessary, such as in cases where a higher-layer protocol might provide error and flow control.
UDP is the transport protocol for several well-known application-layer protocols, including Network File System (NFS), Simple Network Management Protocol (SNMP), Domain Name System (DNS), and Trivial File Transfer Protocol (TFTP).

Shak.blog.notes 08/20/2024

Thinking Like an Architect - InfoQ tags: blog ...