File Converting & Races (May 25)

Our new accounting software reads existing Goldenseal files. It’s a one-time conversion that moves everything into a new file. You’ve spent many hours creating the data, and you might as well keep it.

TurtleSoft has a very big company file, with 35 years of accounting and business records. It takes about 10 minutes to convert it. Sometimes the update finishes OK. Sometimes it crashes at random places near the end.

We haven’t see crashes in smaller test files, so it seemed most likely that it’s a memory problem. However the conversion maxes out at 65 megabytes of RAM use. That’s puny. The debugger output didn’t helped to find a cause. It was rather a mystery.

Last week we converted the most recent TurtleSoft file so we could use it to test the new accounting app. It crashed. Dang. Can’t start testing with the latest data.

We decided to split the conversion process into two parts, to reduce the memory footprint. The first step moves all the records into a new file. That part has never crashed. Then the conversion finishes later, when the Pro file first opens. It adjusts references to bank transactions and breakdowns, and tidies up many other details. Almost everything in the file gets tweaked.

While debugging the two-step process, it gave some new error messages. One was a clue that helped us find the crash source. It was a sneaky one.

Our C++ code has a “watcher” class that manages record lifetimes. When the function finishes, it reduces a reference count. If nothing else needs the record and it is unchanged, the watcher deletes it from RAM. That’s how we conserve memory and prevent leaks.

There’s another watcher that takes records out of the database if their size may increase. Otherwise, they will over-write nearby records and corrupt the file. That watcher restores them at the function end. They may end up in a new location within the file.

The code often needs both types of watchers. In one spot during the conversion, we used both and forgot to control which would clean up first. That created a “race condition”.

On a modern multi-core CPU, the two watchers run at the same time in different threads. Almost always, removing the record from RAM takes longer, so the record is back in the database before it disappears. However, if conditions are just right, the RAM watcher wins the race. If we didn’t tell it to wait, it may delete the record prematurely. When the other watcher tries to clean up, it acts on something that doesn’t exist. That’s 100% guaranteed to crash.

The code probably fails that way just once in 100,000 tries, but that’s about how many times our file runs the race.

Our staff fixed the bug. Then we searched the code base, and found a couple other places with the same error. Oops. Those have been causing rare crashes for years. At least they don’t corrupt any data. We assign records to the database on the fly, but don’t actually write them to disk until things are calm, a few seconds later. So the crash just loses a small chunk of data entry.

The long-term solution was to add a new watcher class that does both things in the proper order. Now the crashes are gone, the code is safer, and our file converts fine. We also went back to the original one-step conversion. It’s easier for users.

Intermittent bugs are the hardest to fix! It sure feels good when one bites the dust. If you ever have a batbug infestation, you’ll feel the same way about them. They’re ancestors to bedbugs, but intermittent, and smarter.

Before building a release version, we need to merge the Qt code into our app so it’s easy to install. That is not an easy process. We’ll probably hire an expert to do it. It also will be time to start paying the Qt Company for a license. Both steps are still at least a month or two off.

However, if you’d like to make sure your Goldenseal company file will transfer properly, we can test it for you now. The sooner we find any other bugs, the better. We won’t look at the data, but at least we can make sure everyone’s files will convert without giving errors. If your file has corrupted records, maybe we can add code to fix them. Contact us at support@turtlesoft.com to arrange a file transfer.

Dennis Kolva
Programming Director
TurtleSoft.com

Windows & Source Control (May 18)

So far, our staff has only worked on the Mac version for our new Qt-based accounting software. It’s time to start building it for Windows, too.

The first step was to move the latest code from source control to a Windows machine. Source control is the backup system we use these days. It saves changes, and shows the entire project history in case there’s need to revert.

Our staff has been using two tools from Atlassian: SourceTree is a desktop app that saves on the local drive, and BitBucket is a website that saves in the cloud. We push (update from here to there) a few times a day, and pull (there to here) to update machines with the latest.

The pull to Windows used to work fine, but this time it gave error messages. Online, there were many reports from other users having the same problem. The cause: Atlassian changed the way it handles passwords a few weeks ago. The update was smooth for Mac, but very rocky on Windows.

Atlassian had a long list of possible fixes. Forum users also gave suggestions. We tried them all several times, trying to find the magic combination. After 3 days of frustration, it still did not work.

Atlassian also had a big outage last month for their other cloud services. It took them two weeks to fix it. Uh-oh. We decided to switch to GitHub and GitHub Desktop for source control. Those are working OK. Their workflow and interface are different, but we will get used to it.

All of these source control tools are wrappers for git, a Unix applet that first appeared in 2005. Pure git is cranky and confusing from the command line, but the GUI apps and websites make it friendlier. Not super friendly, but enough to get by.

Before source control we saved zip files, and put dates in the comments to help locate the right files. We still do that, but it’s less vital now.

As for the Windows version, the next step was to install Qt and start building the app. As expected, there were snags. Downloading the latest Qt libraries just gave a bad link error. Fortunately, we already have an earlier version of Qt on an older machine. It won’t build 64-bit, but the 32-bit app was a success. It’s enough to start testing.

The app didn’t run at first: another source control problem. Github automatically switches text line endings from Mac format (LF) to Windows (CR/LF). It screwed up our text resources. Once that was fixed, TurtleSoft Pro ran OK on Windows. After some tweaking, it even looks good.

Getting the Win version purring in less than a week is faster than expected. It could easily have taken longer. From here on out we can test for Mac & Windows in parallel. It’s also good to use two different compilers: Windows Qt caught a few errors that the Mac version missed.

Incidentally, that line feed thing comes from manual typewriters. They have a lever to slide the platen (CR carriage return) and also move down a line (LF line feed). With a careful push on an old manual, you can do just one or the other.

The original Macintosh used CR for line ends. Unix and newer Macs use LF. Windows uses CR plus LF. Line endings are just one of many irksome problems that programmers face, when writing software for more than one operating system.

Dennis Kolva
Programming Director
TurtleSoft.com

Source Code (May 11)

Our staff went on a rampage last week, and deleted many C++ classes from the TurtleSoft source code.

Some were left over from the early days of Goldenseal development. Back in the early 90s, computers were s-l-o-w. It took at least 7 minutes to compile the app after any change. Bigger changes ran over lunch, or overnight. Really big ones took all weekend. It would have been even slower if we didn’t use the fastest possible hardware, at $7K a pop (1992 dollars).

For the first few years, TurtleSoft had two or three programmers. Because builds were so slow, we split many classes into parent/child files, using C++ inheritance. Smaller files were quicker to compile. Each programmer also could make changes on their own assigned files, without affecting the others. We merged files every Friday, before the big weekend rebuild.

TurtleSoft wasn’t the only code base using many generations of small classes. The PowerPlant and NeoAccess frameworks were also that way. Cocoa and Qt still are.

Having many small generations does have some advantages. But it’s more confusing, and it sure makes debugging harder. It’s kinda like having tools in a case in a bag in a toolbox, inside a cabinet in a truck in a garage. You’ll spend more time fetching tools than using them.

The frenzy started last week while adding right-clicks to smart fields. The None option erased the field OK, but the text came back later. Arrrrrgh! Debugging the problem went deep into old Goldenseal code. Four different classes were involved. Too confusing. We merged them into one class, and deleted the others. Then it was easy to fix the problem.

It felt so good that the rampage continued. Popup menus, buttons, checkboxes and text fields all shrank. It was like popping C++ pimples.

Once you start swinging a wrecking bar, everything looks like a wall that should come down. So we went through the list of source files, and deleted more that were obsolete. Another twenty or thirty bit the dust.

Shrinking the code base saves compile time, but that hardly matters these days. Even on a cheap Mac Mini, a full rebuild takes 62 seconds or less. Most changes only need a few seconds. The biggest gain is reduced clutter, so programmers are less frazzled and more productive. It helps to have a tidy workplace.

After all that fun, our staff got back to regular programming. Plenty of little details that still need work.

Testing sometimes turns up obscure bugs that have been around for years. For example, the warning about customers going over their credit limit is too strict when you change an existing sale. We found that by accident while testing something else. Now the code is more complicated, but exactly right.

Dennis Kolva
Programming Director
TurtleSoft.com

Links (May 4)

Our accounting/estimating software stores all sorts of info for your company. There are 18 types of accounts: customers, projects, employees, vendors, subs, bank accounts and a few others. Also 35 business transactions for estimating, accounting and project management: estimates, purchases, sales and many more. Most of them link to other records. For example, a Material Purchase has a supplier, a job account, a payment transaction, and maybe some cost items. Also, payment terms and a few other details.

You may want to take a peek at those linked items. Our software gets you there via commands in the View menu, or buttons in the record layout. Smart fields and table rows also have links. All of them open a record window that shows whatever you clicked on.

Accounts also have buttons to create new linked records: purchases from a vendor, sales or estimates for a customer, etc. All that linkety-linking makes your data more useful.

This past week, our staff worked on the links interface. We put it off until near the end because it’s important, and a dilemma.

Goldenseal uses a different window for each type of record. To show a link, it simply opens a new window, or brings an existing one to the front. That part is easy, but the multi-window setup has some basic flaws. Windows accumulate all over the screen. It’s easy to leave half-finished records somewhere in the clutter. Eventually the mess will drive you nuts, until you tidy up and close them.

The multi-window problem is even worse for Windows OS. That has a big Goldenseal window, with record windows inside it. It’s all because MS Windows puts a menu bar on each app window rather than at screen top. The window-in-window interface is the least bad option.

TurtleSoft Pro has a different design: just one window for everything. It has a tool bar, an outline view and tabs. The new look has much easier navigation. It solves the clutter problem. In general it’s pretty nifty. One-window apps are the trend these days, with buttons instead of menu commands. We are going with the flow.

The one-window setup does have a design problem: how do we show links?

We can’t put them in a tab. That was our first attempt. If the new tab jumps to the front, it hides the one you just clicked. If not, you have to click the correct tab to see it. One is annoying, the other is awkward and useless.

The new accounting app already has the option to show some records in separate windows. It’s there for die-hard Goldenseal fans who hate the tabbed window, or for anyone who wants to see two things at the same time. We tried that to show links, and it seemed decent.

What if the link is already in a tab? The solution was to move it out of the tab bar and into a new window.

What if you click a link from a separate window? For now it makes another separate window. That may bring back the clutter problem. Maybe we should add it to the tab panel, instead. It will take some real-world testing to find the best approach.

Another option is to use a temporary movable modal dialog: show one record until you click OK or Cancel. We already do that for lists. It may be the best solution for accounts and transactions, also. Code is already there for it. It’s another option to test out during daily use.

For links out of smart/clairvoyant fields, Goldenseal adds commands at the bottom of the popup menus. TurtleSoft Pro has a right-click menu instead. It’s easier to program, and easier to use.

Right-clicks are one more useful tool. I’m sure we will add more of them during testing. They are yet another way to get there from here.

Dennis Kolva
Programming Director
TurtleSoft.com