for( auto& post : post_stream ) { …

  • Don’t be so sensoritive, man.

    Continuing with the plug-progress theme, here’s the status this week:

    The core-plugs have actually all spread out. The frustrating part is that I didn’t hit this area with kyllinga killer so I’m confronted with kyllinga growth masking the spread of the runners. I’m just going to let it fill in green and hit this hard once I think the grass can take it.

    This is a closer look at the situation:

    You can see the low, close to the ground blades of the floratam spreading out, but there are also large clumps of kyllinga competing for the same space.

    Some of this kyllinga problem is that I’m watering very frequently to support the growth of viburnum bushes in the same irrigation zone. I can’t pull back on the water. The kyllinga just hops in everywhere it gets a chance. This weed is a real nuisance.

    I’ve also started to get a sense of the peaks and valleys in the moisture sensor data. I’m trying to get a sense of peaks and valleys so I can (manually) calibrate irrigation zone operation to respect a minimum and maximum:

    I wish I had the data from the winter. The damage I have in my lawn, I think, is from Take All Root Rot. Wherever the municipal irrigation failed, the water ran through a channel. When the water didn’t evaporate quickly and pooled, it created problem zones that just failed to allow the grass to recover in the spring.

    I looked today whether some of these areas were completely dead, and they weren’t. It just appears that I need to hit the leaves iron and turn things around so the roots can heal eventually. I’m still trying to learn how to do this, and I’m hoping I can fix the damage myself.

  • The moai learn, the better I get

    If you ever visit a Home Depot in Florida during spring, you’ll instantly know it’s a wild place, especially the outdoor gardening section. People are rushing to the aisle with Black Kow manure, loading up carts before others arrive. It’s like the Tickle-Me Elmo craze of Christmas past, but instead of Elmo, it’s bagged cow poop that’s good for plants. Just being in such a crazy environment makes you want to try something new or have a personal project in mind.

    On one of my Home Depot weekends, I ended up buying a plant called Lemon Coral Sedum. It seemed like the sort of plant a questionable character like me could manage. I ended up putting a pot of this stuff outside my front door and noticed that, without any real care, it would naturally just spread and grow on the nearby rock beds. I didn’t so much as have to water it. There were just a sort of spongy, small growths that showed up nearby without any real human intervention. I’ve been letting the “weed” spread, collecting the growths, and putting them inside 3D-printed pots:

    I’ve always wanted to visit Easter Island. This is the best I can do.

    It’s wild how you can start out 3d printing circuit board enclosures and up with Moai with succulents growing out of their head.

  • Bermuda Experiment Update

    I haven’t really actively watered the Bermuda experiment since I was satisfied with seeing the different grass blades, but Scott’s common Bermuda absolutely took off even faster than the 2x-Pennington variant.

    I wish I had the resolve and fight in me that Bermuda grass has — I’d be a more successful human being. I guess I’ll just let it serve as inspiration:

    Bermuda grass!

    I’m very tempted to try and do a controlled region with this grass, but I believe working with it is like working with dynamite. All of my experience so far suggests that I cannot contain this grass in any meaningful way.

  • Moisture Sensors

    One of the ongoing problems I have in my irrigation system is that I think the zone grouping for the irrigation controller makes no sense. There are sections that need less water and other sections that need more water, but there’s no real way to decouple the total amount of flow to a specific area within a single zone without putting effort into physically changing the sprinkler heads. I also don’t have any sort of insight on what makes sense if I were to tweak sprinkler heads. My preference would be to split the zones, but apparently the trouble zone is in a “difficult” location.

    I’m attempting to gain some insight on this problem by looking at how different zones register in terms of soil moisture if I change the frequency of watering or with various settings. What I know from reading various internet forums is that the root system in one area could end up stunted if I don’t allow for deep watering. I’ve planted some sensors, and I’m already noticing that I’m still in over-watering territory even after dialing back my settings. If I can find some compromise here that works, I’d consider that a win. Here’s a recent sampling of data with a new sensor — there’s not enough data yet, but it makes for some nice blog color:

    Screenshot

    Plug Progress

    Oh, and here’s the plug progress. Things seem to be spreading, albeit slowly. (Some of the greenery is because I still have a Kyllinga infestation — it takes repeated application of herbicides to get rid of this damned weed.) I think the progress is quite visible relative to the photos from the first post showing the plugs being planted.

  • Plug Progress: Keepin’ it Reel

    It turned out that the reason there was so much devastation in my lawn is because the time slots that were programmed into my irrigation controller coincided with low municipal water supply pressure. The system was programmed to fire at 3:30 a.m. I wasn’t quite sure what was going on, so I placed little water collectors over the lawn to analyze the distribution of water:

    The Real Killer:

    When the boxes weren’t registering with water and there were soggy spots, I realized what had happened: the pooling zones contributed to fungus before the temps warmed up. The fungus weakened my St. Augustine and opened me up to weeds and Bermuda. My short cutting of the lawn didn’t help; however, had the irrigation been fine, I’d likely have been fine. I’ve halted mowing until I have an adequate green up, and then I’ll manually trim the height to the recommended 3-4″.

    It became much easier for me to manage the diagnosis of these problems after I installed a Wi-Fi unit into my irrigation controller and started observing behavior by triggering the app and zones as needed.

    The Real Kyllinga:

    The wet pooling zones contributed to another problem — kyllinga. I had the yard sprayed with Dismiss to blow away the sedge and the kyllinga. I have unsightly brown spots with dead kyllinga, although it looks like I need to hit the yard again in a few weeks to really manage this infestation.

    Plug Progress:

    Two weeks ago, I dropped plugs on the area where the sedge and kyllinga died off. The original photo was on or around April 7th. On April 21st, I am seeing extremely healthy plugs with very beautiful green growth. The eastern end of the plug patch is seemingly filling in. I did not hit this area with Dismiss; I’m just going to deal with the remaining weeds after the grass gets a stronger foothold.

    One thing about lawn issues is that the “debug cycle” to diagnose real problems is much longer than for diagnosing problems in something like software. The process of being forced to understand the process is helping me develop a real skill: being patient.

    Here’s a current photo of the progress below. (You can even see the dead kyllinga at the bottom.) The plugs themselves have greened up quite a bit — I’m just waiting for the runners to take off.

  • Plug’n Play

    This past week I realized the reason the verticut on the St. Augustine grass went poorly is because my irrigation system is broken. I’m waiting for irrigation repairs. (I tried tinkering with Bermuda plugs, but because of irrigation issues, most of my Bermuda plugs didn’t come out looking so hot. I’m toying with the idea of creating an isolated Bermuda zone to alpha-test the idea of converting to Bermuda grass.) In the meantime, I’m coming to terms with the sheer amount of turf-grass madness going on in my lawn.

    Last season, I had a professional come by and spray herbicide, not fully comprehending how weedy the lawn I acquired actually was. The professional basically said the nutsedge would sort of wilt away, but the remaining grass would stay somewhat healthy. What he didn’t explain was that where there were large pockets of sedge grass, I’d have a giant barren spot that would subject me to erosion and other dilemmas. I happened to have multiple spots like this.

    I’m just going to come out and say it: I can’t stand nutsedge. It’s only April, and this menace is everywhere. I power raked and tore up the dead zone where the previous nutsedge was and dropped plugs. It took some time and a lot of rewinding and replaying videos from people who seemed competent on YouTube:

    St. Augustine plugs (before pouring on compost and leveling sand)

    I have no idea whether this will work as I am a novice, but I enjoyed sweating in the hot Florida sun. It was a nice break from the sorts of problems I encounter on weekdays.

  • Bermuda Growth Rates

    Continuing the life of a grass-blundering fool, I’m still committed to the slow expansion of Bermuda grass, even though I’ve plugged parts of my lawn with St. Augustine where things have gone bad.

    You’re not supposed to seed a Bermuda lawn because of color mismatch — or so I am told on the lawn care forums. The patch growing on the west side of my lawn has this deep, dark emerald color that I wish I could match. But, just to test the theory out on seed coloration, I bought two random bags of grass and put the seeds on both sides of the pot:


    Supposedly, the Pennington “Smart Seed” variety was supposed to grow at 2x the rate. The seeds themselves were a different shape and color than the seeds from the Scott’s bag. Below in the photograph, I put the Pennington on the left of the pot and then the Scott’s on the right side of the pot. (The pot just has some potting soil in it, but I don’t think this affected the result too much.)

    Sure enough, around 2.5 weeks out, the Pennington grass is growing much much more quickly. The Scott’s grass is there if you look close enough.

    More importantly, though, the coloration on this grass is nowhere near the deep dark emerald color that I have growing on the lawn now. The forums are correct about seeds. I plan to transplant some of these seeds into an isolated zone to tinker with the fertilization parameters in different areas and test out different shade levels. Let’s see how that goes.

  • Blundering and Watching the Grass Grow

    I moved to Florida a few years ago, partly out of frustration with life during the pandemic where I previously lived. There was a lot going on, and life was complicated, but I managed to acquire tenant status at a few rental properties to occupy my time as I awaited what felt like an inevitable COVID-19 demise. The terms of the lease agreements required me to either take care of the lawns myself or hire a professional. Initially, I thought this wouldn’t be a big deal. Grass is just grass—just cut it.

    All the rental properties I lived in had St. Augustine grass. I became familiar with this type of grass; however, most of the irrigation parameters had been preset for me. The owners had already scheduled the fertilizer according to protocols and had stated their cutting height preferences. Generally, I only needed to replace bare spots with plugs or sod. I did the bare minimum to keep things green and healthy. Despite everyone around me being quite unimpressed that I handled my own lawn care, I largely enjoyed it.

    Then, I got my own lawn.

    I thought what I had was a different strain of St. Augustine grass because it was much softer and more pleasant to step on than the crunchy St. Augustine grass I had in the rental properties. I liked the feel on my feet when the grass was cut lower, so I continued to cut the lawn shorter and shorter, not realizing that I had a predominantly St. Augustine lawn which does not fare well when cut too low.

    For one full season, I cut my grass short and it seemed like things were going okay. Then, at the start of spring, I tried to cut even lower. I thought this might eliminate the little dead, dormant patches and encourage fresher, greener growth.

    This was a mistake.

    While my lawn isn’t completely dead, it’s looking a bit worse for wear. I reduced the cutting, improved the fertilizer situation, and increased the watering. However, an interesting side effect of my mistake was the appearance of a new grassy invader: Bermuda grass.

    My lawn turned out to be a mix of Bermuda and St. Augustine, but the longer blades of St. Augustine had mostly kept the Bermuda at bay and had dominated the growth in the lawn. I was fascinated by the appearance of Bermuda. I ran my fingers and feet through it. It was slim, soft, felt incredible, and spread rapidly wherever I cut the grass low. The first time I encountered a substantial patch of it, I was astonished. This grass is beautiful, invasive, and aggressive—the more I read about Bermuda, the more I became intrigued.

    It’s still early days, and I haven’t committed to a full Bermuda lawn, but I’ve decided to take a measured approach and gradually expand the Bermuda’s presence without completely destroying the St. Augustine. These two grasses require different care, and it’s not entirely clear if I’ve done irreparable harm to the St. Augustine. However, I’ve resolved to let the St. Augustine dominant patches grow back to 4 inches, and where the Bermuda has taken hold, I plan to cut very low and use a reel mower to help it spread.

    Here’s a photo of a border region where Bermuda thrived after I mistakenly cut too low. The left side shows where Bermuda has exploded, and the right side is a failed attempt at verticutting what probably shouldn’t have been cut low and verticut.

    As a side note, I’m writing here on the blog because I will talk about grass with anyone willing to listen. It just so happens that no one in my orbit wants to hear about grass from me, so I figured I might as well return to blogging on my low-traffic blog and write about grass. There’s nothing too controversial about grass, right?

  • Selectively composing classes with constexpr functions, SFINAE, and parameter-pack driven private-inheritance in C++17 (Part 1)

    This blog post was inspired by a use-case I encountered in an open source project where the developers wanted to offer different functionality depending on whether the product being offered was an enterprise offering versus a community offering. Under normal circumstances, preprocessor defines were used to separate functionality. However, when certain combinations of behavior were required, the preprocessor macro situation made the code much messier and harder to unit test. This post highlights a proposed solution and a trick I find particularly helpful.

    The Basics

    I think private inheritance is undervalued in the C++ universe, particularly now in C++17 where we have things like if-constexpr and more sophisticated compile-time capabilities. As you likely already knew, private inheritance, in the object-oriented software development universe, means that there exists a “has-a” relationship. (While I touch on the basics here a little bit, if you’re not familiar with private inheritance mechanics, the article here is also very helpful.)

    Consider the following:

    class Machine : private Gear {
        // ...
    };

    In the above code, a Machine “has a” Gear. If in a particular application, say the Machine has a Gear and also a Pulley. The class might then look something like:

    class Machine : private Gear, private Pulley {
        // ...
    };

    So far so good. When someone downstream of you wants to use your Machine in a C++ program, it wouldn’t be proper to type cast your Machine to a Pulley; a Machine isn’t necessarily a Pulley. This is one of the benefits of private inheritance — you can’t cast through a base-class pointer to a derived class. An additional bonus with private inheritance is that, with ‘using’ statements, you can pull the interface of a base class into the derived class’ interface. For example:

    class Machine : private Gear { 
      // ... 
    public:
      using Gear::someMethod;
    };

    In the above example, Gear‘s someMethod() is now part of the public interface for Machine.

    Towards the Maintenance Quandary:

    Let’s move away from our Machine example and move onto another class, Feature. Consider the entry blurb to this blog post where I encountered a problem where I needed a Feature to function a certain way depending on whether it’s an Enterprise or Community build. For the sake of discussion, let’s say I add a Developer build also. Furthermore, accept the following:

    • Enterprise functionality is provided by the EnterpriseFeatureImplementation class
    • Community functionality is provided by the CommunityFeatureImplementation class
    • Developer functionality is provided by the DeveloperFeatureImplementation class

    Our Feature implementation class could conceivably use methods from EnterpriseFeatureImplementation, CommunityFeatureImplementation, or DeveloperFeatureImplementation. A possible implementation could be something like the following:

    
    template< typename FEATURE_IMPL >
    class FeatureImpl : private FEATURE_IMPL {
    public:
      using FEATURE_IMPL::featureSpecificMethod;
    };
    
    constexpr auto feature_selector() {
        if constexpr( is_enterprise_build() ) {
            return EnterpriseFeatureImplementation();
        } else if constexpr ( is_developer_build() ) {
            return DeveloperFeatureImplementation();
        } else { /* if( is_community_build() ) */ 
            return CommunityFeatureImplementation();
        } 
    };
    
    using Feature = FeatureImpl< decltype( feature_selector() ) >;

    (For your benefit, I’ve created an execution environment for you to test and tinker with the above here: https://www.godbolt.org/z/4iRhwU.)

    On the surface, the above is fairly flexible; we have a constexpr function that evaluates some function that lets us choose what interface to expose at compile-time. However, there are some things about the above that can get irritating during development cycles. Namely, the feature_selector() method needs to be updated with various criteria in order to select which interface to use. I consider this a maintenance headache (thus, a maintenance quandary.)

    A more practical approach involves the use of templates and parameter packs. The goal will be to detect automatically whether a supplied class provides the functionality we need. For example:

    template< typename... FEATURE_IMPLS >
    class FeatureImpl : private FEATURE_IMPLS... {
      ... // Code goes here
    };

    And the above would be used like so:

    using Feature = FeatureImpl< Enterprise, Developer, Community >;

    But, an issue remains: How do we choose which methods via ‘using’ to bring to the derived class interface? How do we detect automatically whether the class supplies functionality for the service level (Enterprise or Community) that we want?

    A Proposed Fix for Interface Method Resolution:

    Earlier, I referred to the utility of being able to pull from privately inherited classes so that you could build an interface for the derived class. If we’re using a parameter pack, this clearly becomes tricky. The approach I am proposing involves the use of constexpr functions and SFINAE — let’s start with the basics (and later expand towards fold-driven broadcast methods and CRTP in Part 2!)

    At the start of the blog post, I mentioned choosing between enterprise and community features in an application — a community-edition binary would not need to supply functionality that is present an enterprise-edition binary, for example. Consider code like the following — and note the comment in the code:

    template< typename... FEATURE_IMPLS >
    class Feature : private FEATURE_IMPLS... {
    public:
        // How do we choose from FEATURE_IMPLS for 'using' statements?
    };

    My approach (to the question posted in the comment) is to resolve whether each class within FEATURE_IMPLS fits certain criteria and “upgrade” based on whether the binary has been configured to be built for community edition or enterprise. I would use code such as the following:

    template< typename... FEATURE_IMPLS >
    class Feature : private FEATURE_IMPLS... {
    public:
       using InterfaceMethodSelector = decltype( FeatureDetails::resolve_function< FEATURE_IMPLS... >() );
       using InterfaceMethodSelector::methodToUse;
    };

    The Resolve Function’s Meta Function:

    Let’s detail what a possible resolve_function might look like. First, let’s start with a simple meta-function — in this case, we consider a meta function that determines whether a feature implementation defines a constexpr function that tells us whether a class implements an enterprise feature. We use SFINAE such that substitution failure resolves to a derivative of std::false_type.

    template< typename T, typename = void >
    struct HasEnterpriseFeature : std::false_type {};
    
    template< typename T >
    struct HasEnterpriseFeature< T, std::enable_if_t< T().isEnterpriseFeature() > > : std::true_type {};
    

    The Resolve Function Itself:

    The resolve function’s innards:

    // If we get to the last type, just return the last type.  The default
    // will just be whatever lands last in the parameter pack.
    template< typename FEATURE >
    constexpr auto resolve_function() {
        return FEATURE();
    }
    
    template< typename FEATURE_IMPL, typename FEATURE_IMPL2, typename... REST_OF_FEATURE_IMPLS >
    constexpr auto resolve_function() {
        if constexpr( HasEnterpriseFeature< FEATURE_IMPL >() ) {
            return FEATURE_IMPL();
        } else {
            return resolve_function< FEATURE_IMPL2, REST_OF_FEATURE_IMPLS... >();
        }
    }

    What the above resolve_function does is use a meta-function (HasEnterpriseFeature<T>) to determine if a member of the pack has a feature. If it doesn’t have the feature, the function moves on to the next member of the pack. Note that the above is just an example. You could create your own resolve_function and use whatever criteria you’d like to compose your derived class interface.

    The final code would look something like the following:

    
    #include <iostream>
    #include <type_traits>
    
    namespace FeatureDetails {
    
    template< typename T, typename = void >
    struct HasEnterpriseFeature : std::false_type {};
    
    template< typename T >
    struct HasEnterpriseFeature< T, std::enable_if_t< T().isEnterpriseFeature() > > : std::true_type {};
    
    // If we get to the last type, just return the last type.  The default
    // will just be whatever lands last in the parameter pack.
    template< typename FEATURE >
    constexpr auto resolve_function() {
        return FEATURE();
    }
    
    template< typename FEATURE_IMPL, typename FEATURE_IMPL2, typename... REST_OF_FEATURE_IMPLS >
    constexpr auto resolve_function() {
        if constexpr( HasEnterpriseFeature< FEATURE_IMPL >() ) {
            return FEATURE_IMPL();
        } else {
            return resolve_function< FEATURE_IMPL2, REST_OF_FEATURE_IMPLS... >();
        }
    }
    
    }
    
    struct EnterpriseFeatureImplementation {
        // Comment this out to make it not compile
        constexpr auto isEnterpriseFeature() { return true; }
        auto methodToUse() { std::cout << "Enterprise implementation!" << std::endl; }    
    };
    
    struct CommunityFeatureImplementation {
        constexpr auto isEnterpriseFeature() { return false; }
        auto methodToUse() { std::cout << "Community implementation!" << std::endl; }
    };
    
    template< typename... FEATURE_IMPLS >
    class Feature : private FEATURE_IMPLS... {
    public:
       using InterfaceMethodSelector = decltype( FeatureDetails::resolve_function< FEATURE_IMPLS... >() );
       using InterfaceMethodSelector::methodToUse;
    };
    
    using SelectedFeature = Feature< EnterpriseFeatureImplementation, CommunityFeatureImplementation >;
    
    int main( int argc, char *argv[] ) {
        SelectedFeature f;
        f.methodToUse();
        return 0;
    }
    

    I have a sample of the use of the method here, on godbolt.org, an interactive online C++ environment: https://www.godbolt.org/z/4QMmMo

    Be sure to tinker with the example on Godbolt. Notice that the general rule still applies with templates: If the template isn’t used, the compiler doesn’t generate code for it. Observe the advantages of composing classes this way — you don’t pay for what you don’t use.

    You might still be asking some questions, however. What if you wanted to choose multiple methods from different classes? What if you wanted to execute multiple methods from subsets of the different classes. We’ll address those in Part 2.

  • Everything just broke: HDF5 woes on Ubuntu 18.04

    I wrote a system for capturing data and placing it into tables using HDF5. The system ran for 6 years or so, almost every single night, through various updates and upgrades. Then one day, I took production systems and just opportunistically updated them because I had some time on my hands. (I know, I know. It’s terrible dev-ops, but I’m a rag-tag operation here. Just look at this blog.) Oddly, as of two weeks ago, with no code changes, my system started generating .h5 files that were unusable. I only detected this problem as of 3 hours ago as a result of getting some bad calculations out of a batch job.

    I’m left thinking it was some kind of library change or library dependency that broke. I actually don’t know the exact reason (yet) why things broke, but I am guessing either some 1.8 to 1.10 issue or some library dependency triggered this new problem. Either way, I don’t care that much — I just want access to my old data back.

    Here are the symptoms and when I knew I was in trouble:

    HDF5 1.10 on Ubuntu no longer let me read read-only archives of files that were being read from and used daily for years. h5ls failed. h5dump failed. hdfview failed. When I tried to use h5ls or h5dump, they both just simply complained that they were unable to open the older files.

    If you’re panicking about data being inaccessible (like I was two hours ago), I have a temporary work-around. (I will update this post if anything changes.) You need to drop back to the older version of hdf5 — and you need to build it from source.

    git clone https://bitbucket.hdfgroup.org/scm/hdffv/hdf5.git

    Then, once you’re in the hdf5 directory from the git clone:

    git fetch origin hdf5_1_8
    git checkout hdf5_1_8
    mkdir build
    cd build
    cmake -DHDF5_ENABLE_Z_LIB_SUPPORT=on -DZLIB_USE_EXTERNAL=off ..

    Then build. Once it’s built, you can ‘sudo make install’ and the default configuration will put the installation files in /usr/local/HDF_Group. Here, you’ll find a set of builds of tools like h5ls, etc. You will also find development headers and libraries you can link your own utilities to.

    If you set your linker and include paths properly and rebuild your utilities against this library, you’ll at least be able to get back into your data. This will gave you some time with your data before you have to ponder future storage needs. In my case, I’ll be using the older library to re-encode the last two weeks of data.

    Perhaps it’s time to try Kudu or Parquet? Who knows? In any case, I hope this helps random people who might be flipping out over data loss.