Musings
muse: to turn something over in the mind meditatively and often inconclusively
He ain't heavy, he's my payload

Rox now supports a "vendor extension" to the XML-RPC specification. If you enable it then you can specify a request encoding on the client side. On the server side you can register multiple encodings which are looked up by name.

An example of an encoding would be a gzip encoding. After the approriate incantations the client will gzip it's payload before sending it and (optionally) indicate that it will accept gzipped content in the response. If the server has a handler registered for the gzip encoding it will unzip it and the server-side handler will never know the difference. And if the client indicated it's willing to accept gzipped encoded content in the response (by means of the Accept-Encoding HTTP header) then the server will do the honours. If not, the server will send back an unencoded response.

You can plug your own encodings in (Rox has support for a couple of compression encodings) so if you think there's an efficiency gain to be had by translating your XML-RPC tags into Klingon then who am I to stand in your way?

As part of interop testing I started to look at the Apache XML-RPC project's vendor extensions. It turns out they've implemented something similar but I'll need to use version 3 of their library and just the examples were enough to scare me off. Configuring the client to compress requests requires instantiating something called XmlRpcClientConfigImpl and then setting a bunch of properties (which I think are just string names) on this object. This is then passed to a setConfig() method.

It looks like they've done some work to decouple the tranport layer (HTTP) implementation, which is a good idea. It let's you plug in a replacement HTTP implementation when you realise how much the Java URLConnection implementations suck (although their example plugs in the Jakarta Commons HTTP implementation which isn't a whole lot better).

And I see lots and lots of factories. I don't have a problem with factories per se. They have their place. But I tend to lean towards sub-classing and factory methods, rather than factories. And given that the only way to provide a factory in the Apache implementation is to subclass, a factory method strikes me as simpler (since 90% of the time all you want to do is plug in a different implementation of something).

It looks (from a quick inspection) like they might support POJO serialization. It's not entirely clear. But I see as part of their vendor extensions they've added support for a bunch of new types. This is not a bad idea. If you control both ends of the pipe this could make things a lot easier for you. But, as part of this they seem to be heading down the XML namespace path. If you're planning to interoperate in the XML world then this is not a bad idea. It avoids collisions. But, one of the reasons XML-RPC avoided namespaces early on was because it seriously complicated things and it was always intended to be as simple as possible (one of the other reasons is that namespaces hadn't yet been finalized). I think namespaces in this context was the wrong decision.

They have decided to support passing XML-RPC method parameters as an Object array. I'm not going to argue (Rox does this too). This strikes me as far more natural since the 90% case involves a method with a static list of parameters. The overhead of a List is usually unwarranted. As an aside, for most of our internal APIs we ended up passing a single struct as parameter. This gives us "named" parameters and is far more future-proof since adding new fields can be done transparently (if required).

I'll admit I only spent about 5 minutes looking over the new API, and it's not all bad but, frankly, I think they've taken a step backwards.

Posted at 10:57 PM

Hope crawls out of the oddest holes

There's a song floating around the radiosphere at the moment. It's a local crowd, I have no idea who. I have no idea what the song's called either. Eventually I'll pin down a set of sufficiently unique substrings in the lyrics to figure it out.

But that's secondary. There are days where there's very little going on to inspire hope in this country (or indeed the world). For reasons I'll try to explain shortly, this song runs counter to that trend.

The song's a pretty upbeat piece, with a fairly hummable tune (thank your luck stars you don't share a car with me in the mornings). The lyrics are a mixture of a local African language and English. And it sounds like the guys singing it are having an absolute blast. It makes me think of If I had a million dollars by the Bare Naked Ladies. You just know it's all play and no work.

It's just nice to hear someone who's so obviously doing what they love, despite anything Life may have placed in their way.

Posted at 10:35 PM

I'd expect nothing less

I think it's fairly fitting (or at least representative of my life so far) that the session with the guy who will be marrying us (in 11 days no less) ended with me troubleshooting his email.

Somewhere, the person holding the strings is chuckling quietly to themselves.

Posted at 06:44 PM

A favour (or two) to ask ...

arniston_small.jpg Dear thoughtful motorists.

While I appreciate that you've seen me in your mirror, and that you've pulled onto the shoulder to let me past I'd like to suggest you don't. The primary reason for this is that you're now doing something "out of the ordinary" and, frankly, that's how accidents happen. People take a mite longer to process a situation they're not expecting. It's also difficult from my side to determine when you're going to decide that I'm not taking advantage of your generosity and pull back onto the road. If this coincides with me making the decision to overtake, well, it could get interesting.

It doesn't help that all too often this display of generosity takes place in the face of heavy oncoming traffic, on blind corners, or just before the crest of a hill. In short, in the least convenient place possible.

I'd suggest that instead you stick to a constant speed as far as possible and leave me to overtake you in my own good time. I have more than enough acceleration to render you almost a non-issue.

But I appreciate the thought, which brings me to ...

Dear thoughtless motorists.

Actually, this will take me too long to write. There are too many examples of thoughtlessness on the road, even if you focus exclusively on bikes. Today I ran into yet another example: the thoughtless smoker.

Please spare a thought for the bike behind you when you're smoking. Flicking hot ash back towards me is not the best way into my good books. Especially if I'm riding with my visor up because the act of smoking has paralyzed your central nervous system and it's all you can do to keep your car between the pavement and centerline and I'm forced to slow to 20km/h as a result.

Frankly, if you're prepared to coat the inside of your lungs with tar I don't see why you're not prepared to dump a little ash in your ashtray.

Regards
The guys on the bike behind you

Posted at 04:57 PM

On children

Something to chew on.

After a year or so of enjoying our marriage, we discussed having children. People who know us and know how central our children our to our lives (I can’t use the singular form yet) may find it surprising that we could see ourselves being happy with and without children. But I think that was crucial for our personalities. The fact that we could live rich and fulfilled lives without children meant that we weren’t choosing to have children to somehow complete ourselves.

Posted at 03:38 PM

James on Joel on Software

Joel Spolsky, so well known for his opinions on software that his site shows up as the first restult in a search for Joel on Google.

We've been using Bugzilla for our bug-tracking but we stopped and re-evaluated this week and figured that something a little more general might not be a bad idea. After a little looking around we figured we'd give FogBugz a try. Both Joel and FogBugz have a good reputation and they offer a 90 day no-questions-asked money back guarantee.

So we purchased a copy on Wednesday and figured we'd be using it the end of the day. Wrong. It seems Joel's opinions may be nothing more than that. Perhaps we'd have fared better with a Windows version but Debian's an officially supported platform so I'd expect the same level of testing for both. Perhaps both have seen the same level of testing and I'm just giving Joel more credit than he deserves.

Anyway, it took two days to get it installed and part of that involved fixing it ourselves.

I only hope using it is a more pleasant experience.

Posted at 12:26 PM

HTTP meets SSL

How's this for an unexpected "edge case"?

Take one HTTP client that wants to negotiate an HTTPS session (i.e. HTTP over SSL). Add one HTTP server that is serving unencrypted HTTP responses. Connect them together and sit back.

In the worst case, nothing happens, ever. If you were smart and set a socket level timeout on the client before starting then eventually you'll see it expire.

Why?

It's pretty simple actually. In a normal HTTP transaction the client connects, sends a request and reads a response. So in our scenario the server accepts the connection and waits patiently for the client to send a request.

Now consider the SSL protocol handshake. It's server-initiated, so the client makes a connection and waits for a server "hello" message. So in our scenario the client connects and waits for a hello from the server.

So now we're in a position where the client is waiting for the server, and the server is waiting for the client.

This isn't normally a problem because convention has HTTP servers on port 80 (or 8080) and HTTPS servers on port 443 (or 8443). These default ports are derived from the protocol portion of the URL (http and https respectively). It's probably pretty rare to find an HTTP server running on port 443 that's not using SSL (if you're doing this then you're a monkey). So it's probably pretty rare that an SSL client and a non-SSL server get wired up. Which is why you don't often see this.

I stumbled across it while testing Rox's SSL implementation (way back), since this represents one of my testcases. I wanted to ensure that I'd be able to detect mismatched client/server expectations. It turns out the only way to handle this case is with a socket timeout (I certainly can't see another way).

Posted at 05:06 PM

Rox 0.4 released

Changelist:

  - registerProxyingHandler() has been pushed down into XmlRpcServer, since
    it registers an XML-RPC specific handler. This should not affect 
    existing code unless the server instance was been stored in a member
    of type HttpRpcServer.
  - HttpRpcServer and XmlRpcServer now use InetAddress instances instead
    of Strings for host addresses. I think this is more consistent with
    other, similar APIs, especially within the JDK.
  - HttpRpcProcessor now implements Runnable instead of extending Thread.
  - HttpRpcProcessor now sports a stop() method for shutting down a client
    or server.
  - String URIs (or mount points) are now used instead of URI instances.
    URI's normalization was sufficiently lacking so that it doesn't make
    sense to depend so heavily on this class. URI normalization has also
    been moved into Utils.normalizeURIPath() so we can cater explicitly
    for some edge cases.
  - Fixed a bug which resulted in a malformed Content-Type header being
    returned to the client if an exception occurred within a server-side
    handler.
  - When proxying objects on the server side Rox will now raise an 
    exception if more than one method with a given name is declared on 
    the target object (currently there is no support for method 
    overloading and there are no immediate plans to support this). 
    Methods declared on java.lang.Object are not included when
    proxying an Object.
  - Rox was erroneously expecting the HTTP Host header to be present
    in HTTP responses. They're only mandatory in requests. This has been 
    fixed.
  - An XmlRpcFaultException has been introduced and RpcFaultException
    moved and modified to extend RuntimeException. This exception can
    be raised if explicit control over the XML RPC fault returned to
    the client is required from within a method on a proxied server
    side Object and you don't want to (or can't) modify the throws 
    clause on that method.
  - Final fields are now skipped during marshalling and unmarshalling.
  - Client-side timeouts are now supported. Timeouts are set per
    client instance, but can be changed on an existing instance. By
    default there is no timeout. If a request times out the connection
    on which the request is pending is closed.

Posted at 11:57 AM

Find of the week

A favourite Sushi venue has a generator.

If I owned a sk8tboard and wore baggy shorts around my ankles I'd throw in something like "Stylin'!"

Posted at 09:14 AM

Joke of the week

What did South Africa have before candles?

Electricity.

Posted at 03:20 PM

Rolling blackouts

Tentatively back online after a weekend and Monday filled with power outages.

There are all sorts of stories floating around, including ones put forward by Eskom themselves that try to pin the problems on heavy mist and "pollution" after recent fires. The only sensible story I've heard is that one of our local Nuclear power cells underwent a "controlled shutdown" late last week and it will take until tomorrow to bring it back online. Luckily it was "controlled". I don't want a third arm, I'd have to cut holes in all of my shirts.

It always amazes me how people react to power failures. It's like they don't know what to do with themselves. Roads back up because they have no idea how to deal with traffic lights at intersections that no longer work, and I swear a bunch of people respond by getting into their cars and driving off only to realise there's nowhere to go. These people seem to end up circling their neighbourhood in a weird "Shaun of the Dead" like state.

It's as if the entire world turned into a shopping mall replete with the usual mindless herbivores that seem to inhabit them. A whole bunch of people suddenly have no idea where they're going or what they plan to do, but dammit they're doing it first and by God if you cut me off I'm going to lay my head down on my hooter until I expire.

Me, I'm just glad my disks came up in one piece.

Posted at 11:32 PM

Fourteen Defining Characteristics of Fascism

Read through this essay and tell me which country leaps to mind first.

To give credit where credit is due, I got there via this, but I think it's even more effective to read the original essay without having someone else join the dots for you.

Posted at 11:37 AM

Muppetness by design

Yesterday's Muppet award goes to Sun, who have, through various twists and turns, lead us to a point where the ServletException class in the Servlet API sports a custom implementation of causal exceptions.

This means that if something goes wrong deep down within a servlet you get a very helpful "Servlet execution threw an exception", without any indication of what that exception might be.

You have to catch ServletException explicitly and dump it's causal exception using their getRootCause() method.

Better yet, it turns out this is "deliberate" in the sense that versions prior to 2.5 of the Servlet API target J2SE 1.3 as their minimum supported runtime version. Which means they can't rely on 1.4's causal exceptions. A bug was logged but has been closed and marked as "fixed" even though in actual fact it wasn't fixed at all (whoever closed it claimed it couldn't be fixed).

Utter bollocks. Assuming Sun have been good developers (not always a valid assumption) and are calling their own getter (getCause()) from within methods like printStackTrace(), all they need to do is implement getCause() on ServletException and make it call getRootCause(). This would not break compatibility and would mean on 1.4 or higher you'd get the expected behaviour, at least for printStackTrace().

Monkeys, the lot of them.

Posted at 11:10 AM

$#%@#$%$#^$#^

Fucking missing fucking angled fucking bracket fucking cost me four fucking hours of fucking debugging.

And Tomcat said nothing, NOTHING. 404 Not Found my ass. More like 417 Expectation Failed (said expectation being that people who are allowed to work on Tomcat are NOT FUCKING MORONS).

Posted at 02:21 PM

Rox 0.3 released

I just uploaded version 0.3 of Rox. Get it here.

For those still awake, here's the changelist.

  - Fixed a bug which produced malformed XML for XML-RPC faults.
  - Byte, Short and their respective primitive types are now
    marshalled as ints.
  - Character (and char) are marshalled as a single character
    string.
  - The ParameterTypeMapper interface has been replaced by a more
    general UnmarshallerAid which supports pluggable FieldNameCodec
    implementations as well as parameter type mapping.
  - The logic governing Class member introspection has been extracted 
    into a new class (ClassDescriptor). In addition to centralizing
    this logic this new class caches class member information upfront
    which should result in a performance improvement when repeatedly
    marshalling or unmarshalling objects of the same type.
  - A new utility method has been added to HttpRpcServer to
    simplify using a synchronous proxying request handler.
  - Method lookup on the server side when proxying an object is
    more general (and hopefully more useful as a result). Names
    are matched case-insensitively after dropping '-' and '_'.
  - Static fields were being included when marshalling or
    unmarshalling objects. They're now skipped (along with transient
    fields).
  - Encoded field names are cached as they're computed to reduce
    the cost of repeatedly marshalling instances of the same class.
  - In the spirit of being "strict in what you produce and tolerant
    in what you accept" RoX will now raise an exception if an
    integer value exceeds the range defined by the XML-RPC
    specification (32 bits, signed). RoX will accept integer values
    that exceed this range, provided they fit into the target
    member's range.
  - Convenience methods have been added for configuring and
    querying the number of worker threads on an HttpRpcProcessor
    instance.

I see I've had a little traffic from Europe, a hit from India, Indonesia (I think) and somewhere in the states. And someone I don't know downloaded Rox. Cool :-)

Posted at 09:12 PM

Ups and downs

potjie_small.jpg It's been a rather busy weekend, replete with ups and downs. After a late night reorganizing our source control repository (and putting our DBAT back together afterwards) Friday dawned. Fortunately Friday was anything but demanding (unless you consider lunching on Swordfish steak demanding). Friday evening we joined some friends for dinner at what turned out to be a great restaurant in Muizenberg. The evening would have been perfect but for one thing: my car refused to start. Our compatriots had already bailed and were thoughtful enough to switch their phones off and then just to drive the point home both our phones died. We just managed to squeeze in a call to Ben ("Help!") and to a towing service ("Help!").

I hate it when things you take for granted just stop working. It's probably a good object lesson (don't take X for granted) but it really fouls up my mood. And it was all the more annoying for happening on a Friday evening, which means there's nothing I can really do until Monday. I was not a happy camper. But what can you do?

hermanus_feb06_small.jpg Saturday saw us doing a bit of last minute shopping and some preparation for the Potjie Off Otto's been threating to organize for lord knows how long now. Actually, I think the final catalyst was Walters more than anything else. He's always game. We'd organized a different meat for each pot. Otto did a chicken potjie, Walters bravely took on oxtail and I hauled out my favourite lamb recipe. It's been well over a year since my last potjie (I think) and I'd forgotten how pleasant the activity is: there's the feeling of being productive combined with the necessity of waiting and doing nothing (this is the key to a good potjie: do as little as possible). A beer, some sunshine (lots of sunshine, yesterday was a scorcher) and a chance to talk rubbish (or in Otto's case to trash talk his "opponents").

Although we never dragged a verdict out of the judges I think Otto had the right of it: the real winner yesterday was potjie.

Then a little bit more work on Rox before turning in for an early start. 6:30am always comes as a surprise. Regardless of how much you thought you were expecting it.

After the car saga I fully expected my bike not to start: Life and I have this uneasy relationship: she kicks me, I let her. But she started without any problems and Andy and I headed off to meet the Pegasus crowd for a breakfast run to Hermanus. The weather was overcast but at least it was cool. 34 bikes turned up, more than I've ever shared the road with in a group. The resulting ride (which included Sir Lowry's pass) was a bit hairy. Breakfast on the other end was immensely welcome. I always feel hollow the morning after a large meal, and potjie is always a large meal. After breakfast Andy and I set off and the day's ride really began.

arniston_feb06_small.jpg On the other side of Hermanus we stopped in Stanford for fuel before heading off to Napier. The roads out that way are superb. Long sweeping bends, almost no cars and incredible scenery. By this time the weather had turned warm. Before the day was through I'd seen 36 degrees a few times on my thermometer. From Napier we rode to Bredasdorp and on to Arniston where we were treated to a terrific seaside view and some of the worst service in recent memory (at the Arniston Hotel). Back to Bredasdorp and up to Swellendam to get back onto the N2. The ride back was pretty windy and a strong gusty wind like that is pretty much the worst thing possible on a bike. Nothing like the threat of a permanent imprinting of the Mercedes logo in your forehead to keep you tense for a few hundred kms.

When we stopped for a drink in Riviersonderend Andy heard that his mother-in-law may have had a stroke. Fortunately it looks like it may just be over-exertion coupled with high-blood pressure but it's pretty crap to have that kind of uncertainty hanging over you while you're that far from home. And I think his wife was pretty shaken by the news. One more reason to hot-foot it home.

And it really was a scorcher. My word was it hot. Only when we reached Caledon did it cool down and then dramatically. It dropped 10 degrees as we passed through Caledon and it was most welcome. It also heralded the weather to come. Back over Sir Lowry's pass only to hit the longest tailback I've seen in some time. Judging by the emergency vehicles we passed as we slipped through the traffic (a bike has certain advantages) there were at least two serious accidents.

Once through that lot we encountered the usual nutters. Cars that sit on your ass only to pass you and then slow to a crawl when you let them by. Golfs and GLVs (German Luxury Vehicles), as usual. Do owners of those cars have to pass a different test to the rest of us? One that makes sure there's a good chance they're an asshole?

And it didn't make things any better to find ourselves in the middle of a sudden spot of wet weather. Cape Town doing her best to live up to the whole four seasons in one day thing.

So now I'm feeling a little spent. I think I'm going to sit here and do as little as possible. For a little while anyway. I think I have another idea for Rox.

Posted at 06:38 PM

Bah

Bastard cars.

Posted at 01:19 AM

Testing, testing, 1 2 3

This has to be some of the best porn I've stumbled across in a while.

Tell me you don't agree with me? Now ...

  1. How many of you followed that link without thinking?
  2. How many of you thought about it but followed it anyway?
  3. How many of you rotated your monitor or prepped yourself in some way in case someone walked passed while you were busy?
  4. How many of you were disappointed?

Posted at 09:17 AM

Sarge, I can't feel my legs!

Okay, so that's a bit of an exaggeration. Recall that sometime back I had a minor altercation with a car and, much to my dismay, wrote my last bike off.

I came down pretty hard on my left side and since then the skin over my left hip has been numb. I noticed yesterday that the skin on my left foot is numb in the same way. I don't know if it's just something I hadn't noticed until now, or if it's a recent "development".

How do you debug a nervous system?

Posted at 08:31 PM

RoX 0.2 released

Get it here.

A few additions since the previous RoX related post, nothing major. Outstanding issues are mostly related to field name encodings and Roland's SAX based unmarshaller still has some work before it's complete. I also need to look at limiting the number of connections in the connection pool so an async client that just goes nuts with requests doesn't bring the system to its knees.

Apart from that RoX is looking quite good.

Posted at 12:34 PM

Conspiracy theorists unite

Weird moment just now. I think my mouse button got stuck and for a few seconds everything my cursor crossed received mouse click events.

After it sorted itself out the Firefox window with the focus promptly fetched fbi.gov. I kid you not.

I'm sorry Osama baby, but those late night calls have just got to stop until the heat dies down.

Posted at 11:33 AM

RoX 0.2 looms large

After a little burst of work RoX has seen many improvements and unless I find anything significant this evening release 0.2 should be out sometime this week.

I'm battling to keep up with the traffic on the project page (that's a joke, so far I think only Andy has downloaded it).

The most significant milestone is that RoX now passes the (somewhat meagre) public XML-RPC test suite. This would have happened sooner but I only found them this morning. Just as well, the tests did flush out a few weird bugs on the server side proxying front.

For the truly bored here's the changelist so far:

  - The AcceptPolicy interface has changed slightly. In addition
    to the new SocketChannel an (approximate) indication of the number
    of existing connections is passed to the policy implementation.
  - Fixed a race condition during connection establishment which
    resulted in requests occasionally failing to be sent to the
    server.
  - Fixed a bug that meant if the remote entity shuts a connection 
    down cleanly during a read the caller wasn't notified. 
    A specific IOException exception (RemoteSocketClosedException) 
    is passed to the caller to indicate this case.
  - All the boolean test methods on the Log interface now take a Class
    context parameter so implementations can make the most informed
    decision about whether or not a given logging action should be
    allowed.
  - Log4J has been added to the RoX project, along with a Log4J
    adapter implementation of the Log interface. This adapter class
    is built into a separate (optional) extension JAR (rox-log4j.jar).
  - Introspected Fields are cached. Class.getField() is pretty
    expensive in the general case.
  - Support has been added for selecting between compact XML for
    efficiency, or more readable but less efficient XML for
    debugging.
  - The ResponseChannel interface now has a close() method on it
    allowing asynchronous server-side method call handlers 
    to close the channel on which a response would normally be
    sent.
  - When unmarshalling a struct member where the Java Object member 
    is an array type with a component type other than Object RoX
    will marshal an array of instances of the component type. So
    if you have a field (public or accessible via a setter) of
    type Foo[] then it will be populated with instances of Foo
    (assuming the data within the XML-RPC array is amenable).
  - Fixed a bug that would result in a NullPointerException instead
    of a more informative exception if no field or setter could be 
    located for a struct member.
  - Support has been added for marshalling and unmarshalling arrays
    of primitive types (int, long, double, float and boolean).
  - Support has been added for marshalling and unmarshalling 
    multi-dimensional (well, they're really jagged) arrays, of both 
    primitive types and POJOs.
  - XmlRpcMethod and kin have been refactored to split out unmarshalling.
    Marshalling is still the province of this class but unmarshalling is
    now handled by implementations of a new pair of interfaces, one
    for method calls and one for method responses. The (DOM based) 
    unmarshalling logic in XmlRpcMethod has been moved out into 
    concrete implementations of these interfaces. This required a number
    of incompatible interface changes.
  - An interface encapsulating common XML-RPC constants has
    been introduced.
  - An experimental SAX based unmarshaller is included with this
    release. It's by no means finished yet and the interface exposed
    is still under review. Thanks to Roland Patterson-Jones for
    this contribution (and some testing and debugging).
  - Fixed a bug that broke server side proxying when parameter types
    were user-defined structs.
  - Field name encoding/decoding is now pluggable. RoX still defaults
    to assuming hyphenated fields for XML-RPC struct member names
    and camelCase for Java member names.
  - As of this release RoX passes the validation suite published at
    
       http://validator.xmlrpc.com/
       
    The source code for the server can be found in the class
    com.flat502.rox.demo.validation.ValidationSuiteServer. There's
    also a client implementation for testing locally.

Posted at 08:15 PM

WWCND?

Fear the Norris.

Posted at 08:34 PM

The secret life of plants

From a distance plants are usually pretty boring. Especially run of the mill plants that don't burst into colour or grow bright red seed pods every now and then.

Trees, creepers, fynbos (which I find particularly boring from a distance), most plants in fact. Dull as dishwater.

Until you get closer. Next time you have a little time to kill, and assuming you are actually outside, stop and take a closer look at a nearby tree, bush, whatever.

Whenever I do this I'm fascinated. And it's not just the obvious things you start to notice, like just how much life is beavering away in there. It's the sheer complexity in there. It's the dozens upon dozens of unique patterns, shaped by whatever it's growing in, on, under, around or through. I think what mesmerizes me most is that there's this whole other world in there, happily carrying on whether or not I'm aware of it.

I think I'm more aware of it at the moment because of our garden. I've suddenly got a vested interest in whether or not a bunch of plants actually make it, and it's been interesting to see how they've progressed. Some of them are unhappy and voicing their displeasure in the only way they know how (by dying) and others are growing so fast you feel like you should check your cellphone battery is charged before venturing into the garden.

Posted at 09:28 PM