Friday, July 21, 2017

Design Pattern example: Singleton and Observer (Part I)

Copyright © 2017, Steven E. Houchin. All rights reserved.

I've lately been developing a parser library for a certain standard file format used for data interchange between some programs.  At various points in the parsing process, my code detects errors, and I wanted a mechanism to log those errors.  The parser consists of a gaggle of classes (in C#) that encapsulate various data structures, any of which may generate errors or warnings about file format issues.  I certainly didn't want to pass a reference to a logger object as a parameter to every method in every class to accomplish the error logging.

Thinking about the functionality of logging errors, multiple instances of a logger object didn't make sense.  So, I designed a logger class based upon the Singleton design pattern, where one instance of the class is created at first use, and that same instance is retained for subsequent uses:


public class Logger : object
{
    // The Singleton instance
    protected static Logger _instance;

    /// Hidden constructor
    private Logger()
    {
    }

    /// Get the only instance of the class
    public static Logger Instance
    {
        get
        {
            // Get the only instance, creating new if necessary
            if (_instance == null)
            {
                _instance = new Logger();
            }
            return _instance;
        }
    }
        
    public static void Free()
    {
        // Free the only instance when done with the parser
        _instance = null;
    }

    public void LogError(string msg)
    {
        // ... do something to log the error somewhere ...
    }
} // end class Logger

The parser library methods simply get a reference to Logger's class instance like this:

   
    Logger log = Logger.Instance;
    log.LogError("Parse error.");

Each call to the Logger's Instance property returns the same object instance, no matter where in the code it is called.

My next design task was to decide how and where to log the error message itself.  Ultimately, I decided the Logger class shouldn't be burdened with the detail of "where" to log the error. What if App1 wants the library to log to a file, and App2 wants the log rendered to the UI?  At first, I just dumped the messages into an ArrayList, and the parent App would pull them out at its leisure at a later time.  But that was inelegant and didn't notify the App of the error in real time.

The key word I just used there is "notify."  That idea implies a callback, and that brought to mind the Observer design pattern, for which notification is a central part of the concept. For example, Object-A's state changes via some event, and it notifies Object-B of the change. In Observer, though, notifications may also be sent to Objects C and D and E.  So, Objects B through E must register as interested observers with Object-A, and unregister when no longer interested.

To implement Observer, my Logger class needed a callback interface for the observers, registration/deregistration methods, and a structure of some kind to keep track of each observer.

First, the callback interface:


///
/// Interface to be implemented by objects who wish to
/// observe changes on the Logger object's data.
///
public interface ILoggerObserver
{
    void didAddLogMessage(string message);
}

Each of the observer classes must derive from the above ILoggerObserver interface and implement the didAddLogMessage method, which allows the observer to do whatever it wishes to log the message.

Next, a List to keep track of the observer registrations:


public class Logger : object
{
    // The Singleton instance
    protected static Logger _instance;

    // List of Observer objects to be notified of
    // changes to the log
    protected List(lt)ILoggerObserver(gt) _observers;

    /// Hidden constructor
    private Logger()
    {
         _observers = new List(lt)ILoggerObserver(gt)();
    }

    ...

}

Of course, the (lt) and (gt) above are really < and > that don't render well in the HTML code snippet above.

Now, we need the registration/deregistration methods in the Logger class.  These will be made more sophisticated in a follow-on posting.

    /// Add an Observer object to the list of those
    /// to be notified of changes.
    public void Attach(ILoggerObserver observer)
    {
        if (null != observer)
        {
            // Add this observer to the list, but just once
            Detach(observer);
            _observers.Add(observer);
        }
    }

    /// Remove an Observer object from the list.
    public void Detach(ILoggerObserver observer)
    {
        if (null != observer)
            _observers.Remove(observer);
    }

So, finally, the user's parser code initializes logging by registering as an Observer, and calls the parser:

public class MyParser : ILoggerObserver
{
    ...

    public void MyParseLogic()
    {
        Logger log = Logger.Instance;
        log.Attach(this); // become a Logger observer

        Parser p = new Parser(my_file_path_to_be_parsed);
        p.Parse(); // will call the same Logger instance

        log.Detach(this); // resign as a Logger observer

        ...
    }

    /// Implement the ILoggerObserver interface
    public void didAddLogMessage(string message)
    {
        // Output the message to a TextBlock control or
        // pop up a Message Box.
        ...
    }

} // end class MyParser

With follow on postings, I'll show the Logger's notification logic, and a better way to unregister as an observer.

Wednesday, July 29, 2015

UITableViewCell and backgroundView


Copyright © 2015, Steven E. Houchin. All rights reserved.

I have some code that modifies a table view cell so that it acts like a gradient-colored button within a grouped table view. I'm developing for iOS 6.1. When the cell is to be shown (via tableView:willDisplayCell:forRowAtIndexPath:) the gradient color is rendered into a UIView using a CAGradientLayer object.  Actually, I create two of these UIViews: one for the normal button state and one for the pressed state.  Each of these two views are saved into the UITableViewCell's "backgroundView" and "selectedBackgroundView" properties, thus giving the button-like behavior.

But, while doing this, I ran into a problem: cell reuse. In my tableView:cellForRowAtIndexPath: callback, I was using dequeueReusableCellWithIdentifier: to get all of my table's cells - even the gradient-colored ones. One of the issues with cell reuse this way is that you must make sure to reset the reused cell's properties to a known default state.  Otherwise a cell can inherit properties set for a completely different cell last time through.

Well, I was doing just that - resetting properties - except for "backgroundView" and "selectedBackgroundView".  By not resetting those, the gradient colors appeared in cells where they were not intended.  So, I added this to my cell reset code:
[tableView setBackgroundView:nil];
[tableView setSelectedBackgroundView:nil];
Well, the result was a mess.  All of the grouped table view cells lost their rounded-edge borders.  It turns out that these background view properties have view objects set by default that provide the grouped table view cells their rounded look, so can't be set to null.  I suppose I could have copied the values and saved them somewhere to restore later when resetting the reused cell properties, but that seemed like the wrong thing to do.

The solution was to create a pool of separate reusable cells for the gradient cells. For these cells, which are within their own table view sections, I used the table view method dequeueReusableCellWithIdentifier:forIndexPath:, specifying a different identifier string for it than for the standard cells.  But, one glitch with this approach is that, to use this method, I also had to first register the cell identifier string for the class in my viewDidLoad method:
[[self tableView] registerClass:[UITableViewCell class]
               forCellReuseIdentifier:@"GradientCellId"];
Once I did that, then cell reuse in tableView:cellForRowAtIndexPath: worked great for both the gradient cells and the normal cells since they now draw from different reuse pools:
UITableViewCell *cell;
NSString *cellid;
if (MyTableSectionGradient == [indexPath section])
{
        cellid = @"GradientCellId";
        cell = [tableView dequeueReusableCellWithIdentifier:cellid
                                               forIndexPath:indexPath];
}
else
{
        cellid = @"NormalCellId";
        cell = [tableView dequeueReusableCellWithIdentifier:cellid];
}
if (!cell)
{
        cell = [[UITableViewCell alloc]
                                  initWithStyle:UITableViewCellStyleDefault
                                reuseIdentifier:cellid];
}


Monday, January 14, 2013

OSX AuthorizationExecuteWithPrivileges example

Copyright © 2013, Steven E. Houchin. All rights reserved.

I've read various posts online about developers' travails with OSX's AuthorizationExecuteWithPrivileges API, and misunderstanding about how it works.  So, here is some of what I've learned about it.

Apple's documentation states that it "Runs an executable tool with root privileges."  But, users soon discover that the new process does not, in fact, run as root.  In reality, the new process executes at an elevated privilege level that allows it to become the root user by calling 'setuid(0)'.  For example:

// Fork a child process
pid_t child_pid = fork();
if(child_pid == 0)
{
  // This is done by the child process
           
  // Change to the root user
  uid_t userid = getuid();
  setuid(0);  // set root permissions 

  // Do things as root ... 

  // Restore normal permissions
  setuid(userid);
  exit(0);
}

Note that there is danger in using AuthorizationExecuteWithPrivileges.  For example, your app might invoke a helper tool named 'grok' that will execute with the elevated privileges.   If a hacker figures out that 'grok' is started this way, he can replace 'grok' with his own trojan binary, which can then make itself root and thus do nasty things to your system. It isn't really hard for a hacker to determine that 'grok' is invoked this way, because the MAC's Console utility logs that AuthorizationExecuteWithPrivileges was called to execute 'grok.'   So, if you must execute 'grok' this way, your app should first validate the 'grok' binary in some way to make sure it has not been tampered with.  What I did was to open 'grok' as a binary data file and then I scan it for a known string used in the code, such as an innocuous printf format string.

The first parameter to AuthorizationExecuteWithPrivileges is an AuthorizationRef object.  This is obtained via a call to AuthorizationCreate:

AuthorizationRef authorizationRef;
OSStatus status = AuthorizationCreate(NULL,
                       kAuthorizationEmptyEnvironment,
                       kAuthorizationFlagDefaults,
                       &authorizationRef);
if (status != errAuthorizationSuccess)
{
    // Notify user of the error ...
}

The actual elevated rights you request are specified via a call to AuthorizationCopyRights, at which time the user is prompted to enter his password.  Along with requesting certain rights, you can specify a custom icon and text for the password popup.  Note however that your icon will not appear if it resides in a directory beneath any ancestor directory that lacks Everyone access.  Here's what the icon specification looks like, which is passed as the AuthorizationEnvironment parameter to AuthorizationCopyRights:

AuthorizationItem kAuthEnv[1];
const char *iconPath = "/Applications/MyApp.app/Resources/myicon.icns";
kAuthEnv[0].name = kAuthorizationEnvironmentIcon;
kAuthEnv[0].valueLength = strlen(iconPath);
kAuthEnv[0].value = (void *)iconPath; // fully qualified path
kAuthEnv[0].flags = 0;
AuthorizationEnvironment authorizationEnvironment;
authorizationEnvironment.items = kAuthEnv;
authorizationEnvironment.count = 1;

Next, in order to use AuthorizationExecuteWithPrivileges, you must request the "system.privilege.admin" right.  You set this up as follows:

const char *grokPath = "/Utilities/grokUtil/grok";
AuthorizationItem executeRight = {
                        kAuthorizationRightExecute,
                        strlen(grokPath)
                        (void *)grokPath,
                        0};
AuthorizationRights rightsSet = {1, &executeRight};

Note that kAuthorizationRightExecute is defined as "system.privilege.admin" in the Security framework's AuthorizationTags.h.  This is then used in AuthorizationCopyRights to actually acquire the rights for the AuthorizationRef object:

AuthorizationFlags flags =
                  kAuthorizationFlagDefaults |
                  kAuthorizationFlagInteractionAllowed |
                  kAuthorizationFlagPreAuthorize |
                  kAuthorizationFlagExtendRights;

// Call AuthorizationCopyRights to determine
// or extend the allowable rights
OSStatus status = AuthorizationCopyRights(
                                authorizationRef,
                                &rightsSet,
                                &authorizationEnvironment,
                                flags,
                                NULL);
if (errAuthorizationCanceled == status)
{
    // User canceled authentication  ...
}
else if (status != errAuthorizationSuccess)
{
    // Notify the user of the error ...
}

All that's left at this point is to execute the privileged helper tool:

FILE *fpStdout = NULL;
status = AuthorizationExecuteWithPrivileges(
                        authorizationRef,
                        (const char *)grokPath,
                        kAuthorizationFlagDefaults,
                        argv,  // normal argv array of program args
                        &fpStdout);
bool success = (status == errAuthorizationSuccess);
pid_t newProcId;
if (success)
{
   // Get the new process id
   newProcId = fcntl(fileno(fpStdout), F_GETOWN, 0);
   fclose(fpStdout);
}
else
{
   // Notify user of the error ...
}

AuthorizationExecuteWithPrivileges returns as soon as the new process has started.  It does not execute it as a child of the current process, so a waitpid on the resulting process id gives an error.

Friday, February 10, 2012

Learning to hate AllocateAdapterChannel

Copyright © 2012, Steven E. Houchin. All rights reserved.

I have a scatter-gather device I'm supporting in a Windows PNP driver. Normally, a driver developer would use the GetScatterGatherList API to map multiple IRP buffers to a device's DMA capabilities. However, in my case, my device has peculiar buffer alignment requirements that I can't count on GetScatterGatherList to handle. But, no worries. The AllocateAdapterChannel API is available.

Wait! Not so fast. In order for my device to perform at peak speed, multiple Read and Write IRPs are simultaneously active and mapped to the DMA. What this means is, I can't wait for the occurrence of an interrupt and an IRP completion before mapping the next IRP to the DMA; I map dozens or hundreds of them to the DMA in advance.

GetScatterGatherList handles all this just fine as long as each IRP has its own associated separate DMA_ADAPTER object. In theory, AllocateAdapterChannel should be able to do the same, but it can't. There is this sneaky little note in the WDDK documentation that throws a fly into the oatmeal:

Only one DMA request can be queued for a device object at any one time. Therefore, the driver should not call AllocateAdapterChannel again for another DMA operation on the same device object until the AdapterControl routine has completed execution.

The key phrase there is "device object." DEVICE_OBJECT is a parameter to AllocateAdapterChannel. So, even if I have a separate DMA_ADAPTER object for each mapped IRP, it still uses just the one DEVICE_OBJECT. The note above blandly states "until the AdapterControl routine has completed execution." Exactly how do I know when it completes execution? If the driver is executing its assembly "ret" instruction, it is technically still in the AdapterControl callback, so anything I do inside it to notify another thread to proceed is too early.

I believe the issue here is that DEVICE_OBJECT is placed on a wait list by the kernel when the DMA is not immediately available. Thus, we can't have that object placed twice on a list. Maybe the answer is to create a separate, fake DEVICE_OBJECT for each IRP, just like I do with DMA_ADAPTER.

Charging ahead, I created a pool of DEVICE_OBJECTs, copied from the original, and used them round-robin for each simultaneous AllocateAdapterChannel, preventing any more calls if none available.

No luck. The failure manifests itself by the AdapterControl being called back twice in a row for the same IRP - i.e. two calls to AdapterControl for an IRPs single call to AllocateAdapterChannel. Now, maybe I am still doing something wrong managing my fake DEVICE_OBJECTs. For example, when do I really know that a DEVICE_OBJECT is available for reuse? It's the fly and oatmeal problem again with the AdapterControl callback: when has it really "completed execution?"

For now, I don't have a workable solution to this. I'll let you know if I figure it out.

Monday, October 24, 2011

Computing the viewport size within a WPF Border control

Copyright © 2011, Steven E. Houchin. All rights reserved.

I have a WPF application that renders a photo bitmap inside a System.Windows.Controls.Image control that is contained within a System.Windows.Controls.Border. If the photo bitmap is too large for the app window (either in the horizontal or vertical direction), I set the Image's corresponding size attribute(s) to 'Auto' (i.e. Double.NaN) within the Image's SizeChanged event handler. If the bitmap is smaller than the app window, I set the Image's size to the actual fixed size of the bitmap, so it doesn't get scaled.

But, that left a problem when I resized the app window smaller: a fixed-size Image was truncated by the border when the window shrank smaller than the photo's bitmap size. And, because the Image's width/height weren't set to Auto, its SizeChanged event wasn't firing.

However, the Border's SizeChanged event was firing. So, I added that handler for the Border control, planning to set the Image's proper width/height after resize.  That left another problem in this new event handler: how to calculate whether or not the Image control's width/height should be Auto or fixed.  Put another way, what was the size of the viewport inside the Border control where the Image would be rendered?

The Border's SizeChanged event handler is passed a SizeChangedEventArgs parameter that provides the new width/height of the Border control. The size available to the Image control inside that will clearly be smaller, but by how much? Here is the algorithm in C# that I came up with (keep in mind that a negative BorderThickness means the border is drawn outside the control's drawing area):

// Calculate the Border control's new viewport
// size within the drawn border where the Image control
// is rendered (add in any padding and non-negative
// border thickness).
Size viewport = new Size();
viewport.Width = e.NewSize.Width -
    (border.Padding.Left + border.Padding.Right) -
    ((border.BorderThickness.Left > 0) ?
        border.BorderThickness.Left : 0) -
    ((border.BorderThickness.Right > 0) ?
        border.BorderThickness.Right : 0);
viewport.Height = e.NewSize.Height -
    (border.Padding.Top + border.Padding.Bottom) -
    ((border.BorderThickness.Top > 0) ?
        border.BorderThickness.Top : 0) -
    ((border.BorderThickness.Bottom > 0) ?
        border.BorderThickness.Bottom : 0);
This viewport variable now holds the size available for the Image control inside the border. Now, all I have to do is determine if the Image needs to be scaled down in the viewport or set to a fixed size. One thing I discovered is that the Image's Margin value must be taken into account, since it is also rendered inside the viewport along with the photo bitmap. The code to determine the right sizing, in this case for the width is:

// Calculate the image's real width to determine if
// scaling is needed
double imageWidth = _bitmapActualSize.Width +
    image.Margin.Left + image.Margin.Right;
if (viewport.Width > imageWidth)
{
    // Restrict the Image control's width to the
    // bitmap's actual width
    image.Width = _bitmapActualSize.Width;
}
else if (viewport.Width < imageWidth)
{
    if (Double.NaN != image.Width)
    {
        // Set the Image control's width to 'Auto' so
        // it will scale down to fit
        image.Width = Double.NaN;
    }
}
The same calculation is done for the Image height immediately after. This results in the proper change to the photo bitmap size just at the right time.

Wednesday, August 31, 2011

Eliminating Visible Image Borders on Blogger

Copyright © 2011, Steven E. Houchin

Something that has driven me crazy for quite awhile about Blogger is its propensity to place a thick white border around any image I added to my postings. Editing the HTML of the img element to include border="0" or a style="border: none;" or anything else like that was simply ignored. What the heck was happening?

Then, I found a hint on another site, where it referred to Blogger's "template style sheet." After some poking around in Blogger, I stumbled across it. When logged in, navigate to the Dashboard page, then select the Design tab (or link), then click the Edit HTML link along the top. This brings up a screen that allows editing of your blog template, which contains the HTML, CSS, and Javascript that is the basis for every posting. On this template page, it suggests you download your existing template before messing with it, which sounds like good advice. Under the Edit Template heading is the text of the template which you can alter.

Okay. Now to the nuts and bolts of what I did to eliminate the image border. In my template, there was a CSS directive like this:

.post-body img,  .post-body .tr-caption-container { 
   padding: 8px;
}

The 8 pixels of padding is the border I saw, because it seems to inherit a white background color from elsewhere. My images are controlled by the ".post-body img" class. So, I deleted that class specification from the above and created a new one that had the padding and background specifications I wanted:

.post-body .tr-caption-container {
  padding: 8px;
}

.post-body img {
  padding: 8px;
  background: $(post.background.color);
}

This keeps the padding (which I like since it provides some separation between the image and the text) and makes the background color for the image's box the same as the post's color. The $(post.background.color) value is, I think, a variable handled by Blogger's XSL processing that is replaced in the final output with the actual color (or "transparent" in my case).

Once I saved these CSS changes to my template ... voila! The image borders in all my posts (new and old) vanished. In reality, all I really did was change the background color of the padding for just the images.

Thursday, August 11, 2011

Finding IWin32Window in WPF

Copyright © 2011, Steven E. Houchin

I'm developing a WPF desktop application (C# and .NET 3.5) that needs to pop up a dialog window allowing the user to browse for a folder.  .NET provides a convenient (and bland) dialog that does this: System.Windows.Forms.FolderBrowserDialog. To pop up this dialog as modal from my app, I must call its ShowDialog method. Since I want it to be a child of my main window, I need to pass it the parent window, which should be straightforward given the "owner" parameter to the method in question:

DialogResult ShowDialog(System.Windows.Forms.IWin32Window owner);

The problem is, the would-be parent window of that dialog is of type System.Window, not IWin32Window, so "this.Owner" won't match the datatype of ShowDialog's "owner" parameter.  So, given that I have a WPF System.Window-derived parent class, where do I obtain an IWin32Window object?

Well, it turns out I have to write a tiny bit of code for it. Specifically, I must implement the IWin32Window interface on the parent window's class:

public partial class Main : Window,
    System.Windows.Forms.IWin32Window
{
...
   #region IWin32Window implementation
   IntPtr System.Windows.Forms.IWin32Window.Handle
   {
      get
      {
         return ((HwndSource)
             PresentationSource.FromVisual(this)).Handle;
      }
   }
   #endregion
...
}

With the IWin32Window.Handle property now implemented in the parent class, I can simply call ShowDialog(this). Note that you must also include a "using System.Windows.Interop" for this to work.