iPhone SDK / GDB Debugging cheat-sheet

19 08 2009

I’m working on iPhone apps again, and I’ve been learning some things about the power of GDB, the debugger that XCode ships with. I thought I’d better write it down somewhere before I forget it all. “It’s starting to look like you use this blog as a great big notepad in the sky…” I hear you say. What a perceptive little sausage you are…

Anyway, when your iPhone app coughs up an exception (as mine seem to with startling regularity), fear ye not. Simply drop to a GDB console window and type

“bt” (bt = short for backtrace)

A list of stack frames will be displayed – this is basically the call stack of your app. The most recent (deepest) frame is at the top. Look through the list until you find a frame referring to some code you wrote. If you’re lucky enough to find one, type

“f <frame number>” (f = short for frame)

This will show you the line of code the error occurred on. Pretty freakin’ sweet huh? But there’s more. Type

“p <variable name>” (p = short for print)

to see some info about the variable in question. Typing

“po <variable name>” (po = short for print-object)

might well give you the contents of the variable, especially if it happens to be an NSString. You can also try things like

“p (NSInteger) [response statusCode]“

to get the statusCode of an NSHTTPURLResponse.

There’s bound to be plenty more useful stuff in there too – GDB appears to be immensely powerful. I’ll post more when I find it. In the meantime, there’s a great doc here that goes into great detail.





Ignoring devices with udev rules

3 03 2009

I have a Dane Elec 8GB USB stick. It was cheap, it seems to be reliable, and you never know when 8GB of pluggable free space might come in useful… It did come ready built with a minor irritation, however. When you plug the stick in it gets seen as two separate drives – one 1MB drive with some windows-only software on it and another with the full 8GB of space. I have no use for the software on the 1MB drive, so I’d prefer not to see that drive when I plug the stick in.

“Aha, you idiot!” I hear you cry. “Why don’t you just run up fdisk and delete that partition. Easy!” Tried that – It’s not quite that simple. It’s a composite USB device, meaning that it is seen as two separate SCSI devices rather than two separate partitions. Instead I put a text file on the small partition called “__THIS IS THE WRONG PARTITION__” and resolved to just ignore it.

This weekend I was reading about creating udev rules here (Yeah, I know. My life is just one long thrill ride…) and I hit upon an idea. Surely it must be possible to ignore a device with a udev rule? Indeed it is, and it’s pretty straightforward…

I plugged the device into my laptop and checked the output of dmesg to see that the device was picked up as /dev/sdb (The large drive) and /dev/sdc (The small, ignorable one.) The udev system includes a tool which can give an enormous amount of information about a plugged in device, so I ran “udevinfo -a -p /sys/block/sdc”. /sys/block/sdc is the place under the sys directory that contains the information about the block device /dev/sdc. udevinfo first provides information about the device itself, and then walks up through the parent devices, giving information about each one in turn. A trimmed version of the information about my device is shown below.

looking at device ‘/block/sdc’:
KERNEL==”sdc”
SUBSYSTEM==”block”
DRIVER==”"
ATTR{dev}==”8:32″
ATTR{range}==”16″
ATTR{removable}==”1″
ATTR{size}==”2880″
ATTR{stat}==” 3 0 24 4 0 0 0 0 0 4 4″
ATTR{capability}==”13″

looking at parent device ‘/devices/pci0000:00/0000:00:1d.7/usb5/5-5/5-5:1.0/host3/target3:0:0/3:0:0:1′:
KERNELS==”3:0:0:1″
SUBSYSTEMS==”scsi”
DRIVERS==”sd”
ATTRS{device_blocked}==”0″
ATTRS{type}==”0″
ATTRS{scsi_level}==”0″
ATTRS{vendor}==” “
ATTRS{model}==”USB DISK Pro “
ATTRS{rev}==”PMAP”
ATTRS{state}==”running”
ATTRS{timeout}==”30″
ATTRS{iocounterbits}==”32″
ATTRS{iorequest_cnt}==”0xd”
ATTRS{iodone_cnt}==”0xd”
ATTRS{ioerr_cnt}==”0×2″
ATTRS{modalias}==”scsi:t-0×00″
ATTRS{evt_media_change}==”0″
ATTRS{queue_depth}==”1″
ATTRS{queue_type}==”none”
ATTRS{max_sectors}==”240″

You are allowed to use the attributes from the device itself and one parent when writing a udev rule. It’s important to use attributes that aren’t going to change. KERNEL==”sdc” is obviously a bad idea – if I have another block device plugged in before I insert the usb stick next time I’m going to get a different block device name. In the end I grabbed the model name from the parent and the subsystem and size from the device itself and wrote a rule that says:

SUBSYSTEM==”block” ATTR{size}==”2880″ ATTRS{model}==”USB DISK Pro ” OPTIONS==”ignore_device”

and put it into a new file: /etc/udev/rules.d/10-local.rules. The rules files in that directory are processed in name order, so the 10- part puts my rules pretty close to the start of the list. This rule basically says “If you get a block device where its size is 2880 and its model is “USB DISK Pro ” then ignore it. The four spaces in the product name were what was reported by udevinfo, so I copied it exactly.

If you’re running a kernel without inotify support (I think almost all recent kernels will have inotify support built in) you’ll need to either reboot or force udev to reload its rules. My kernel does have inotify support, so I ejected the device, unplugged it, plugged it back in and crossed my fingers. Lo and behold, only the large drive appears. A look at dmesg shows that the smaller drive was still seen, and it still appears as /dev/sdc, but it wasn’t mounted. I was surprised it got assigned a device name at all, but at least I’ll never see it again. Scratch one minor irritation from my life, and I got to learn something into the bargain. I’m calling that a win… :)





SQL Server Management Studio – Adding Columns

11 02 2009

Like many .Net Development teams we use SQL Server 2005 as our database. A colleague of mine was adding a column to a pretty hefty table the other day and was having problems. The operation was timing out in management studio. The reason for this problem is the way that management studio makes the changes you ask for.

As an example, see the table design below. It’s a trivial example, but the same goes for any table.

A simple table

A simple table

The equivalent of what my colleague was doing was to add a new column and move it to be between ColumnA and ColumnB, because logically the piece of information that would be stored in the new field was related to ColumnA. The SQL that Management Studio was generating to perform this task went through the following steps:

1. Create a new table that is a copy of the original with the new column added.
2. Copy the data from the original table to the new table. (In my colleague’s case several million rows!)
3. Drop the original table.
4. Rename the new table to the original name.

This, understandably, was taking quite a while, particularly step 2.

When we added the new column at the end of the table, the SQL that Management Studio created was the equivalent of:

ALTER TABLE Example_T ADD ColumnC varchar(50) NOT NULL;

which executes in less than a second.

The lesson of this is to think very carefully before adding a new column into the middle of an existing table. If the column would be ok at the end, leave it there. If not, and your table is large, expect a wait and a very busy database server! Step 2 above locks the content in the original table too, which is likely to cause problems for your users if you’re working on a live system. SQL Management Studio provides a button on the toolbar which allows you to see the SQL script that will be used to perform your changes (The one that looks like a scroll of paper with a floppy disk beside it.) I strongly suggest taking advantage of that to check your changes are doing what you expect.





Windows Media Encoder 9 SDK OnStateChanged Event

21 11 2008

I’m working on a project that allows users to upload video to a website. We’re intending to use Silverlight Streaming Services to stream the content to users, so the video needs to be in a WMV format. Rather than ask the user to do that for themselves, we’re going to use the Windows Media Encoder SDK to re-encode the video for them.

I wrote a console app in vb.net to try it out. The Start() method of the Encoder object is an asynchronous call, so once you’ve kicked it off you need to wait around for it to complete. This doesn’t seem to be a problem – there’s an OnStateChanged event you can handle that should get called when the encoder’s state changes to “Stopped”. Problem was, the handler was receiving “Starting” and “Started” but then nothing else? Why not? After a few minutes of searching I found this little gem buried in the docs:


// In order for the events to be triggered correctly,

// the windows message queue needs to be processed.

// Note: This is only necessary in a C# console

// application. A C# Windows application processes the

//message queue automatically.

Eureka!

So, after a quick reference to System.Windows.Forms.dll and the addition of line 7  to the code sample below, my wait loop and event handler now look like this:


            objEncoder.PrepareToEncode(True)
            objEncoder.Start()

            Console.WriteLine("Encoding...")

            While Not c_blnDone
                Windows.Forms.Application.DoEvents()
                Threading.Thread.Sleep(1000)
            End While
    End Sub

    Protected Sub HandleEncoderStateChange(ByVal state As WMEncoderLib.WMENC_ENCODER_STATE)
        Console.WriteLine(state.ToString())

        Select Case state
            Case WMENC_ENCODER_STATE.WMENC_ENCODER_STOPPED
                c_blnDone = True
        End Select

    End Sub

…and everything works just fine.





Opera 9.5 Beta 2 for Windows Mobile

20 10 2008

Opera 9.5 beta 2 for Windows Mobile has been released. It’s a beta product, so Opera undoubtedly refuse to accept any liability blah blah blah, but it seems pretty stable to me. Updates since the last beta include the ability to use the hardware keyboard on my HTC Kaiser (Yay!) and landscape mode rendering. It may only be a beta, but it already beats Pocket IE hands down. It features iPhone like full page rendering with zoom. It’s not quite as slick as the iPhone browser, but it’s the best browser for a Windows Mobile device I’ve ever seen.

In any case, it makes browsing on my mobile a far more appealing prospect. It should keep me busy until contract renewal time :-p…





Reading Large XML files in .Net

7 10 2008

A while ago I wrote a post talking about avoiding the use of the XMLDocument class for writing large XML files. XMLDocument objects quickly become very large and can easily overwhelm even a fairly powerful machine when used to output large amounts of data.

Reading large XML files presents many of the same problems. The XMLDocument does not scale well in terms of memory use when large amounts of XML are loaded into it. The solution appears to be to use the XMLTextReader.

This is a better method which works pretty well, but the XMLTextReader doesn’t allow me to use XPath to pull items out of the XML data, and imposes an unfamiliar (to me, at least) pseudo-event driven model for reading items from the XML file.

For certain types of XML file, specifically those where the file is made up of many repeated sections (think large RSS file with many <item> elements), I prefer to use a combination of an XMLTextReader to parse the file as a whole, reading the repeated items into an XMLDocument to process them. This ensures that only a small amount of XML is loaded into an XMLDocument at a time, and still allows me to use XPath within individual elements. It’s not as easy or powerful as loading the entire document into an XMLDocument would be, but it’s far cheaper in terms of memory usage.

To illustrate, see the code sample below.


Dim xtrInput As XmlTextReader
Dim xdItem As XmlDocument

xtrInput = New XmlTextReader("sample.xml")

While xtrInput.Read

    While xtrInput.NodeType = XmlNodeType.Element AndAlso xtrInput.Name.ToLower() = "job"

            xdItem = New XmlDocument
            xdItem.LoadXml(xtrInput.ReadOuterXml())

            'Process xdItem here
    End While

End While

xtrInput.Close()

A sample input file to the above code might look like this:


<?xml version="1.0" encoding="iso-8859-1"?>
<jobs>
    <job>
        <title> Test Job Title 1 </title>
        <description> Test Description 1</description>
        <salary> £10,000 pa </salary>
        <location> Test Location 1 </location>
    </job>
    <job>
        <title> Test Job Title 2 </title>
        <description> Test Description 2</description>
        <salary> £10,000 pa </salary>
        <location> Test Location 2 </location>
    </job>
    <job>
        <title> Test Job Title 3 </title>
        <description> Test Description 3</description>
        <salary> £10,000 pa </salary>
        <location> Test Location 3 </location>
    </job>
</jobs>

The outer while loop reads through the xml file one node at a time until it runs out of data, at which point the loop exits and the file closes.

Within the outer loop is another While loop which checks to see whether the XMLTextReader is positioned on an element start node of with a name I’m interested in – in this case a <job> element. If that is the case, I read the entire element into an XMLDocument called xdItem, by calling ReadOuterXml on the XMLTextReader. As well as giving me the XML for the current node and any children, this call also moves the XMLTextReader’s file pointer onto the next sibling node of the current <job> node, so the next time I loop around the while loop the XMLTextReader is immediately on another <job> node, so I process the next one, and so on. This continues until I run out of <job> nodes.

Once the <job> element and its children are loaded into the XMLDocument I can use all the familiar XMLDocument ways to extract content from any elements and/or attributes in the <job>.

As an aside, if I were deploying the above code to production I’d wrap the creation of the xdItem and any subsequent processing in a Try…Catch. This means that any unexpected errors in an individual <job> item do not stop the rest of the file being processed.

The code I’ve outlined here is capable of reading in and processing XML files of practically any size and doesn’t suffer from the memory problems associated with loading large files into XMLDocuments. If it fits what you’re intending to do, by all means use it. If you come up with any improvements, please post your thoughts in the comments.





Hiding the keyboard in an iPhone app

2 10 2008

I’m aware that I said that my next post would be about reading large XML files in .Net, but this has come up and I wanted to write it down somewhere to make sure I didn’t forget it…!

I’m working on an iPhone application at the moment. I’m learning as I go, so progress is quite slow. Recently I’ve been trying to work out how to dismiss the on-screen keyboard when the user has finished editing the contents of a text box. Due in part to the (Now lifted) Non-Disclosure Agreement that Apple was forcing people to accept if they wanted to develop for the iPhone, there’s not a lot of information out there on iPhone development.

In any case, I recently stumbled across the answer here, which seems to work quite nicely. I’ve run up a quick sample to illustrate it, as much for my own benefit the next time I need to do it as for anything else.

Essentially, you need to do a few things:

  1. The Controller of the View that contains the text field(s) you’re interested in needs to implement the UITextFieldDelegate protocol.
  2. The text fields themselves need to have their delegate set to the View Controller.
  3. You need to implement a function that will be called every time the user hits return in a text field that’s within your View.

To satisfy point 1, your View Controller’s .h file needs to contain something like this:

@interface MyViewController : UIViewController <UITextFieldDelegate> {

For point 2, it’s a case of firing up Interface Builder and, for each of the text fields you’re interested in, dragging the “delegate” connector onto the “File’s Owner”. When you’ve got it right, the connector tab for the text field will look like this:

For point 3, you need to implement the function below with your View Controller’s .m file:


- (BOOL)textFieldShouldReturn: (UITextField *)theTextField {
[theTextField resignFirstResponder];
return YES;
}

…and that should do you.





Writing Large XML files with .Net

29 09 2008

I do a lot of work for a UK based Job Search Engine called AllTheTopBananas.com. They index job data from lots of different providers and make it available to search in one place. Some of this job data comes into AllTheTopBananas via feeds, mainly in XML. Recently I was talking to one of their providers who uses .Net, who was telling me that they couldn’t provide a complete export of their data in an XML format, because doing so causes their server to run out of memory.

I’ve seen this problem before in a previous job, and in that case it stemmed from using an XMLDocument to build the feed. The XMLDocument keeps the entire XML data set in memory until you specifically write it out. For XML files that are just one chunk of xml for each row from a database, as in the case outlined here, there is a better way – the XMLTextWriter. The XMLTextWriter works in a similar way to a StreamWriter, so it writes the data out to your XML file immediately, which in turn keeps your memory usage down.

Using the XMLTextWriter is a little different in terms of technique to using an XMLDocument, so I’ll outline an example of how to use one.


Dim xtwOutput As System.Xml.XmlTextWriter
Dim sdrJobs As System.Data.SqlClient.SqlDataReader

xtwOutput = New System.Xml.XmlTextWriter("sample.xml", Text.Encoding.GetEncoding("iso-8859-1"))

'Configure the XMLTextWriter to format the XML nicely, and write the root element's open tag
With xtwOutput
    .Formatting = System.Xml.Formatting.Indented
    .Indentation = 1
    .IndentChar = ControlChars.Tab

    .WriteStartDocument()
    .WriteStartElement("jobs")
End With

sdrJobs = GetJobsForExport()

While sdrJobs.Read
    'Write the <job> element and its children
    With xtwOutput
        .WriteStartElement("job")

        .WriteElementString("title", sdrJobs("title").ToString())
        .WriteElementString("description", sdrJobs("description").ToString())
        .WriteElementString("location", sdrJobs("location").ToString())
        .WriteElementString("salary", sdrJobs("salary").ToString())

        .WriteEndElement() '</job>
    End With
End While

sdrJobs.Close()

'End the document - this will close any open elements
With xtwOutput
    .WriteEndDocument()
End With

xtwOutput.Close()

In the code above, the first thing I do with the XMLTextWriter (line 4) is create a new one, and initialise the encoding to “iso-8859-1″. Setting the encoding is an important step that shouldn’t be overlooked. Consumers of your xml file expect there to be an xml declaration at the top of the file to tell them the encoding of the file. This must match the actual encoding of the file. It is also important to choose an encoding that is able to represent the characters you intend to put in the file – pound signs can sometimes cause problems, for example (That’s pound as in GBP, not #…). I usually use “iso-8859-1″ as it seems to give me the best results, though “utf-8″ is another encoding that seems to work in most cases.

I then set up the XMLTextWriter to indent my output (lines 7-14). This isn’t strictly necessary, but it makes the file much more human-readable. I also write the xml declaration (.WriteStartDocument()) and the root node of the xml file.

I then call a function that returns a SQLDataReader (line 16). I’ve not included the code that actually instantiates the SQLDataReader as that’s not part of the point I’m trying to illustrate.

Within the While sdrJobs.Read…End While (lines 18-30) I output a single job element, along with its children, to the xml file. See below for an example of the output file.

Finally, once the While loop exits I close the SQLDataReader, call WriteEndDocument on the XMLTextWriter to close any open elements and close the XMLTextWriter itself.

The xml output from the code above looks like this:

<?xml version="1.0" encoding="iso-8859-1"?>
<jobs>
    <job>
        <title> Test Job Title 1 </title>
        <description> Test Description 1</description>
        <salary> £10,000 pa </salary>
        <location> Test Location 1 </location>
    </job>
    <job>
        <title> Test Job Title 2 </title>
        <description> Test Description 2</description>
        <salary> £10,000 pa </salary>
        <location> Test Location 2 </location>
    </job>
    <job>
        <title> Test Job Title 3 </title>
        <description> Test Description 3</description>
        <salary> £10,000 pa </salary>
        <location> Test Location 3 </location>
    </job>
</jobs>

As you can see, the formatting I asked for has been carried out, and we have a nice readable xml file. So how much memory did I use to generate it?

Running the code above on a test database where the SQLDataReader returns 50,000 rows, the process uses less than 15MB of memory at its peak, and outputs a 75MB xml file. By contrast, loading the resulting XML file into an XMLDocument uses over 150MB – over 10 times as much memory.

Hopefully that explains how an XMLTextWriter can be used to output large amounts of xml much more efficiently than an XMLDocument is capable of. If you found this article useful, for my next post I’m intending to show what I think is a neat way of combining the XMLTextReader and XMLDocument to read our large xml file back in and parse it.





Ubiquity

26 09 2008

Ubiquity is an extension for the Firefox web browser and one of the most interesting projects so far to have come out of the Mozilla Labs. It does for Firefox what Quicksilver does for Mac OS X, though in a more limited way at the moment.

Essentially, it provides a framework for building lightweight extensions to Firefox, and seems to be intended to make mixing content from different sites a simple matter. There are plenty of examples available on the web of what it’s capable of (See here for a quick run down of the built in commands), and they’re also asking for user submitted commands.

Perfect though the Ubiquity extension is for commited command line lovers like myself, the question I have to ask is “Would my Mother use it?”, and to be honest I think the answer is “No.” Don’t get me wrong, I love it. I’ve written commands for it, and I use it daily. For developers and people who like to meddle it’s brilliant, but is it going to bring instant mash-ups to web users as a whole? Personally, I can’t see it. For that it needs, (shudder) a point and click interface. Add that (With an option to keep the command line. Please!) and away we go. Imagine – Right click on the page. Click the “Map this address” button and away we go **.

If you’re interested in writing commands for Ubiquity, the tutorial I linked to above is a good place to start. Sadly, the documentation appears to be a bit thin on the ground at present so the best way to learn is to look at commands other people have written. In that spirit, this is my command for listing all the links in a page that match a certain pattern. Feel free to take it and extend it – but please publish your changes. The success of projects like Ubiquity depends on people scratching their own itch and then publishing the results.


CmdUtils.CreateCommand({
  name: "getlinks",
author: { name: "Kevin Pease"},
  description: "Gets links out of a page for the given pattern",

  takes: {"pattern": noun_arb_text},

  preview: function(pblock, directObject) {
    searchText = jQuery.trim(directObject.text);

    if(searchText.length < 1) {
      pblock.innerHTML =
          "Gets links with the supplied pattern from the page";
      return;
    }

    var previewTemplate = "${links}";
    var previewData = {links: this._getLinks(directObject)};
    pblock.innerHTML =
        CmdUtils.renderTemplate(previewTemplate, previewData);

  },

  _getLinks: function(directObject) {

    var doc = Application.activeWindow.activeTab.document;

    var pattern = "a[href*='" + directObject.text + "']";
    var strBuffer = 'Links matching ' + pattern + '

';

    jQuery(doc.body).find(pattern).each(function(event){
        if(strBuffer.indexOf(this.href) == -1)
        {
	  strBuffer = strBuffer + this.href + '
';
        }
    });

    return strBuffer;
  }

});

** UPDATE: I’ve just stumbled across this very feature. Was it always in Ubiquity? I’d never noticed it before…





Hello world!

26 09 2008

Let’s start this as we mean to go on…

10 PRINT "Hello World!"
20 GOTO 10

Job’s a good ‘un… :-)