[FIX] Missing space in transformable attribute codegen. issue 89 (Daniel Tull, Kris Markel, Whitney Young)
[NEW] mogenerator’s standard templates are now bundled into the mogenerator binary itself. This should solve the problem of templates growing out of sync with the intended version of mogenerator (exacerbated by the now-popular homebrew installer). You can still use your own templates with the --template-path and --template-group parameters. issue 79 (Ingvar Nedrebo, rentzsch).
[NEW] Support for per-entity custom base classes, set via mogenerator.customBaseClass key in the entity’s user info. (Trevor Squires)
[CHANGE] mogenerator installer no longer installs separate template files (but it won’t touch those already installed).
[CHANGE] mogenerator’s .pkg installer no longer includes Xmo’d since 1) Xmo’d doesn’t work with Xcode 4 yet and 2) Xcode.app now lives in /Applications, so the installer needs to get smarter to cope.
Last year Victoria and I tried something different: visiting San Francisco during WWDC, but not actually attending WWDC. Here’s a quick rundown of our experience.
Pros:
Ticket Price. Buy yourself another MacBook Air.
Recordings: Since I didn’t spring for a ticket, there’s no guilt about missing a live session. Ever since Apple phased out after-session Q & A, the online videos tend to be better than the live sessions.
Additionally, Apple has come a long way from the days where you’d get a box of DVDs in the mail many many months after the conference. The last couple of years Apple aggressively edited the recordings during WWDC itself and generally made them available 2-3 weeks after the conference.
Sleep Schedule: Wake up late sans guilt that you’re missing an Important Session. Dovetails nicely with late nights typical of WWDC.
Out of SOMA: There’s much less of a need to stay in SOMA since you won’t need to make those early-morning sessions. We stayed in a bed and breakfast in Pacific Heights and enjoyed many new establishments.
Cons:
Lessened Hallway: The best part of WWDC is the hallway. Since you can’t get past the Moscone lobby, such interaction opportunities are lessened. That said, we found great success in just hanging out outside the Moscone. We didn’t do it enough, but we immediately bumped into folks we knew and had several nice chats.
No Badge: A lot of parties require a WWDC badge to get in. Fortunately there are parties with specific invitation lists and undiscriminating bars.
Lab Time: I’m listing this one for completeness since friends tell me they’ve received valuable debugging and feedback in the labs. Unfortunately in all my years of WWDC, I’ve only managed to stump engineers assigned to the Lab, so I don’t use it any more with the exception of…
UI Design Lab: Finally, a serious con. I’ve gotten benefit out of this lab (when I remember to reserve a slot before they’re all booked up).
Stump the Experts: another serious con. This one’s always a blast.
Non-cons:
Apple Design Awards: I prefer to review the list of winners and runners-up instead of attending this event.
Lunchtime presentations: Worth going to when you’re there, but I wasn’t broken up about missing them.
Bash: The Bash is fun and good for mingling but there’s plenty of that already during WWDC.
Bottom line: we consider our WWDC-less WWDC a rousing success and plan to do it again.
You realize pretty fast that, if you do things a certain way, there is a lot of money to be made on events like this. It’s honestly not that hard to run huge profits. When you have this kind of demand, where tickets to the first NodeConf sold out in 10 minutes and tickets to JSConf sold out in one second, it’s hard not to make money. This is hard work and there’s nothing wrong with making money.
But, here’s the rub. I don’t want to go to the conference that is being run to make someone money. I don’t want to be a product. I want to attend, or speak, at a conference to build community. That’s what I get off on. I’ve got money, I make a good living, so I don’t need to run conferences that I wouldn’t like to attend myself.
Once you run a conference, you can’t look at conferences the same way again. For better and for worse.
[NEW] Support for Xcode 4.3 and it’s relocation of momc into its bundle. Only supports /Applications/Xcode.app for now. (Matt McGlincy)
[CHANGE] Now generates size-specific scalar types (int16_t, int32_t, int64_t) instead of size-variable types (short, int, long long). bug 2 (Rob Rix)
[NEW] Can now generate NSFetchedResultsController creation code for to-many relationships (use --template-var frc=true). (Daniel Tull)
[DOC] Link to John Blanco’s Getting Started with Mogenerator.
@cieslak People seem to think that making stuff easy to use is only for the benefit of stupid users. Expertise comes in different flavors.
@bradlarson The same “stupid users” who fix your car, or perform surgery on you, or teach your kid a foreign language. Drives me nuts.
via Russ Roberts:
Two top U.S. hurricane forecasters, famous across Deep South hurricane country, are quitting the practice of making a seasonal forecast in December because it doesn’t work.
William Gray and Phil Klotzbach say a look back shows their past 20 years of forecasts had no predictive value.
I love the intellectual honesty this must have taken. I wish practitioners of software development could look back and evaluate what doesn’t work, but that’s challenging from both a pragmatic and human-nature standpoint.
[FIX] Was incorrectly using -mutableSetValueForKey: for ordered relationships instead of -mutableOrderedSetValueForKey:. bug 75 (Martin Schürrer)
[NEW] Now generates Mike Ash-style constant structures for attributes, relationships and fetched properties. This allows you to write code like [obj valueForKey:PersonMOAttributes.age]. Tip: you’ll need to enable ARC generation (--template-var arc=true) if you’re using ARC. (Daniel Tull)
[NEW] --base-class-force option, for specifying a base class even if the model file’s entities don’t specify one. (Joe Carroll)
[NEW] PONSO: NSSet-based templates, improved inverse relationship logic and plug memory leak. (Tyrone Trevorrow)
[FIX] PONSO: Added import for super entity in machine headers. (Tyrone Trevorrow)
[FIX] Migrate from deprecated -[NSString initWithContentsOfFile:] and fix a MiscMerge warning where an immutable object was assigned to a mutable ivar. (Joshua Smith)
Summary: SSDs live fast, die young, and pretend to be OK even while they’re dying. Don’t use one without awesome backups.
And sometimes, they come back from the dead.
※ ※ ※
On November 30 2010, I received my first SSD: a 240 GB OWC Mercury Extreme Pro.
On Thursday, November 10 2011, the drive “died”.
I claimed on twitter there was no warning: there weren’t any I/O errors logged to Console.app > All Messages (a standard technique to recognize a drive going bad). Looking back on it now, there were hints: Alfred corrupting its SQLite database, EyeTV losing its schedules and a recording, pbs (Pasteboard Server) crashing, mds throwing a hissy-fit (not uncommon) and finally a kernel panic (an uncommon event).
Last week I came back from lunch to discover my machine frozen. It was still pingable, but everything that touched the disk locked up. I held down the power key to force a hard reboot.
My machine bounced back, but with kernel BootCache warnings in the Console log. After a bit of googling, I decided to restart the machine in Safe Mode, which I understood would rebuild the BootCache. Turns out it also runs fsck, putting up a nice little progress bar. It was taking a long time, so I went to the gym. I came back an hour later, and the progress bar was where I left it: around 30%.
Uh-oh.
I booted off my nightly SuperDuper backup and launched Disk Utility.
My internal SSD fell off the bus: wouldn’t even appear on the device list. My SSD was gone.
I powered down my MacBook Pro and prepared to yank the drive for replacement from OWC. I didn’t expect any issues, they’ve happily replaced two traditional failed drives for me in the past. On a hunch, after I yanked the battery, I counted to down 10 and plugged the machine back in.
It successfully booted off the SSD.
So my SSD was “back”. My guess is the drive firmware simply turns off its SATA connection when it gets backed into an unrecoverable corner. Removing power seemed to “unlock” the drive.
This is kind of a worst-case scenario, since I didn’t trust the drive anymore but it seemed to be working and OWC may not want to replace it.
fsck came back with a couple of invalid inodes, and indicated successful repair. Still not trusting it, I tried a traditional way to force drive failure: a reformat with writing zeros. ~45 minutes later, the drive mounts sans any reported trouble.
If this was a traditional drive, I might have started to trust it again. However, I know about an extra trick some SSDs have up their sleeve: block-level de-duplication.
So I wrote a small C program that fills a file or device with random data. Note to Unix pedants: I know I could have done this with shell commands or your $FAVORITE_LANGUAGE, but I wanted to get close to the kernel on this one and reduce variables for ease of reproduction.
Random data defeats deduping, and I ran my program with parameters to fill my SSD. I went to bed.
This morning I discovered my SSD, which happily survived a complete filling with zeros, failed when I tried to fill it with random data. It fell off the bus again, and wouldn’t show up in Disk Utility.
I removed the drive from the MacBook Pro and plugged it into my Mac Pro via a drive toaster and reran the stress test.
It passed. I reran it again. It passed again.
My SSD had resurrected itself.
I have since reinstalled the SSD and am happily using it again. I’ve also rewritten and enhanced my initial C program into a better, faster one I’ve entitled stressdrive. It now passes my SSD with flying colors:
$ sudo ./stressdrive /dev/rdisk0
blockSize: 512
blockCount: 468862128
speedScale: 16x
scaled blockSize: 8192
scaled blockCount: 29303883
writing random data to /dev/rdisk0
writing 100% (block 29303002 of 29303883)
1779f30a231c1d07c578b0e4ee49fde159210d95 : SHA-1 of written data
verifying written data
reading 100% (block 29302306 of 29303883)
1779f30a231c1d07c578b0e4ee49fde159210d95 : SHA-1 of read data
SUCCESS
My current hypothesis is that my SSD wore out a flash block and attempted to mark the block as bad and recruit a fresh block from its overprovisioning reserve. This path has a bug, causing the controller to panic. Maybe the supposedly fresh block also had issues, maybe a few of them did. I’m thinking restarting the SSD by removing power helped it make progress in the recovery until it succeeded.
I did have the SSD mysteriously drop off my internal bus again today right before the stressdrive test, so I’m keeping an eye on it — I may not be out of the woods yet.
By the way, through all of this, my SSD’s SMART status has remained “Verified”. Ugh.
This week two friends of mine with a Sandforce controller also had SSD failures similar to mine, where the drive fell off the bus. At least one had the same experience as me where the drive was able to “resurrect” itself and pass “surface scans” (whatever those are). Anecdotes aren’t data, but there you go.
I should also mention OWC has been a champ, proactively finding my original order with them and emailing me when I originally mentioned my failure on twitter. They’ve offered to replace my drive, but I’m keeping it for now. What can I say, running a fast drive that may die at any moment makes me feel alive.
A few months back Benjamin Stiglitz taught me that it’s finally possible to build practically-hygienic macros with modern plain ol’ C #defines. Here’s his example:
#define MIN_PASTE(A,B) A##B
#define MIN_IMPL(A,B,L) ({ \
__typeof__(A) MIN_PASTE(__a,L) = (A); \
__typeof__(B) MIN_PASTE(__b,L) = (B); \
MIN_PASTE(__a,L) < MIN_PASTE(__b,L) ? MIN_PASTE(__a,L) : MIN_PASTE(__b,L); \
})
#define MIN(A,B) MIN_IMPL(A,B,__COUNTER__)
So this C code:
int a = 11;
int b = 42;
int c = MIN(a, b);
preprocesses into this:
int a = 11;
int b = 42;
int c = ({
__typeof__(a) __a0 = (a);
__typeof__(b) __b0 = (b);
__a0 < __b0 ? __a0 : __b0;
});
Here’s how __COUNTER__ works:
A new predefined macro
__COUNTER__has been added. It expands to sequential integral values starting from 0. In conjunction with the ## operator, this provides a convenient means to generate unique identifiers.
It’s still not gensym-quality, since the generated variable name can shadow other variable names:
int a = 11;
int b = 42;
int __a0 = a * b; // uh oh
int c = MIN(a, b);
assert(__a0 == 462); // passes though
This is contrived, since you probably aren’t going to prefix your variable names with double-underscores. That said, this code does compile and execute correctly, although enabling -Wshadow will reveal all is not well.
Here’s a quick script that will take the selected tasks in OmniFocus 1.9.4 and put a simple space-indented text representation on the clipboard:
tell application "OmniFocus"
tell first document window of front document
set selectedItems to selected trees of content
if ((count of selectedItems) < 1) then
error "Please first select a task"
end if
set output to ""
repeat with itemItr in selectedItems
set output to output & my printTree(itemItr, 0)
end repeat
end tell
end tell
set the clipboard to output
on printTree(node, indent)
set output to ""
repeat indent times
set output to output & " "
end repeat
set output to output & name of node & (ASCII character 13)
tell application "OmniFocus"
repeat with treeItr in trees of node
set treeItr to treeItr as any
set output to output & my printTree(treeItr, indent + 1)
end repeat
end tell
return output
end printTree