My favorite motivational quotes

I have been keeping a list of quotes which I read once in a while to motivate myself and to push myself to do the right things instead of doing things which are convenient. These has been a great source of inspiration for me. So instead of maintaining the list in my drafts, I decided to share it with others and inspire them too. I will keep updating this list with the new ones I like.

 

  1. It is better to deserve honors and not have them than to have them and not deserve them.”
      by Mark Twain
  2. “Character is the result of two things: mental attitude and the way we spend our time.”
      by Elbert Green Hubbard
  3. “When it’s time to die, let us not discover that we have never lived.”
      by Henry David Thoreau
  4. “A healthy attitude is contagious but don’t wait to catch it from others. Be a carrier.”
      by Anonymous
  5. “As you think, so shall you become.”
      by Bruce Lee
  6. “Always be yourself, express yourself, have faith in yourself, do not go out and look for a successful personality and duplicate it.”
      by Bruce Lee
  7. “If you love life, don’t waste time, for time is what life is made up of.”
      by Bruce Lee
  8. “Real living is living for others.”
      by Bruce Lee
  9. “Happiness is not by chance, but by choice.”
      by Jim Rohn
  10. “Without a sense of urgency, desire loses its value.”
      by Jim Rohn
  11. “Do not go where the path may lead, go instead where there is no path and leave a trail.”
      by Ralph Waldo Emerson
  12. “A man is what he thinks about all day long.”
      by Ralph Waldo Emerson
  13. “Before we acquire great power we must acquire wisdom to use it well.”
      by Ralph Waldo Emerson
  14. "When you choose to be pleasant and positive in the way you treat others, you have also chosen, in most cases, how you are going to be treated by others.”
      by Zig Ziglar
  15. “Great spirits have always encountered violent opposition from mediocre minds.”
      by Albert Einstein
  16. “Try not to be a person of success, but rather a person of virtue.”
      by Albert Einstein
  17. “How wonderful it is that nobody need wait a single moment before starting to improve the world.”
      by Anne Frank
  18. “We are what we repeatedly do. Excellence, therefore, is not an act but a habit.”
      by Aristotle
  19. “Experience is the child of thought, and thought is the child of action.”
      by Benjamin Disraeli
  20. “To talk goodness is not good… only to do it is.”
      by Chinese proverb
  21. “An optimist is a person who sees a green light everywhere. The pessimist sees only the red light. But the truly wise person is color blind.”
      by Dr. Albert Schweitzer
  22. “If you have built castles in the air, your work need not be lost. That is where they should be. Now put the foundation under them.”
      by Henry David Thoreau
  23. “Every man must decide whether he will walk in the light of creative altruism or in the darkness of destructive selfishness.”
      by Martin Luther King Jr.

If you know of any quotes which you think might fit in this list, please leave it as a comment.

Thanks,
Kanwal

Application specific mapping in FastCGI ISAPI 1.5

IIS team recently released FastCGI ISAPI 1.5 for IIS 5.1 and IIS 6.0. One of the major new features added in this release is per application process pools. Per application process pools allow users to specify a unique FastCGI mapping for a particular web application in fcgiext.ini. Using this functionality administrators can now choose to run a web application with PHP version which can be different from what is used for rest of the PHP applications in the same site or the server. This was always possible in IIS 7.0 and 7.5 by overriding PHP handler in web.config but not on WinXP and Win2K3. Version 1.0 of FastCGI ISAPI only allowed specifying a different process pool at a site level granularity. So if a site has both wordpress and gallery installed, it wasn’t possible to use different PHP versions for running them. With FastCGI 1.5 that is possible now. For providing application specific mappings, we extended site specific mapping feature. Let’s learn application specific mapping by comparing it with site specific mapping.
 

 

 
Site specific mapping
Application specific mapping
fcgiext.ini
[Types]
php=PHP_53
php:1234=PHP_52
 
[PHP_53]
ExePath=c:\php530\php-cgi.exe
 
[PHP_52]
ExePath=c:\php520\php-cgi.exe
[Types]
Php=PHP_530
Php:1234=PHP_526
Php:/w3svc/1234/root/wordpress=PHP_530
Php:/w3svc/1234/root/gallery=PHP_520

[PHP_526]
.
.
.

Details
Above configuration will make FastCGI module pick PHP_53 mapping for all sites but use PHP_52 mapping for site with id 1234.
FastCGI module will pick PHP_520 mapping for gallery and PHP_530 for wordpress defined under site 1234. All other php applications under site 1234 will be handled using PHP_526 mapping. Remaining sites will use PHP_530 mapping.

Application path’s format for fcgiext.ini is “/LM/W3SVC/<siteId>/ROOT/<appname>”. In this format “/LM” and “/W3SVC” parts are option. “/Root” can be emitted for applications pointing to root of the site.

fcgiconfig.js
fcgiconfig.js -add -section:php_530 -extension:php -path:c:\php530\php-cgi.exe -site:1234
fcgiconfig.js -add -section:php_530 -extension:php -path:c:\php530\php-cgi.exe -application:/w3svc/1234/root/wordpress
 
 
Picking the right mapping
Among all the formats (including wildcard formats) which are accepted in fcgiext.ini mappings, FastCGI goes through following logic to pick which mapping to use for each request.
 
·         If mapping for current  application is present, it takes highest priority and is used. E.g. php:/w3svc/1234/root/drupal=ApplicationHandler
·         If wildcard mapping for the current application is present, it is used next. E.g. *:/w3svc/1234/root/drupal=ApplicationHandler
·         If mapping for a particular site is present but application specific mapping is not present, than that is used. E.g. php:1234=SiteHandler
·         If site specific and application specific mapping is not present, FastCGI module look for wildcard mapping for a particular site. E.g. *:1234=SiteHandler
·         If none of the above is present, mapping for the file extension takes priority. E.g. php=ExtensionHandler
·         Wildcard mapping comes last. *=WildcardHandler
 
If FastCGI doesn’t find a mapping after going through the logic above, an error is returned.
 
What’s coming next
 
Now that applications can be configured to run using a particular PHP version on IIS 5.1 and above, our next goal is to support multiple PHP versions side-by-side in WebPI. This would require PHP installer to support side-by-side install which is also something we are looking at. Once PHP installer has the required support, we will list different PHP versions in WebPI and let users install multiple versions of PHP. Additionally users will be able to target a particular PHP version when installing a PHP application using WebPI.
 
Hope this helps.
Kanwal

Inconsistencies in wincache statistics page explained

Problem description

 

Many customers running WinCache reported seeing different cache statistics on consecutive requests to wincache.php. Specifically, cache uptime and opcode cache summary returned second time by wincache.php was completely different than the data returned first time. Occasionally data shown in the opcode cache summary table didn’t match the chart displayed on its side. Many customers correctly guessed that this happens because there are multiple cache instances present in different php-cgi processes but thought that none of the PHP processes are sharing cache data and were worried about excessive memory usage by WinCache. I have been replying to many customers personally and posting on forums explaining why they see this behavior but as more and more customers are using WinCache, this question is becoming more common. Ruslan who is PM for WinCache suggested writing a blog post to help customers understand the reason. So here you go.

 

Detailed explanation

 

WinCache creates many memory segments which are shared among all the php-cgi processes launched by a particular IIS worker process. For simplicity sake I will use the term “all php processes” to refer to “all php processes launched by one IIS worker process”. In version 1.0, WinCache creates 5 shared memory segments. Mostly these segments are shared successfully among all the php processes. In fact 4 shared segments are always shared but memory segment for opcode cache is sometimes not shared. Reason for this is that 4 of the 5 memory segments store data structures which are completely defined by us. Anytime we need to store a pointer in the shared segment which points to some other data in the shared segment, we define pointer as simple integer which is then set to offset from start of memory segment. This way other processes can reach the data pointed by this pointer even when absolute address of the data might be different. In contrast, data stored in opcode cache is defined by the PHP engine and include many absolute pointers. These pointer values cannot be changed to offsets without incurring a very heavy performance penalty which will totally defy the purpose of WinCache. For this reason, we try to map the global opcode cache segment at same address in all processes using MapViewOfFileEx which can possibly fail if the address is already occupied. All other caches doesn’t have this restriction and are mapped anywhere which mostly succeed. If we fail to map the opcode cache at a particular address, we create another opcode cache in processs local memory so that requests processed by this process are also very fast. Typically this happens for 5%-10% of php processes. Below figures illustrates state of the caches in a normal php process (figure 1) and in a process which ends up creating a local cache (figure 2). For more information on these caches, read my previous blog.

 

Local Cache Explanation

Now that you understand this design, all the anomalies seen in responses of wincache.php can be explained. If the process which processes request to wincache.php has a local cache, opcode cache data will be different from the one shown when request is handled by a process which is using global opcode cache. Also since cache uptime in wincache.php is picked from opcode cache (ocache_fileinfo), it will be age of either global opcode cache or local opcode cache. Reason why chart sometimes didn’t match opcode cache summary is because request to draw the chart is sent separately. If the chart draw request reaches a process which has different cache structure than the one which returned summary data, there can be a mismatch.

 

Improvements in WinCache 1.0.1

 

In WinCache 1.0.1, we have made few changes to wincache.php which will make all this a little less confusing. Since cache uptime can be different for file cache and opcode cache, we have moved the cache uptime field to opcode cache and file cache summary tables. So you will now see two cache uptimes. File cache uptime will reflect age of global file cache and opcode cache uptime will reflect age of global or local opcode cache. We also added cache scope property in opcode cache summary table which will be either “global” or “local”. This will indicate if the opcode cache data you are looking at is for global cache or a local cache. To fix the chart discrepancy, we now send data required to draw the chart in the request itself so that chart always matches the data in the summary table. All these changes were made based on feedback from you. So keep sending your feature requests and feedback so that we can keep improving WinCache.

 

Hope this helps.

Kanwal

Using windows live as SMTP relay server

Today I started writing a program to notify me when IP assigned to my router by my broadband provider changes. I wanted this program to check IP address of the router every few minutes and send me email if it detects that IP is changed. For sending email, I used System.Net.Mail.SmtpClient which requires a smtp host. Instead of running a smtp server on my machine, I started looking for free smtp relay servers available on the internet. I was surprised to find out that there are plenty of them available. In fact most of the popular email service providers like windows live, yahoo, gmail offer smtp relay services. You can read more about smtp relay servers and get a list of freely available smtp relay servers here.

Below is the code I used to send email notification using windows live smtp relay. If you want to use gmail, you can use "smtp.gmail.com" as the smtphost with gmail credentials.

static
bool SendEmailNotification(string newIpAddress)
{
    bool success = false;

    //
    // Send email using live account
    //
    SmtpClient mailClient = new SmtpClient("smtp.live.com", 587);
    mailClient.UseDefaultCredentials = false;
    mailClient.EnableSsl = true;

    MailMessage message = new MailMessage("WindowsLiveUserName@live.com", destination@domain);
    message.Subject = "Require immediate action – IP address change";
    message.Body = "New IP address is " + newIpAddress;
    message.Priority = MailPriority.High;

    NetworkCredential credentials =
       
new NetworkCredential("WindowsLiveUserName@live.com", "YourPassword", "");
    mailClient.Credentials = credentials;

    try
    {
        mailClient.Send(message);
        success = true;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }

    return success;
} 

 

I am still making some changes to my IpChangeMailer program. I will make it available for download once it is complete.

Thanks.
Kanwal

WaitForAllObjects to wait on more than MAXIMUM_WAIT_OBJECTS handles

One of the painful limitations of WaitForMultipleObjects function is that you can use it to wait for a maximum of MAXIMUM_WAIT_OBJECTS number of object handles. Value of MAXIMUM_WAIT_OBJECTS is 64. If you need to wait on more than MAXIMUM_WAIT_OBJECTS handles, you can either create a separate thread to wait on MAXIMUM_WAIT_OBJECTS and then do a wait on these threads to finish. Using this method you can create MAXIMUM_WAIT_OBJECTS threads each of those can wait for MAXIMUM_WAIT_OBJECTS object handles. Few months ago I needed code for doing this and couldn't find it on the internet. Here is how I implemented WaitForAllObjects.

typedef
struct _WAIT_THREAD_INFORMATION
{
    DWORD      dwWaitObjectCount;
    PHANDLE    pWaitHandles;
    DWORD      dwWaitMSeconds;
} WAIT_THREAD_INFORMATION, *PWAIT_THREAD_INFORMATION;

VOID
WaitForAllObjects(
    DWORD     dwWaitHandleCount,
    HANDLE *  pWaitHandles,
    DWORD     dwMaxWaitMSeconds
)
{
    HANDLE *                  pThreadWaitHandles    = NULL;
    WAIT_THREAD_INFORMATION * pWaitInformationArray = NULL;

    DWORD                     dwThreadCount         = 0;
    DWORD                     dwLastWaitCount       = 0;
    DWORD                     dwWaitHandleIndex     = 0;
    DWORD                     dwMaximumWaitObjects  = MAXIMUM_WAIT_OBJECTS;

    ASSERT( dwWaitHandleCount    >  0 );
    ASSERT( pWaitHandles         != NULL );
    ASSERT( dwMaxWaitMSeconds    >= 1000 );
    ASSERT( dwMaximumWaitObjects <= MAXIMUM_WAIT_OBJECTS );

    if( dwWaitHandleCount <= dwMaximumWaitObjects )
    {
        WaitForMultipleObjects( dwWaitHandleCount,
                                pWaitHandles,
                                TRUE,
                                dwMaxWaitMSeconds );
    }
    else
    {
        //
        // Create separate threads to wait on maximum wait objects
        // and then make this thread wait on thread handles
        //
        dwThreadCount   = dwWaitHandleCount / dwMaximumWaitObjects;
        dwLastWaitCount = dwWaitHandleCount % dwMaximumWaitObjects;

        if( dwLastWaitCount > 0 )
        {
            dwThreadCount++;
        }

        //
        // This function can handle a maximum of
        // MAXIMUM_WAIT_OBJECTS * MAXIMUM_WAIT_OBJECT handles
        //
        if( dwThreadCount > dwMaximumWaitObjects )
        {
            dwThreadCount     = dwMaximumWaitObjects;
            dwLastWaitCount   = 0;
        }

        pThreadWaitHandles    = new HANDLE[ dwThreadCount ];
        pWaitInformationArray = new WAIT_THREAD_INFORMATION[ dwThreadCount ];

        if( pThreadWaitHandles == NULL || pWaitInformationArray == NULL )
        {
            //
            // Failure
            //
            goto Finished;
        }

        for( DWORD count = 0; count < dwThreadCount; count++)
        {
            //
            // Set information for the thread
            //
            pWaitInformationArray[ count ].dwWaitMSeconds =
                dwMaxWaitMSeconds;
            pWaitInformationArray[ count ].pWaitHandles =
                &pWaitHandles[ dwWaitHandleIndex ];

            if( count != dwThreadCount - 1 || dwLastWaitCount == 0 )
            {
                pWaitInformationArray[ count ].dwWaitObjectCount =
                    dwMaximumWaitObjects;
                dwWaitHandleIndex += dwMaximumWaitObjects;
            }
            else
            {
                pWaitInformationArray[count].dwWaitObjectCount =
                    dwLastWaitCount;
                dwWaitHandleIndex += dwLastWaitCount;
            }

            pThreadWaitHandles[ count ] =
                CreateThread( NULL,
                              0,
                              WaitForMultipleObjectsThread,
                              &pWaitInformationArray[ count ],
                              0,
                              NULL );
            if( pThreadWaitHandles[ count ] == NULL )
            {
                //
                // Not able to create threads break from the loop
                // and wait for threads
we already created.
                // dwThreadCount doesnt include this iteration
                //
                dwThreadCount = count;
                break;
            }
        }

        //
        // Failure is ignored
        //
        WaitForMultipleObjects( dwThreadCount,
                                pThreadWaitHandles,
                                TRUE,
                                dwMaxWaitMSeconds );
    }

Finished:

    if( pThreadWaitHandles != NULL )
    {
        for( DWORD count = 0; count < dwThreadCount; count++)
        {
            if( pThreadWaitHandles[ count ] != NULL )
            {
                CloseHandle( pThreadWaitHandles[ count ] );
                pThreadWaitHandles[ count ] = NULL;
            }
        }

        delete [] pThreadWaitHandles;
        pThreadWaitHandles = NULL;
    }

    if( pWaitInformationArray != NULL )
    {
        delete [] pWaitInformationArray;
        pWaitInformationArray = NULL;
    }

    return;
}

//static
DWORD
WINAPI
WaitForMultipleObjectsThread(
    LPVOID lpParameter = NULL
)
//
// Thread routine which calls WaitForMultipleObjects
// This is used to wait for more than MAXIMUM_WAIT_OBJECTS objects
//
{
    DWORD                    dwReturnValue      = 0;
    PWAIT_THREAD_INFORMATION pThreadInformation = NULL;

    ASSERT( lpParameter != NULL );

    pThreadInformation = ( PWAIT_THREAD_INFORMATION )lpParameter;

    ASSERT(pThreadInformation->dwWaitObjectCount <= MAXIMUM_WAIT_OBJECTS );
    ASSERT(pThreadInformation->pWaitHandles      != NULL );
    ASSERT(pThreadInformation->dwWaitMSeconds    != INFINITE );
    ASSERT(pThreadInformation->dwWaitMSeconds    >= 1000 );

    dwReturnValue = WaitForMultipleObjects(
                        pThreadInformation->dwWaitObjectCount,
                        pThreadInformation->pWaitHandles,
                        TRUE,
                        pThreadInformation->dwWaitMSeconds );

    return dwReturnValue;

}

Sample usage of this method will look like below.

//
// Allocate memory for wait handle array
//
pWaitHandles = new HANDLE[ dwWaitHandleCount ];

...

//
// Call WaitForAllObjects
//
WaitForAllObjects( dwWaitHandleCount,
                   pWaitHandles,
                   dwMaximumWait );

...

//
// Free memory held by pWaitHandles
//
if( pWaitHandles != NULL )
{
    delete [] pWaitHandles;
    pWaitHandles = NULL;
}

Hope this helps.
Kanwal