Recent Posts

Day 4

Tuesday 28 April

Over the years, I have maintained a variety of blogs and migrated my content between most popular blogging platforms (WordPress, Blogger, Drupal, Ghost, Joomla, Habari, Typepad, Tumblr, Posterous, Jekyll, Django, Octopress, Nikola, Hugo, Pelican).

For this #100DaysToOffload exercise, I am using write.as. I currently have a neglected but perfectly functional blog which uses a static site generator (Hugo) and publishes the content on Amazon S3.

However, it's five months since I posted on that blog and I can guarantee that if I were to use that platform, the workflow would be:

  1. What is the precise filename syntax of a new Hugo blog post ?
  2. What is the precise syntax of the YAML front-matter ?
  3. How do I publish pages to S3 ?
  4. Oh wait, hang on. I remember now. I wrote a handy shell script for that. Where is it ?

Now, if I was more intelligent, I would not live my life endlessly re-circulating in Groundhog Day, forever condemned to relive my past mistakes. But I'm not so I am.

Yes, I know that I could have a shell alias and an Emacs template that did the necessary and deposited me directly in the editor ready to write. Patches welcome.

Using write.as has no much barriers. You just write. I remarked on Mastodon about the minimalist interface but this was not a criticism, far from it. I truly believe the stripped down minimalist UI is ruddy marvellous.

write.as minimal

Furthermore, write.as fits perfectly with Kev Quirk's urging to 'Just. Write' when he conjured up the idea of 100 Days To Offload.

You don't even need to register on write.as. You can simply post anonymously.

To get such a minimalist, clutter free, calming environment, you would typically need a 'Distraction Free' plugin on most other platforms. That's after you'd wasted an hour evaluating all the 'Distraction Free' plugins.

And another thing, the people behind write.as are great. For example, I had a minor issue with my post yesterday. As it contained two YouTube links, it was flagged as potentially spam and/or mindless click-bait (fair enough) but I sent a quick email to support and the issue was promptly resolved.

Day 3

Monday 27 April

I don't normally write much about my job. I guess that's because I am wary of revealing company confidential information but I work for Oracle Corporation and have done so since 2006. I am a Technical Consultant ('Jack of all Trades, Master of None').

I find 'Dear Diary' blog posts quite tedious but anyway, during these strange times, it's something to write about.

I have been a remote worker since I returned to work following a 'minor health issue' in 2011 so this remote working thing isn't novel, strange, challenging or depressing for me. I don't need endless quizzes, fancy dress meetings or 'Best Zoom background' competitions to motivate me or raise my spirits.

09:00 - login and process email.

It's a cliche but you do need to be quite disciplined when you're a remote worker. I always endeavour to get to my height adjustable desk by 09:00, err, let's say 09:30, well at least by 10:00 (in case anyone notices).

The temptation to lounge around in my pyjamas watching mindless daytime TV or the tennis from Wimbledon has never been an issue for me. I feel very lucky to be able to work from home. I have done my share of sitting in airport lounges, staying in expensive hotels, eating in lovely restaurants (on my own) during years of foreign travel to help customers in glamorous locations like Prague, Bergen, Madrid and West Bromwich.

It's down to trust. Your employer is trusting you to get the job done. Guess what - if you don't, someone, somewhere will notice.

09:30 - demo to colleagues of a embryonic APEX application that, essentially, provides real-time access to an Excel spreadsheet on an internal Web site. Sounds trivial but this enables multi-user access and a single source of truth without managers circulating the file via email which is beneficial.

11:30 - complete a design document for an external client describing how we intend to purge data from FY14 due to legal requirements. Again, straightforward but slightly complicated by the fact, the client needs to review and approve the data to be removed. The data volumes to be purged involves millions of records to there is no way they can possibly meaningfully 'review' the data but the purged data is preserved in separate tables for audit purposes (and recovery in case we got the threshold date wrong)

13:00 - lunch. A cheese sandwich using home-made bread. We didn't have any yeast so, while it smelled nice coming out of the oven, it was slightly dense and heavy going. A single slice felt like you'd eaten an entire loaf.

14:00 - research an longer-term internal project providing an APEX front-end to a Document repository. Sounds interesting and is a real project with eight people involved using REST API's. Most of my APEX work to date has been just me on my own so it will be useful to work with a more experienced colleague and learn something.

15:00 - cherry picking presentations from the recent APEX@Home marathon.

The Covid-19 Therapeutic Learning System (TLS) was particularly interesting to me as it was a real-life application developed very quickly. Imagine demonstrating an initial prototype to Larry Ellison over Zoom !

16:00 - researching pastel coloured histograms, doughnut rings and pie charts in APEX.

17:00 - wife's return from work imminent (she is a nurse in a GP surgery) so put some salmon fillets in the oven to accompany the roasted vegetable couscous with feta cheese she made on Sunday.

18:00 - moment of weakness and I find myself watching 'About A Girl' from Nirvana's first ever live gig at the Pyramid Club in New York from 1989.

Day 2

Sunday 26 April

Wife cut my hair. Probably not as good as the lady who visits us at home but my sideburns no longer resemble those of a 1970's George Best. Fringe is sub-optimal but who cares. Not me.

Another walk in Richmond Park. Entered at Kingston Gate, walked up to Isabella Plantation car park and back again.

Don't know how many steps or distance but it takes us about an hour.

Wife painted (most of) the lounge. The fact that the circle behind the wall clock was a darker blue than the rest of the room inexplicably bothered her.

It didn't bother me one jot so I made myself scarce by washing her car and vacuuming the interior. Somehow she had contrived to park somewhere under a tree and the vehicle looked like it had been on safari through the Serengeti national park (i.e. coated in bird muck). Some of it needed scraping off with my fingers. Which was nice.

4pm saw 'Street Bingo'. A neighbour rigged up a small amplifier and we all crossed numbers off a grid. Someone got the first line, someone else got the entire grid ('House'). This was followed by a quiz of 'Five things'.

Five Harry Potter books, five Beatles songs, five characters from 'Friends' etc. The teenage kids enjoyed it. We didn't win at bingo and didn't win a single round of the quiz but we enjoyed a glass of wine in the sun and chatting with our immediate neighbours.

We are now best friends forever after they had kindly bought us six Magnum ice-creams as a trade for the use of our Karcher high-pressure water jetwash to clean their patio.

Day 1

Saturday 25 April

Went for a walk in Richmond Park. Still swerving people, mainly on the roads approaching the park and at the entrance gates.

Great to see families out on bikes, dog walkers, people jogging and folk enjoying the open spaces with no cars and no cyclists on the roads.

Thankfully, didn't see any cyclists flouting the massive 'NO CYCLING' signs on every gate as that was getting irritating and rather stressful.

Bought a baguette for lunch from a bakery/coffee shop fresh from the oven. Strictly speaking, a breach of the advice but he's a small, local business struggling, there was no queue and the bread was warm and fresh from the oven.

Hoovered the lawn and mowed the house.

The wife made some minestrone soup and a lamb tagine. This enforced lockdown is turning her into a domestic goddess.

Coronavirus playlist

  • Safe European Home - The Clash
  • My Corona - The Knack
  • Germ Free Adolescence - X-Ray Spex
  • Don't Stand So Close To Me - The Police
  • Soul In Isolation - The Chameleons
  • Ghost Town - The Specials
  • Clampdown - The Clash
  • You're A Germ - Wolf Alice
  • Eat Yourself Fitter - The Fall
  • All By Myself - Eric Carmen
  • Waiting For The Man (with a vaccine) - Velvet Underground
  • Paranoid - Black Sabbath
  • Panic - The Smiths
  • I Predict A Riot - Kaiser Chiefs
  • Anarchy In The UK - Sex Pistols
  • It's The End of The World (as we know it) - R.E.M.

Watch Your User

Connor McDonald posts an excellent series of articles about tuning a database application.

This analysis from a end user perspective reminded me of my own experiences when I was a technical consultant helping customers running a large CRM application, typically in call centres scattered across Europe.

I was often summoned onsite and told to solve the problem that 'The application is slow'. Usually, different people were eager to give me their view on the issue:-

  • Oracle DBA's often would be pouring over AWR reports or a monitoring tool and examining wait events in minute detail. 'We can see multiple ITL waits over 700 ms. This means we need to increase the FREELISTS for the ORDERS table but the business won't let us have an outage'.
  • The application developers would also proffer their own diagnosis - 'Oh yes, we already know what causes that. It a custom workflow written by the previous integrator. It needs refactoring but it will take 3 months'.
  • The CEO brusquely told me - 'This CRM application isn't fit for purpose. If this isn't resolved by Thursday, we're going to evaluate SAP and Safra will be hearing about this'.

Now, this is all detailed, technical analysis and background providing useful information to be considered but I would often ask to see the problem at first hand by talking to an individual who was using this application all day, every day to see the perspective from his point of view.

This simple request was often met with puzzlement and resistance by the technical team - 'Why do you want to watch a user ? We've already told you what the problem is. This will just waste time'.

Sometimes, this resistance was born out of a concern that the user feedback would unearth different, unrelated functional issues and distract me from the performance problems under investigation. Alternatively, a floor supervisor would air the valid concern that my conversation with an agent would distract him from dealing with the customer call. This was easily overcome by letting the agent handle the call with me simply watching and taking notes. Then, after the call was finished, we'd have our chat.

On one occasion, this approach of listening to the users proved particularly beneficial. The client was a utility company but could have easily been a bank or a telco. The business scenario in the busy call centre was typical. he, Essentially, the customer calls in with a query or complaint which is resolved by the agent.

Some call centres use CTI technology where the application looks up the customer from the inbound telephone number and then presents the customer details to the agent on the screen so he can start the dialogue, typically security checks.

However, this call center didn't use CTI so the agent had to manually search for the customer before the call could commence.

I watched the agent process an entire customer enquiry from start to finish and took notes.

The call started and after the initial exchange, the agent asked for customer's surname and started a search. In this example, the customer was Mr. Johnson. I watched with interest as the agent typed in 'J' into the customer tab and his 'Search'. This operation took a long time. There are 66 million people in the UK and 38 million of them appear in this client's database. Searching a table for all customers with a surname starting with 'J' is expensive performance wise.

The agent didn't seems phased or perturbed or even irritated as the hour glass popped up. He merely continued to clear security with the customer. By the time, this exchange was complete, the search had finally returned.

My eyes widened as the agent then proceeded to sort all these thousands of customers by surname and scrolled down page by page searching for 'Johnson'. Again, sorting a large data set like this is sub-optimal performance wise. This is an online application where users are expecting each button click to return within 3 seconds - not 3 minutes. The solution isn't for the DBA to increase the PGA to allow larger temporary segments to accommodate the massive sort operation. The solution is not to issue the request to sort thousands of records in the first place.

It would have been marvellous if the agent had uttered the immortal words 'Sorry, Mr. Johnson but the system is really slow today'. Unfortunately, he didn't but you can certainly envisage similar scenarios where this excuse is proffered.

When the agent finally identified 'Mr. David Johnson' of '23 New Street, Canterbury, CT2 6AD', the rest of the customer call went pretty quickly. It was either taking a payment, changing a tariff, lodging a complaint, a billing enquiry or a change of personal details and common to most agents working on that floor.

After the call ended, I asked the agent why he used that sequence of searches and scrolling to identify that specific customer. The answer, inevitably, was 'We always do it that way and when I joined, that's what Barry showed me...'

Then we revisited the call using a different technique. This time, I recommended he searched for the complete surname (he has that available as soon as the customer starts talking). When he searched for 'Johnson', the query ran much quicker but there are still probably thousands of people called 'Johnson' in the UK.

Instead of sorting and endlessly scrolling to locate the customer in question, I suggested he simply entered the postcode into the 'Address' section. The postcode is now known after the customer completed the security questions. He could have used customer number but that's a long 12 digit number with scope for error when entering it.

[ Ironically, one of his reasons for typing in 'J' instead of 'Johnson' was that 'Hey - I'm pretty lazy and that's a lot of typing' which resonated with me as that's normally my attitude. ]

The agent just needed to type the first element of the postcode ('CT2') to refine the search further and now we have the customer details on the screen in a fraction of the time it used to take him.

I thanked him for his time and told him it had been a very interesting exercise for me to see the application actually in use. He reciprocated and thanked me. As he went to put his headset back on, he smiled and said:-

'You're not going to tell my Supervisor about what we've just done, are you ?'

'Well, yes I am. Trying to solve these performance issues is why I've been asked to come in. Why do you say that ?'

'If Barry gets to hear about this, our call targets will probably be doubled !'.

He smiled and nodded at the electronic rolling ticker display detailing how many calls have been handled, how many are waiting, average call duration etc.

why I dislike the popular TV quiz show - Tipping Point

We all love pub quizzes and like TV quiz shows. I think it's partly because we are curious to see whether we can answer the questions and sometimes, to occasionally, laugh at some of the bizarre answers offered by contestants under time pressure.

One of my favourites recently was a lady who was asked:-

'Hydrocarbons are made up of carbon and which other element ?'

'Carbon dioxide'

I loved this answer because she replied, in part, with 'Carbon' which would have meant that hydrocarbons comprised of carbon, and well, more carbon. Then she added two atoms of oxygen for good measure.

Tipping Point is a very simple game; it's essentially the Penny Falls we all loved as children when we visited the amusement arcades at the seaside.

However, to tart it up a bit for TV, Tipping Point has introduced a load of silly phrases and words to make the game seem more exciting:-

  • 'broad push' - when multiple counters fall and get pushed on the next level. These, in turn, get moved forward en masse to push more counters forward than a single counter could
  • 'ghost drop' - when a counter takes a long time to fall, sometimes by lodging on a peg, so it takes longer to fall to the bottom.
  • 'rider' - when a counter doesn't lay flat but lies over another counter, reducing its effectiveness.

This is probably the most common and irritating. We get contestants and the host, Ben Shephard, constantly urging 'Don't ride, don't ride, DON'T YOU DARE RIDE !' or 'OH NO ! DAVID ! I CAN'T BELIEVE IT - IT'S A RIDER'

  • 'flat' - when a counter falls and just lies, err, flat so it's optimally positioned to be pushed onto other counters in an effort to move them too. 'JUST SETTLE FLAT. GO FLAT !'
  • 'light up drop zone 3 please' - the contestant has a choice of four separate columns in which to place the counter. These are known as 'drop-zones' but it's incredibly irritating to constantly hear 'drop zone 3 please Ben' followed by 'drop zone 3 - light her up please'.
  • 'ambient drop' - a rogue counter that falls, and may potentially dislodge more counters, but sadly when no contestant is active. Any fallen counters are declared null and void. Ben loves these rare events and almost screams orgasmically as he reiterates the rules to the disappointed contestant.
  • 'rapid drop' - a counter that falls through the drop zone without hitting any pegs that disrupt or change its direction resulting in a fast, vertical drop.
  • 'boomerang drop' - a counter that is dropped from one drop zone but miraculously is diverted (obeying the laws of physics) and ends its journey in an adjacent drop zone.
  • 'lateral movement' - another common and incredibly irritating phrase. Used when the counter is simply going to do nothing of note other then fill an empty void. Ben immediately tries to dispel everyone's disappointment and boredom by fuelling a forlorn hope for some sideways motion and shrieking 'Janet, don't worry. We might get some lateral here', 'If we could just get some lateral, maybe the silver one will drop' or 'We could use some lateral here'.

Another element I find slightly irritating is the fake, forced bonhomie and camaraderie on the show. You are a contestant, competing for money against three other contestants, you don't know, on a TV game show. Please don't pretend you're all best friends and like each other by congratulating or otherwise commenting or providing lengthy, detailed Tipping Point analysis during other players' turns.

'Oh - marvellous drop, Peter. That's set you up very nicely indeed.'

'Oh - she's not being very kind to us today' (attempting to humanise the machine)

'Oh yes - well done Yvonne. You've capitalised on all my hard work there and won £450 but I don't care. Honest.'

'Oh - hard luck Brian. I can't believe that black one on the edge didn't fall.'

The best counter-example was a wonderful young man with a wispy, straggly beard (probably a student) who simply answered all his questions, frowned and silently cursed when he got a question wrong and barely reacted or smiled after a successful answer. He also grimaced, sighed inwardly and silently cursed when other contestants did well. He certainly didn't comment, praise, empathise with or interact with the other players. On the contrary, you could almost see him wince as other players luckily dislodged multiple counters to increase their total.

So that's why I hate 'Tipping Point'. Plus I have applied 79 times to go on the show and not been accepted.

the curious case of the filling station incident

7:54am on a quiet Monday morning. Quiet because it's New Years Eve. I have just put £15 into a hire car prior to returning the vehicle.

There's just one gentleman is in front of me paying. He has a fuel card so he's asked for his registration. He can't remember this so looks out to the forecourt to check. Maybe this is a hire car too although that seems unlikely as it's an ancient, brown, battered Volvo estate. No problem. Then he's asked for his mileage which he doesn't know. This is optional so no problem.

He leaves and I advance to pay my £15.02.

'Morning. I'm on Pump 8.'

Cashier hits a button and asks me 'Sorry, what pump did you say ?'

'Pump 8. £15.02'.

The cashier then spontaneously closes the till, grabs a high visibility jacket, mutters 'Sorry, Sir' and runs outside to the forecourt where the gentleman who just paid for petrol is slowly getting into the passenger seat of the Volvo.

I stand and watch the shutters slowly coming down as another member of staff refills this hot tray with pasties. I sigh inwardly as I realise what has happened. Still, no problem. I'm not in a hurry and those pasties do smell lovely.

The Volvo passenger slowly returns to the till.

The panting cashier removes his high-vis jacket and says:-

'Sir, you can either pay £5 or cancel the original transaction and start again'.

The gentleman looks puzzled and remarks in a manner eerily reminiscent of Roy Hodgson when he was hauled before the world's press and sporting media after England's defeat to Iceland.

'Sorry - dunno. I don't really know why I'm even here'.

I helpfully offer:-

'I think you've paid for my petrol instead of yours'.

'Oh - well I ain't got any cash so we'd gonna have to cancel and try again'.

The long, drawn out transaction is re-keyed. The man studiously avoids eye contact.

Finally, he has successfully managed to pay for petrol and a copy of the Sun newspaper.

As he finally declines his VAT receipt, he catches my eye as he turns to go.

'No problem, mate. Don't mention it'.

'Mention what ?'

'Well, you've delayed me for 5 minutes just because you paid for the wrong petrol pump'.

'Not my fault, mate, so nothing to say sorry for.'

So now, in this festive season filled with the spirit of goodwill to all men, this wasn't the best thing to say to me at 08:04 on a Monday morning.

All it needed was a quick, polite word on the way out.

'Sorry, mate. Bit early in the morning for me. Not had my morning coffee yet.'

Alternatively...

'Sorry, mate but I forgot to check the pump number. Happy New Year !'

Or even...

'Sorry mate, Dave normally pays but he's busy phoning the depot'.

But no, he couldn't just bring himself to mutter the word 'Sorry'.

Instead he points at the cashier and says:-

'Anyway, it was all his fucking fault'.

'Come on. You fill a car up with petrol. You're supposed to know the pump number or the amount.'

'I'm just the passenger. Dave asked me to pay.'

'Yeah - but look. There's your car and there's a massive NUMBER THREE above your petrol pump. It's not his job to monitor what pump you've used'.

'So what am I supposed to do ? Ask Dave how much I've put in ? Oh yeah - that'll work. Let's try that, shall we ?'

Then the man walks to the automatic doors and bellows to Dave. Amusingly, the automatic doors kept opening and closing on him which angered him even more.

'HOW MUCH FUCKING PETROL HAVE YOU PUT IN DAVE ? DAVE ! DAVE ! HOW MUCH DO I HAVE TO PAY ? DAVE - HOW MUCH FUCKING PETROL ?!'

And with that, he left and got into the passenger seat and Dave drove off.

The cashier then shrugged his shoulders and said 'Sorry' to me as I advanced to pay for my own petrol at pump 8 which totalled £15.02.

I then apologised to a rather perplexed and anxious looking lady for the delay as she purchased her last unleaded fuel of 2018 as the shutters were slowly raised again.

fixing Dovecot stats writer permissions

I tend to switch Linux distributions quite often. Consequently, I tend to have this process down to a fine art and it doesn't take me that long. The most time consuming element is ensuring the necessary backups are in place.

However, you normally find some package or configuration option you forgot about and my recent switch from Arch Linux to Fedora 29 and back again unearthed a strange problem with the Dovecot IMAP server I hadn't encountered before.

When I accessed my email, my automatic message filtering (using sieve) wasn't working so all messages ended up in INBOX. Worse, on every transfer, the messages were duplicated.

The logging revealed a strange error related to file permissions

$ journalctl | grep dovecot
Nov 29 08:45:32 <host> CROND[3356]: (andy) CMDOUT (msg 53/60 (12176 bytes),
delivery error (command dovecot-lda 3415 wrote to stderr: lda(andy,)
Error: net_connect_unix(/var/run/dovecot/stats-writer) failed:
Permission denied))

The permissions on this socket file were as follows:

$ ls -l /var/run/dovecot/stats-writer
srw-rw---- 1 root dovecot 0 Nov 29 08:52 /var/run/dovecot/stats-writer

Google revealed a couple of fixes. One was to simply change the permissions on the socket file to mode 777 which works for the duration of that session but the problem simply reappears after the next reboot.

Another, more promising avenue was to add a new section to '/etc/dovecot.conf'.

service stats {
   ...
}

I tried a couple of combinations which didn't work but then I went back to basics. I am processing my email as 'andy' but the dovecot processes are running as 'root' and' 'dovecot' (although they could be SETUID executables).

root      8276     1  0 11:45 ?        00:00:00 /usr/bin/dovecot -F
dovecot   8278  8276  0 11:45 ?        00:00:00 dovecot/anvil
root      8279  8276  0 11:45 ?        00:00:00 dovecot/log
root      8280  8276  0 11:45 ?        00:00:00 dovecot/config

However, I wondered if Local Delivery Agent (LDA) was somehow running as 'andy' (the error log implied this) which explained the permissions issue as the Linux user 'andy' isn't able to read that socket file.

Sure enough, the fix, inevitably, was a simple one-liner to add user 'andy' to the existing 'dovecot' group.

$ sudo usermod -a -G dovecot andy

in praise of Silver Searcher

Occasionally, I have to search lots of files for a pattern. It was only recently I discovered the wonderful silver searcher utility which saves me a lot of time.

To install 'ag' on Fedora, use the following (which isn't entirely obvious or intuitive if you're used to typing 'ag').

$ sudo dnf install the_silver_searcher

I believe there is an Emacs interface which would save me even more time.

$ time ag 'sql statement execute time' *.log
real    0m0.125s
user    0m0.128s
sys     0m0.257s

$ time find ~ -type f -print0 | xargs -0 grep -i 'sql statement execute time'
real    0m23.725s
user    0m7.965s
sys     0m1.618s