Sunday, 13 November 2011

Fax Solution - Hylafax / IAXModems / Asterisk

Overview
This section depicts integration of Fax solution with Hylafax, IAXModem and Asterisk server. Hylafax is structured around client-server architecture. Hylafax client (JAVA API or Command) can be used by application to submit fax jobs to Hylafax Server. IAX Modems (as software) are used by Hylafax server to communicate with Asterisk Server. Hylafax provides support to send and receive faxes. We used Hylafax solution for sending fax.

Send flow of fax documents from application to fax machine (hard copy):


Application - > Hylafax Client -> Hylafax Server - > IAX Modems - > Asterisk Server - > Fax Machine


System Environment

Software
Version
Linux OS
Linux version 2.6.18-128.el5 (Red Hat 4.1.2-44)
Hylafax          
6.0.3  (http://www.HylaFax.org)
IAXModem
TED
2.21   (http://www.nllgg.nl/Ted/)

Asterisk
Asterisk is free, open source software that turns an ordinary computer into a feature-rich voice communications server. Asterisk makes it simple to create and deploy a wide range of telephony applications and services. Asterisk supports a wide range of telephony protocols. It includes rich support for the handling and transmission of voice over traditional telephony interfaces including analog lines, ISDN-BRI lines and digital T1/E1 trunks.

Hylafax:
Hylafax is an open source fax solution which is structured around client-server architecture. Fax modems may reside on a single machine on a network and clients can submit outbound jobs from any machine that can communicate with the machine on which the modems reside. An access control mechanism controls which users on which machines may access a server.

IAXModem
The IAXmodem application emulates a faxmodem, which would be operated by a HylaFax server to communicate with Asterisk server.

Integration Diagram 



 Issues Faced During Integration

     1.     IAXModems and FaxGetty services are not being started at system startup.
      
     Solution:
There is one Linux file '/etc/inittab' describes which processes are started at boot up.  Below entries have been added in same file to start IAXModem and FaxGetty services.
       
Syntax:
        id:runlevels:action:process
       
Entries:
        m0:5:respawn:/usr/bin/iaxmodem ttyIAX0
        f0:5:respawn:/usr/local/sbin/faxgetty ttyIAX0

Here ‘5’ is a default run level.
       
In case of services are not being started at system reboot, following two things must be ensured:

·         Id for all processes available in file must be unique. Like m0 or f0 should not be configured for other processes.
·         Ensure whether configured run level is a system default run level. On the shell, use below Linux command to check default run level
      $ runlevel

2.      IAXModems are not being registered with Asterisk server
     
      Solution:
·          Ensure the proper communication between box (Asterisk server) and box (Hylafax, IAXModem).
·          Ensure that firewall is not restricting communication between both boxes.
·          Ports for proper communication must be opened on both boxes.

 For example:

Asterisk Server listen IAX connections on port 4569. And IAXModem is configured with port 4570 (in file /etc/iaxmodem/ttyIAX0).  Port 4569 must be opened on IAXModem box and port 4570 must be opened on Asterisk server box.

·          Ensure following configuration files are in  proper unix format
        /etc/iaxmodem/ttyIAX0
       /var/spool/hylafax/etc/config.ttyIAX0
       /var/spool/hylafax/etc/config

      If not, use below command to convert in proper format.

      $ dos2unix       /etc/iaxmodem/ttyIAX0

3.      Outbound fax notification (as email) is not being sent by Hylafax server.
    
     Solution:
Ensure that whether 'sendmail' utility is working properly on Linux system. Use below command to check:
$ sendmail <email-id>

Type any text, press ENTER, type. (Dot), press ENTER. Mail should be delivered to mentioned email id. If not, check sendmail utility configurations. 

Questions & Answers

1.      How to flow dynamic information from Hylafax client to fax email notification?
     Ans:   Use below option with sendfax command to show dynamic information in email notification.
        sendfax -i <tag-value> -d <fax-number> <fax-document>
       <tag-value> can be retrieved in email notification templates using $jobtag variable.

     2.      How to create and use customized email notification template?
     Ans:   Script file ‘/var/spool/hylafax/bin/notify’ is responsible to call Hylafax email notification
     templates. Create new email notification template and modify 'notify' script to use the customized
     template.

Location of existing templates: /var/spool/hylafax/etc/templates

Below line is configured in /var/spool/hylafax/bin/notify file to use existing templates.

template="etc/templates/$TEMPLATE/notify-$WHY.txt"

Newly created file path can be assigned to template variable to use customized templates.

3.      How to convert RTF document to PS format?
     Ans: Use TED tool to convert RTF document into PS format. For more detail about TED
     referhttp://www.nllgg.nl/Ted/
  
References

Ø  Hylafax Source
http://www.HylaFax.org
Ø  Hylafax "sendfax" Command:
http://linux.die.net/man/1/sendfax
Ø  Online PS Viewer:
http://view.samurajdata.se/psview.php?id=2ad4f1f8&page=1&ori=1s
Ø  Hylafax Sendq Tags Description:
http://hylafax.sourceforge.net/man/sendq.php
Ø   Link for Fax Cleanup:
Ø   Summary of transmission errors
http://www.hylafax.org/HylaFAQ/Q344.html
Ø   Hylafax FAQ Archive:
http://www.hylafax.org/archive/2006-03/threads.php
Ø   Hylafax/IAXModem Setup (installation):
http://www.the-asterisk-book.com/unstable/faxserver-mit-iaxmodem-und-hylafax.html#faxe-empfangen
Ø   Configuring Multiple IAXModems:
http://www.trixbox.org/forums/trixbox-ce-development-forum/fax-development/multiple-incoming-faxes-hylafax-and-iaxmodem

Sunday, 6 November 2011

Logical Approach to Optimize Database Performance

Overview
Performance tuning is the major concern while processing data on databases. Though, there can be multiple approaches to tune the database performance at database side. But application specific approaches to optimize the performance always be kept in mind, because performance hit is solely depends on how you are going to get interacted your application with databases.This post demonstrates one of the good approaches to tune the database performance.
Problem Description

  • Scenario: Let us go through the problem and scenario first.
Let say, we want to store user information related to health plans where user can have multiple health plans. Below are the corresponding tables to store the data:
User Table:

User IdUser Name
U1Narendra

Health Plan Table:

Health Plan IdHealth Plan Name
1HP1
2HP2
3HP3
4HP4
5HP5
6HP6
7HP7
8HP8
9HP9
10HP10
..
..
nHPn


    User_Health_Plan_Mapping:

User IdHealth Plan Id
U11
U12
U13
U14
U15
U16
U17
U18
U19
U110
..
..
U1n





In terms of storing health plan information into database there can be a traditional approach i.e. storing mappings between users and health plans (see the aforementioned User_Health_Plan_Mapping table).
  • Disadvantages of this traditional approach
In this scenario, one thing must be observed that whenever health plan list is changed by user through UI, all old mappings need to be deleted and new mappings need to be inserted.
If we have to INSERT and DELETE ‘N number of rows’ only for one user, what about 50, 100 or 500 users?
Here we have to perform ‘delete’ and ‘insert’ data base operations multiple time. This can be the big performance hit.
Solution

How to get rid of this costly execution?
 A mathematical equation ‘2 to the power N’ (2N) can be used to get rid of this costly execution.

Series2122232425…..2N
Value2481632…..N
Below is the revised solution to avoid multiple mappings between user and health plans.
Add a new column in Health Plan table which will contain ‘2 to the power N’ digits:
User Table:

User IdUser Name
U1Narendra


   Health Plan Table:

Health Plan IdHealth Plan Name2_To_Power_N Value
1HP12
2HP24
3HP38
4HP416
5HP532
6HP664
7HP7128
8HP8256
9HP9512
10HP101024
...
...
nHPnN


Now in mapping table instead of having mappings with Health Plan Id, mapping should be with sum of the 2 to the power N digits.
User IdHealth Plan IdSUM_of_2_To_Power_N

U1
1
2046

Where 2046 = 2+4+8+16+32+64+128+256+512+1024
U12
U13
U14
U15
U16
U17
U18
U19
U110

Benefits
    • Only one row is required per user.
    • Only one row UPDATE operation is required rather multiple DELETE and INSERT operations.
Other Concerns

Now you must have one question in your mind. How to display actual health plan on UI if SUM is stored into database instead of multiple User-Health Plan mappings?
The solution is decryption of SUM of 2 to the power N digits.
For example:  32 + 16+ 4 =44 (SUM) --> Decryption Algorithm  -->   32, 16, 4 (List of separate digits)
Decryption Algorithm (Java Utility Class):
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Utility Class to decrypt the sum of 2 to the power N digits.
* @author nverma
*/
public final class CommonUtil {

   /**
    * Instantiates a new common util.
    */
   private CommonUtil() {
   }

   /**
    * Method gives list of individually added digits for given sum of
    * '2 to the power n'
    * For example: getAddedDigitsFor2PowerNSum(268L)
    * [Input]: sum = 268L (256 + 8 + 4)
    * 2^1 = 2
    * 2^2 = 4 <--
    * 2^3 = 8 <--
    * 2^4 = 16
    * 2^5 = 32
    * 2^6 = 64
    * 2^7 = 128
    * 2^8 = 256 <--
    * .
    * .
    * .
    * [Output]: [256, 8, 4]
    * @param sum of '2 to the power n' where n = 1,2,3,4...
    * @return List<Long> of individual digits
    */
   public static List<Long> getAddedDigitsFor2PowerNSum(Long sum) {

       Long input = sum;

       Integer maxIndex = 50;
       /*
        * Create map like below:
        * (value is 2 to power n where n = 1,2,3,4...)
        * evenNo.put(1, 2L);
        * evenNo.put(2, 4L);
        * evenNo.put(3, 8L);
        * evenNo.put(4, 16L);
        * evenNo.put(5, 32L);
        * evenNo.put(6, 64L);
        * evenNo.put(7, 128L);
        * evenNo.put(8, 256L);
        * evenNo.put(9, 512L);
        * evenNo.put(10, 1024L);
        */

       Map<Integer, Long> twoPowerNMap = new HashMap<Integer, Long>();

       Long twoPowerN = 2L;



       for (int index = 1; index <= maxIndex; index = index + 1) {
           twoPowerNMap.put(index, twoPowerN);
           twoPowerN = twoPowerN * 2;
       }

       // Get all individual digits for sum of '2 to the power N'
       // where N = 1,2,3,4...

       List<Long> result = new ArrayList<Long>();

       Long counter = input;
       Integer indexCounter = 0;

       while (counter > 0) {

           while (input > 1) {

               input = input / 2;
               indexCounter = indexCounter + 1;
           }

           // Get the integer from index position
           Long valOfIndex = twoPowerNMap.get(indexCounter);
           result.add(valOfIndex);

           indexCounter = 0;
           input = counter - valOfIndex;
           counter = input;
       }

       return result;
   }
}

***If you think you need more detail and understanding on this approach keep on commenting...:)