<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:admin="http://webns.net/mvcb/"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
   xmlns:wfw="http://wellformedweb.org/CommentAPI/"
   xmlns:content="http://purl.org/rss/1.0/modules/content/"
   >
<channel>
    <title>Jay Pipes</title>
    <link>http://jpipes.com/</link>
    <description>Design, Develop, Discover, Define</description>
    <dc:language>en</dc:language>
    
    <generator>Serendipity 0.9 - http://www.s9y.org/</generator>
    
    <image>
        <url>http://jpipes.com/templates/default/img/s9y_banner_small.png</url>
        <title>RSS: Jay Pipes - Design, Develop, Discover, Define</title>
        <link>http://jpipes.com/</link>
        <width>100</width>
        <height>21</height>
    </image>
<item>
    <title>Describing Drizzle's Development Process</title>
    <link>http://jpipes.com/index.php?/archives/316-Describing-Drizzles-Development-Process.html</link>
<category>Open Source</category><category>MySQL</category><category>Drizzle</category>    <comments>http://jpipes.com/index.php?/archives/316-Describing-Drizzles-Development-Process.html#comments</comments>
    <wfw:comment>http://jpipes.com/wfwcomment.php?cid=316</wfw:comment>
    <slash:comments>13</slash:comments>
    <wfw:commentRss>http://jpipes.com/rss.php?version=2.0&amp;type=comments&amp;cid=316</wfw:commentRss>
    <author>nospam@example.com (Jay Pipes)</author>
    <content:encoded>
&lt;p&gt;
Yesterday, I was working on a survey that &lt;a href=&quot;http://www.chesnok.com/daily/&quot;  title=&quot;Selena Deckelmann&quot;&gt;Selena Deckelmann&lt;/a&gt; put together for open source databases.  She will be &lt;a href=&quot;http://www.lca2010.org.nz/programme/schedule/view_talk/50332?day=wednesday&quot;  title=&quot;Survey of Open Source Databases&quot;&gt;presenting the results&lt;/a&gt; at &lt;a href=&quot;http://www.lca2010.org.nz/&quot;  title=&quot;Linux.conf.au 2010&quot;&gt;Linux.conf.au&lt;/a&gt; this month.
&lt;/p&gt;
&lt;p&gt;
One of the questions on the survey was this:
&lt;/p&gt;
&lt;blockquote&gt;
How would you describe your development process?
&lt;/blockquote&gt;
&lt;p&gt;
followed by these answer choices:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Individuals request features&lt;/li&gt;
&lt;li&gt;Large/small group empowered to make decisions&lt;/li&gt;
&lt;li&gt;Benevolent dictator&lt;/li&gt;
&lt;li&gt;Other, please specify:____________&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
I thought a bit about the question and then answered the following in the &quot;Other, please specify:&quot; area:
&lt;/p&gt;
&lt;blockquote&gt;
Bit of a mix between all three above.
&lt;/blockquote&gt;
&lt;p&gt;
The more I think about it, the more I really do feel that Drizzle's development process is indeed a mixture of individuals, groups, and a &lt;a href=&quot;http://en.wikipedia.org/wiki/Benevolent_dictatorship&quot; &gt;Benevolent dictator&lt;/a&gt;.  And I think it works pretty well. &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt; Here's some of the reasons why I believe our development process is effective in enabling contributions by being a mix of the above three styles.
&lt;/p&gt;
&lt;h2&gt;Who's the Benevolent Dictator of Drizzle?&lt;/h2&gt;
&lt;p&gt;
First, let me get the &lt;a href=&quot;http://en.wikipedia.org/wiki/Benevolent_Dictator_For_Life&quot;  title=&quot;Benevolent Dictator for Life (BDFL)&quot;&gt;BDFL&lt;/a&gt; question out of the way.  We've made a big deal in the Drizzle community and mailing lists that anyone and everyone is encouraged to participate in the development process &amp;mdash; so why would I say that Drizzle has a benevolent dictator?
&lt;/p&gt;
&lt;p&gt;
Well, although he would probably disagree with the tile of BDFL, &lt;a href=&quot;http://krow.livejournal.com/&quot;  title=&quot;Brian &quot;Krow&quot; Aker&quot;&gt;Brian Aker&lt;/a&gt; does have some dictator-like abilities with regards to the development process, and rightfully so.  Brian came up with many of the concepts that Drizzle aspires to be, and Brian has more experience working on the code base than any other contributor.
&lt;/p&gt;
&lt;p&gt;
After having worked closely with Brian now for 18 months or so, I can definitively say that Brian's brain works in a very, well, interesting way.  Those of us who work with him understand that sometimes his brain works so fast, his typing fingers struggle to keep up, resulting in something I call &quot;Krowspeak&quot;.  It's kinda funny sometimes trying to translate &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
With this wonderfully unique noodle, Brian tends to knock out large chunks of code at a time, and often he wants to push these chunks of code into our &lt;a href=&quot;http://hudson.drizzle.org&quot;  title=&quot;Drizzle Build and Regression System - Hudson&quot;&gt;build and regression system&lt;/a&gt; and into trunk to see the results of his work quickly.  Sometimes, this can cause other branches to get out of sync and get merge conflicts, and Brian will inform branch owners of the conflicts and work with them to resolve them.
&lt;/p&gt;
&lt;p&gt;
So, regarding dictator-like development processes, I suppose we have Brian acting as the merge dictator because he's got a lot of experience and understands best how both his code and other's code integrates.  We tried a little while back having myself and Monty Taylor be merge captains, but that distribution of merge work actually created a number of other problems and we've since gone back to Brian being the merge captain by himself, with Lee, &lt;a href=&quot;http://inaugust.com&quot;  title=&quot;Monty Taylor&quot;&gt;Monty&lt;/a&gt;, and myself improving our &lt;a href=&quot;http://launchpad.net/drizzle-automation&quot;  title=&quot;Drizzle Automation project&quot;&gt;automated&lt;/a&gt; build and regression system to help Brian with the repetitive work. 
&lt;/p&gt;
&lt;p&gt;
That said, what Brian does &lt;em&gt;not&lt;/em&gt; do is make decisions in a dictator-like way.  Decisions about the code style, reviews, features, syntax changes, etc are made on the &lt;a href=&quot;https://launchpad.net/~drizzle-discuss&quot;  title=&quot;Drizzle Discuss mailing list&quot;&gt;mailing list&lt;/a&gt; by consensus vote.  If a consensus is not reached, generally, no change is made which would depend on the decision.  Brian does not influence the direction of the software or the source code style any more than anyone else on the mailing list which expresses an opinion about an issue; and for this, I greatly respect his wisdom to seek consensus in an open and community-oriented way.
&lt;/p&gt;
&lt;h2&gt;Groups Empowered to Make Decisions&lt;/h2&gt;
&lt;p&gt;
I'm assuming that what Selena's &quot;large/small group empowered to make decisions&quot; answer meant was what is sometimes called &quot;Cabal Leadership&quot; of a project.  In other words, there is some group which steers the project and makes decisions about the project which affect the rest of the project's contributors.
&lt;/p&gt;
&lt;p&gt;
Drizzle has at least one such group, the Sun Microsystems Drizzle Team, which is composed of Brian, Monty Taylor, Lee Bieber, Eric Day, Stewart Smith, and myself.  One might call us the core committers for Drizzle.
&lt;/p&gt;
&lt;p&gt;
However, while the Sun Drizzle team certainly is &lt;em&gt;empowered&lt;/em&gt; to guide development, it is no different than any other group of developers that choose to contribute to Drizzle.  There isn't a &quot;what the Sun Drizzle team decides&quot; rule in effect.  Our &quot;power&quot; in the development process is no greater or less than any other group of contributors.  We act merely as a team of individuals who work on the Drizzle code and advocate for the project's goals.
&lt;/p&gt;
&lt;h2&gt;Individuals Empowered to Make Decisions&lt;/h2&gt;
&lt;p&gt;
One thing I've been impressed with in the past 18 months is how the Drizzle community has embraced the opinions and work of individual contributors.  I believe &lt;a href=&quot;http://torum.net&quot;  title=&quot;Toru Maesaka&quot;&gt;Toru Maesaka&lt;/a&gt;, Andrew Hutchings, Diego Medina and &lt;a href=&quot;http://posulliv.com/&quot;  title=&quot;Padraig O'Sullivan&quot;&gt;Padraig O'Sullivan&lt;/a&gt; were among the first individuals to begin actively contributing to Drizzle.  Since then, dozens of others have joined the developer and advocate community, with each individual carving out a piece of the source code or community activities that they want to work on.
&lt;/p&gt;
&lt;p&gt;
I have learned much from all these individuals over the last year or so, and I've tried my best to share knowledge and encourage others to do the same.  Our IRC channel and mailing list are active places of discussion.  Our code reviews are always completely open to the public for comments and discussed transparently on Launchpad, and this code review process has been a great mixing bowl of opinion, discussion, learning and debate.  I love it.
&lt;/p&gt;
&lt;p&gt;
More and more we have developers showing up and taking ownership of a bug, a blueprint, or just a part of the code that interests them.  And nobody stands in their way and says &quot;Oh, no, you shouldn't work on that because &lt;em&gt;&amp;lt;insert another contributor's name&amp;gt;&lt;/em&gt; owns that code.&quot;  Instead, what you will more likely see on the lists or on IRC is a response like &quot;hey, that's awesome!  be sure to chat with &lt;em&gt;&amp;lt;insert another contributor's name&amp;gt;&lt;/em&gt;.  They are interested in that code, too, and you should share ideas!&quot;  This is incredibly refreshing to see.
&lt;/p&gt;
&lt;p&gt;
In short, the Drizzle developer process is a nice mix of empowered individuals and groups, and a dash of dictatorship just to keep things moving efficiently.  It's open, transparent, and fun to work on Drizzle.  Come join us &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;
&lt;/p&gt;    </content:encoded>
                
    <pubDate>Wed,  6 Jan 2010 11:17:42 -0500</pubDate>
    <guid isPermaLink="false">http://jpipes.com/index.php?/archives/316-guid.html</guid>
    </item>
<item>
    <title>Great Job, MySQL Engineering!</title>
    <link>http://jpipes.com/index.php?/archives/314-Great-Job,-MySQL-Engineering!.html</link>
<category>MySQL</category>    <comments>http://jpipes.com/index.php?/archives/314-Great-Job,-MySQL-Engineering!.html#comments</comments>
    <wfw:comment>http://jpipes.com/wfwcomment.php?cid=314</wfw:comment>
    <slash:comments>1</slash:comments>
    <wfw:commentRss>http://jpipes.com/rss.php?version=2.0&amp;type=comments&amp;cid=314</wfw:commentRss>
    <author>nospam@example.com (Jay Pipes)</author>
    <content:encoded>
&lt;p&gt;
Just a quick note to congratulate MySQL engineering on their next milestone release, &lt;a href=&quot;http://blogs.mysql.com/kaj/2009/12/15/mysql-550-m2-a-milestone-ready-to-download/&quot;  title=&quot;MySQL 5.5&quot;&gt;MySQL 5.5&lt;/a&gt;.  There seem to be some excellent new features, some of which have been hotly requested for quite some time:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Support for &lt;tt&gt;SIGNAL/RESIGNAL&lt;/tt&gt; &amp;mdash; the ANSI/ISO method of throwing errors inside SQL procedures&lt;/li&gt;
&lt;li&gt;Support for partitioning by &lt;tt&gt;RANGE COLUMNS&lt;/tt&gt; and &lt;tt&gt;LIST COLUMNS&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Support for &lt;tt&gt;semi-synchronous replication&lt;/tt&gt;, which ensures that the master waits until at least one slave has committed a transaction&lt;/li&gt; 
&lt;/ul&gt;
&lt;p&gt;
On the subject of &lt;tt&gt;SIGNAL/RESIGNAL&lt;/tt&gt;, Roland Bouman has, as usual, an &lt;a href=&quot;http://rpbouman.blogspot.com/2009/12/validating-mysql-data-entry-with_15.html&quot;  title=&quot;SIGNAL/RESIGNAL MySQL 5.5 - Roland Bouman&quot;&gt;excellent and informative article on the subject&lt;/a&gt;.  My personal opinion on &lt;tt&gt;SIGNAL/RESIGNAL&lt;/tt&gt; is that it is one of the most poorly-architected, clunky error-raising frameworks even invented, but alas, if you stick with ANSI standard SQL it's the only game in town.   I look forward to seeing the progress on this, especially in relation to the addition of &lt;tt&gt;DIAGNOSTICS&lt;/tt&gt;.
&lt;/p&gt;
&lt;p&gt;
Regarding semi-synchronous replication, Mark Callaghan had a &lt;a href=&quot;http://mysqlha.blogspot.com/2009/12/mysql-55-and-semi-sync-replication-are.html&quot;  title=&quot;MySQL semi-sync replication in 5.5&quot;&gt;quick write-up about it&lt;/a&gt;.  Check out his short article or &lt;a href=&quot;http://datacharmer.blogspot.com/2009/12/getting-started-with-mysql-55.html&quot;  title=&quot;Giuseppe's MySQL 5.5 primer&quot;&gt;Giuseppe's 5.5 primer&lt;/a&gt; for information.  Personally, I'm interested in this in Drizzle, because I'm working on the new replication system.  Putting this functionality into Drizzle shouldn't actually be too difficult.  I'm looking into it.
&lt;/p&gt;
&lt;p&gt;
Anyway, nice job MySQL! Keep up the good work, and continue the milestone release model.  It works.  It would be nice to hear MySQL engineers blogging about what they are working on, though.  Give the community a chance to comment on your work, etc, and drum up interest in the new features before they arrive. Hint, hint &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/wink.png&quot; alt=&quot;;-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;
&lt;/p&gt;    </content:encoded>
                
    <pubDate>Tue, 15 Dec 2009 17:59:12 -0500</pubDate>
    <guid isPermaLink="false">http://jpipes.com/index.php?/archives/314-guid.html</guid>
    </item>
<item>
    <title>A Laptop for Developers without paying The Windows Tax</title>
    <link>http://jpipes.com/index.php?/archives/313-A-Laptop-for-Developers-without-paying-The-Windows-Tax.html</link>
<category>Open Source</category><category>MySQL</category>    <comments>http://jpipes.com/index.php?/archives/313-A-Laptop-for-Developers-without-paying-The-Windows-Tax.html#comments</comments>
    <wfw:comment>http://jpipes.com/wfwcomment.php?cid=313</wfw:comment>
    <slash:comments>17</slash:comments>
    <wfw:commentRss>http://jpipes.com/rss.php?version=2.0&amp;type=comments&amp;cid=313</wfw:commentRss>
    <author>nospam@example.com (Jay Pipes)</author>
    <content:encoded>
&lt;p&gt;
I find it amazing that the U.S. Department of Justice can continue to cover its eyes and ears while Microsoft is allowed to exert its monopolistic power over all hardware manufacturers.
&lt;/p&gt;
&lt;p&gt;
About 20 months ago, I was able to purchase a Lenovo Thinkpad T61 from the lenovo.com website without an operating system installed.  Today, I went to purchase a new Lenovo Thinkpad laptop, again without having to pay the Windows Tax.  Turns out &lt;a href=&quot;http://lwn.net/Articles/298101/&quot;  title=&quot;Lenovo no longer offering Linux laptops&quot;&gt;Lenovo has stopped offering this option&lt;/a&gt;.  What a complete PILE OF SHIT.  Somebody in Microsoft's &quot;Business Development&quot; or &quot;Partners&quot; team must have told Lenovo to stop offering its customers a simple choice of not having to pay the OEM license fees for Windows.  And there's nothing anyone can do about it.  Microsoft is just too big and too pervasive for anybody to have a damn effect on them.
&lt;/p&gt;
&lt;p&gt;
Frankly, it's anti-choice, anti-competition, anti-innovation behaviour from Microsoft.
&lt;/p&gt;
&lt;p&gt;
And its ridiculous.
&lt;/p&gt;
&lt;p&gt;
Does anyone out there know how to get a decent laptop any more without having to fork over my money to a software giant that continues to bully all competition out of the market?  Your suggestions are most welcome.
&lt;/p&gt;
&lt;p&gt;
P.S. Mac is not an option for me.  Sorry.
&lt;/p&gt;
&lt;p&gt;
P.P.S The only thing this post has to do with MySQL is the general discussion on the acquisition of Sun by Oracle, and the pending investigation into possibly monopoly concerns by the EC...but of course I can't comment on that directly...grr.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;UPDATE&lt;/strong&gt;:
&lt;br /&gt;
Seems DELL offers laptops with Ubuntu installed instead of Windows, at least according to search results from their website.  Yeah! \o/ Of course, now I have to just figure out how to get to that customization option.  When I've gone through the customization screens, no option other than Windows is available. &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/sad.png&quot; alt=&quot;:-(&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;UPDATE 2&lt;/strong&gt;:
&lt;br /&gt;
The DELL representative on their online chat program was quite helpful and offered this link to &lt;a href=&quot;http://www.dell.com/business/laptops#subcats=&amp;navla=80770~0~1791343&amp;navidc=LT:%20Operating%20System&amp;navValc=FreeDOS%20and%20Linux&amp;a=80770~0~1791343&amp;page=1&quot; &gt;laptops they offer with no Windows Tax&lt;/a&gt;. &lt;/p&gt;    </content:encoded>
                
    <pubDate>Tue, 24 Nov 2009 13:39:56 -0500</pubDate>
    <guid isPermaLink="false">http://jpipes.com/index.php?/archives/313-guid.html</guid>
    </item>
<item>
    <title>Macro Support in new Drizzle Client Console?</title>
    <link>http://jpipes.com/index.php?/archives/312-Macro-Support-in-new-Drizzle-Client-Console.html</link>
<category>MySQL</category><category>Drizzle</category><category>Python</category>    <comments>http://jpipes.com/index.php?/archives/312-Macro-Support-in-new-Drizzle-Client-Console.html#comments</comments>
    <wfw:comment>http://jpipes.com/wfwcomment.php?cid=312</wfw:comment>
    <slash:comments>1</slash:comments>
    <wfw:commentRss>http://jpipes.com/rss.php?version=2.0&amp;type=comments&amp;cid=312</wfw:commentRss>
    <author>nospam@example.com (Jay Pipes)</author>
    <content:encoded>
&lt;p&gt;
Hi all!
&lt;/p&gt;
&lt;p&gt;
I've been reading through the requested features for the new client on the wiki here:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://drizzle.org/wiki/Proposed_Client_Features&quot;&gt;Proposed Client Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://drizzle.org/wiki/Client/Boots_API_Design_Concept&quot;&gt;BOOTS Console API Design&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
I think all the stuff on that link is excellent so far.  I'd also like to request a feature that I think will be a really cool timesaver for DBAs and developers using Drizzle.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;&lt;em&gt;Macro Support&lt;/em&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Remember, &quot;way back when&quot; you used Microsoft Excel and were able to start recording your actions, then when you stopped recording, Excel would store a &quot;macro&quot; of your actions that you could subsequently replay?
&lt;/p&gt;
&lt;p&gt;
I think this would be incredibly useful for folks who do repetitive work in the console.
&lt;/p&gt;
&lt;p&gt;
Sure, I know, I know...the first reaction folks will say is &quot;&lt;em&gt;but HEY, you guys removed stored procedures!&lt;/em&gt;&quot;  Yeah, yeah... but the feature I'm proposing here is different from stored procedures in the following ways:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;It's entirely client-side&lt;/strong&gt;.  There is no server-side storage/cache, processing, parsing, or anything.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;It's not limited to a small subset of SQL&lt;/strong&gt; that stored procedures (at least in MySQL) are currently limited to.  Anything the new client can do would be able to go into a macro.&lt;/li&gt;
&lt;li&gt;Since the client is in Python, &lt;strong&gt;the macros are themselves re-writable in a scripting language&lt;/strong&gt;.  This gives the recorded macros incredible flexibility.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No fussing with SQL stored procedure permissions&lt;/strong&gt; at runtime (you know, the silly INVOKER/DEFINER crap)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ability to interact with result sets in the macro&lt;/strong&gt;.  Just try doing that easily in a SQL stored procedure.  Using &lt;tt&gt;CURSOR&lt;/tt&gt;s is incredibly clunk and ugly.  Applying a Python function or closure/lambda on each of a result set is elegant and easy.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Imagine the following rough example interface...
&lt;/p&gt;
&lt;pre&gt;
drizzle&gt; RECORD MACRO &quot;sales_report_with_email&quot; (to_email);
macro recording started.

drizzle&gt; mode python;
in python mode.

python&gt; import datetime
python&gt; today= datetime.datetime.now().isoformat()
python&gt; filename= &quot;%s-%s-%s&quot; % (&quot;sales&quot;, to_email, today)
python&gt; Ctrl-D

drizzle&gt; SELECT * FROM sales
         WHERE manager = @to_email; &gt; csv(@filename);
drizzle&gt; mode python;
In python mode.

python&gt; report_txt= open(filename, &quot;r+b&quot;).read()
python&gt; import smtplib
python&gt; mailserver = smtplib.SMTP('localhost')
python&gt; mailserver.sendmail('theboss@company.com', to_email, report_txt)
python&gt; mailserver.quit()
python&gt; print &quot;Mail sent to %s\n&quot; % to_email
python&gt; Ctrl-D

drizzle&gt; STOP MACRO;
Macro &quot;sales_report_with_email&quot; saved.

drizzle&gt; macro(&quot;sales_report_with_email&quot;, &quot;myboss@company.com&quot;);
Mail sent to myboss@company.com
&lt;/pre&gt;
&lt;p&gt;
Pretty powerful, eh?
&lt;/p&gt;
&lt;p&gt;
If you follow the flow above, you will notice the only real trick to solve is passing the macro's arguments into the console's variable array, and from the console's variable array into the Python interpreter's variable scope.  But this is a fairly simple problem to solve...
&lt;/p&gt;
&lt;p&gt;
Thoughts?  Suggestions?  If you've got comments, please feel free to share here, or on the &lt;a href=&quot;https://launchpad.net/~drizzle-discuss&quot;  title=&quot;Drizzle Discuss&quot;&gt;Drizzle Discussion&lt;/a&gt; mailing list, or even update the wiki pages posted above.  Thanks! &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;
&lt;/p&gt;    </content:encoded>
                
    <pubDate>Wed, 18 Nov 2009 09:36:00 -0500</pubDate>
    <guid isPermaLink="false">http://jpipes.com/index.php?/archives/312-guid.html</guid>
    </item>
<item>
    <title>Somebody in Marketing Needs to be Fired</title>
    <link>http://jpipes.com/index.php?/archives/311-Somebody-in-Marketing-Needs-to-be-Fired.html</link>
<category>Thought Tree</category>    <comments>http://jpipes.com/index.php?/archives/311-Somebody-in-Marketing-Needs-to-be-Fired.html#comments</comments>
    <wfw:comment>http://jpipes.com/wfwcomment.php?cid=311</wfw:comment>
    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://jpipes.com/rss.php?version=2.0&amp;type=comments&amp;cid=311</wfw:commentRss>
    <author>nospam@example.com (Jay Pipes)</author>
    <content:encoded>
&lt;p&gt;
Sitting here chatting with &lt;a href=&quot;http://posulliv.com/&quot;  title=&quot;Padraig O'Sullivan&quot;&gt;Padraig&lt;/a&gt; and listening to the television.  A commercial comes on for &lt;a href=&quot;http://www.aciphex.com/&quot;  title=&quot;Ass Effects&quot;&gt;Aciphex&lt;/a&gt;.  Yep, the name is pronounced &quot;Ass Effects&quot;.  Unbelievable.  Somebody's marketing department should be, well, shot.
&lt;/p&gt;    </content:encoded>
                
    <pubDate>Tue, 10 Nov 2009 19:48:21 -0500</pubDate>
    <guid isPermaLink="false">http://jpipes.com/index.php?/archives/311-guid.html</guid>
    </item>
<item>
    <title>Sneak Peek - Drizzle Transaction Log and INFORMATION_SCHEMA</title>
    <link>http://jpipes.com/index.php?/archives/310-Sneak-Peek-Drizzle-Transaction-Log-and-INFORMATION_SCHEMA.html</link>
<category>MySQL</category><category>Drizzle</category><category>C/C++</category>    <comments>http://jpipes.com/index.php?/archives/310-Sneak-Peek-Drizzle-Transaction-Log-and-INFORMATION_SCHEMA.html#comments</comments>
    <wfw:comment>http://jpipes.com/wfwcomment.php?cid=310</wfw:comment>
    <slash:comments>1</slash:comments>
    <wfw:commentRss>http://jpipes.com/rss.php?version=2.0&amp;type=comments&amp;cid=310</wfw:commentRss>
    <author>nospam@example.com (Jay Pipes)</author>
    <content:encoded>
&lt;p&gt;
I've been coding up a storm in the last couple days and have just about completed coding on three new INFORMATION_SCHEMA views which allow anyone to query the new Drizzle transaction log for information about its contents.  I've also finished a new UDF for Drizzle called PRINT_TRANSACTION_MESSAGE() that prints out the &lt;a href=&quot;http://jpipes.com/index.php?/archives/302-Drizzle-Replication-Changes-in-API-to-support-Group-Commit.html&quot;  title=&quot;Drizzle transaction message&quot;&gt;Transaction message&lt;/a&gt;'s contents in a easy-to-read format.
&lt;/p&gt;
&lt;p&gt;
I don't have time for a full walk-through blog entry about it, so I'll just paste some output below and let y'all take a looksie.  A later blog entry will feature lots of source code explaining how you, too, can easily add INFORMATION_SCHEMA views to your Drizzle plugins.
&lt;/p&gt;
&lt;p&gt;
Below is the results of the following sequence of actions:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Start up a Drizzle server with the transaction log enabled, checksumming enabled, and the default replicator enabled.&lt;/li&gt;
&lt;li&gt;Open a Drizzle client&lt;/li&gt;
&lt;li&gt;Create a sample table, insert some data into it, do an update to that table, then drop the table&lt;/li&gt;
&lt;li&gt;Query the INFORMATION_SCHEMA views and take a look at the transaction messages and information the transaction log now contains&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Enjoy! &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;&lt;/p&gt;
&lt;pre&gt;
jpipes@serialcoder:~/repos/drizzle/replication-group-commit/tests$ ./dtr --mysqld=&quot;--default-replicator-enable&quot;\
 --mysqld=&quot;--transaction-log-enable&quot;\
 --mysqld=&quot;--transaction-log-enable-checksum&quot;\
 --start-and-exit
&amp;lt;snip&amp;gt;
Servers started, exiting
jpipes@serialcoder:~/repos/drizzle/replication-group-commit/tests$ ../client/drizzle --port=9306
Welcome to the Drizzle client..  Commands end with ; or \g.
Your Drizzle connection id is 2
Server version: 2009.11.1181 Source distribution (replication-group-commit)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

drizzle&gt; use test
Database changed
drizzle&gt; CREATE TABLE t1 (   id INT NOT NULL PRIMARY KEY , padding VARCHAR(200) NOT NULL );
Query OK, 0 rows affected (0.01 sec)

drizzle&gt; INSERT INTO t1 VALUES (1, &quot;I love testing.&quot;);
Query OK, 1 row affected (0.01 sec)

drizzle&gt; INSERT INTO t1 VALUES (2, &quot;I hate testing.&quot;);
Query OK, 1 row affected (0.01 sec)

drizzle&gt; UPDATE t1 SET padding=&quot;I love it when a plan comes together&quot; WHERE id = 2;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

drizzle&gt; DROP TABLE t1;
Query OK, 0 rows affected (0.17 sec)

drizzle&gt; SELECT * FROM INFORMATION_SCHEMA.TRANSACTION_LOG\G
*************************** 1. row ***************************
         FILE_NAME: transaction.log
       FILE_LENGTH: 639
   NUM_LOG_ENTRIES: 5
  NUM_TRANSACTIONS: 5
MIN_TRANSACTION_ID: 0
MAX_TRANSACTION_ID: 9
 MIN_END_TIMESTAMP: 1257888458463696
 MAX_END_TIMESTAMP: 1257888473929116
1 row in set (0 sec)

drizzle&gt; SELECT * FROM INFORMATION_SCHEMA.TRANSACTION_LOG_ENTRIES;
+--------------+-------------+--------------+
| ENTRY_OFFSET | ENTRY_TYPE  | ENTRY_LENGTH |
+--------------+-------------+--------------+
|            0 | TRANSACTION |          141 | 
|          141 | TRANSACTION |          121 | 
|          262 | TRANSACTION |          121 | 
|          383 | TRANSACTION |          181 | 
|          564 | TRANSACTION |           75 | 
+--------------+-------------+--------------+
5 rows in set (0 sec)

drizzle&gt; SELECT * FROM INFORMATION_SCHEMA.TRANSACTION_LOG_TRANSACTIONS;
+--------------+----------------+-----------+------------------+------------------+----------------+------------+
| ENTRY_OFFSET | TRANSACTION_ID | SERVER_ID | START_TIMESTAMP  | END_TIMESTAMP    | NUM_STATEMENTS | CHECKSUM   |
+--------------+----------------+-----------+------------------+------------------+----------------+------------+
|            0 |              0 |         1 | 1257888458463668 | 1257888458463696 |              1 | 3275955647 | 
|          141 |              7 |         1 | 1257888462222183 | 1257888462226990 |              1 |  407829420 | 
|          262 |              8 |         1 | 1257888465371330 | 1257888465378423 |              1 | 4073072174 | 
|          383 |              9 |         1 | 1257888470209443 | 1257888470215165 |              1 |   92884681 | 
|          564 |              9 |         1 | 1257888473929111 | 1257888473929116 |              1 | 2850269133 | 
+--------------+----------------+-----------+------------------+------------------+----------------+------------+
5 rows in set (0 sec)

drizzle&gt; SELECT PRINT_TRANSACTION_MESSAGE(&quot;transaction.log&quot;, ENTRY_OFFSET) as trx 
       &gt; FROM INFORMATION_SCHEMA.TRANSACTION_LOG_ENTRIES\G
*************************** 1. row ***************************
trx: transaction_context {
  server_id: 1
  transaction_id: 0
  start_timestamp: 1257888458463668
  end_timestamp: 1257888458463696
}
statement {
  type: RAW_SQL
  start_timestamp: 1257888458463676
  end_timestamp: 1257888458463694
  sql: &quot;CREATE TABLE t1 (   id INT NOT NULL PRIMARY KEY , padding VARCHAR(200) NOT NULL )&quot;
}

*************************** 2. row ***************************
trx: transaction_context {
  server_id: 1
  transaction_id: 7
  start_timestamp: 1257888462222183
  end_timestamp: 1257888462226990
}
statement {
  type: INSERT
  start_timestamp: 1257888462222185
  end_timestamp: 1257888462226989
  insert_header {
    table_metadata {
      schema_name: &quot;test&quot;
      table_name: &quot;t1&quot;
    }
    field_metadata {
      type: INTEGER
      name: &quot;id&quot;
    }
    field_metadata {
      type: VARCHAR
      name: &quot;padding&quot;
    }
  }
  insert_data {
    segment_id: 1
    end_segment: true
    record {
      insert_value: &quot;1&quot;
      insert_value: &quot;I love testing.&quot;
    }
  }
}

*************************** 3. row ***************************
trx: transaction_context {
  server_id: 1
  transaction_id: 8
  start_timestamp: 1257888465371330
  end_timestamp: 1257888465378423
}
statement {
  type: INSERT
  start_timestamp: 1257888465371332
  end_timestamp: 1257888465378422
  insert_header {
    table_metadata {
      schema_name: &quot;test&quot;
      table_name: &quot;t1&quot;
    }
    field_metadata {
      type: INTEGER
      name: &quot;id&quot;
    }
    field_metadata {
      type: VARCHAR
      name: &quot;padding&quot;
    }
  }
  insert_data {
    segment_id: 1
    end_segment: true
    record {
      insert_value: &quot;2&quot;
      insert_value: &quot;I hate testing.&quot;
    }
  }
}

*************************** 4. row ***************************
trx: transaction_context {
  server_id: 1
  transaction_id: 9
  start_timestamp: 1257888470209443
  end_timestamp: 1257888470215165
}
statement {
  type: UPDATE
  start_timestamp: 1257888470209446
  end_timestamp: 1257888470215163
  update_header {
    table_metadata {
      schema_name: &quot;test&quot;
      table_name: &quot;t1&quot;
    }
    key_field_metadata {
      type: INTEGER
      name: &quot;id&quot;
    }
    set_field_metadata {
      type: VARCHAR
      name: &quot;padding&quot;
    }
  }
  update_data {
    segment_id: 1
    end_segment: true
    record {
      key_value: &quot;2&quot;
      key_value: &quot;I love it when a plan comes together&quot;
      after_value: &quot;I love it when a plan comes together&quot;
    }
  }
}

*************************** 5. row ***************************
trx: transaction_context {
  server_id: 1
  transaction_id: 9
  start_timestamp: 1257888473929111
  end_timestamp: 1257888473929116
}
statement {
  type: RAW_SQL
  start_timestamp: 1257888473929113
  end_timestamp: 1257888473929115
  sql: &quot;DROP TABLE `t1`&quot;
}

5 rows in set (0.06 sec)
&lt;/pre&gt;
&lt;p&gt;
FYI, if you look closely, you'll see some odd things &amp;mdash; namely that there is a transaction with an ID of zero.  I'm aware of this and am working on fixing it &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;  Like I said, I'm &lt;em&gt;almost&lt;/em&gt; done coding...
&lt;/p&gt;    </content:encoded>
                
    <pubDate>Tue, 10 Nov 2009 17:30:00 -0500</pubDate>
    <guid isPermaLink="false">http://jpipes.com/index.php?/archives/310-guid.html</guid>
    </item>
<item>
    <title>The Great Escape</title>
    <link>http://jpipes.com/index.php?/archives/309-The-Great-Escape.html</link>
<category>MySQL</category><category>Drizzle</category><category>C/C++</category>    <comments>http://jpipes.com/index.php?/archives/309-The-Great-Escape.html#comments</comments>
    <wfw:comment>http://jpipes.com/wfwcomment.php?cid=309</wfw:comment>
    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://jpipes.com/rss.php?version=2.0&amp;type=comments&amp;cid=309</wfw:commentRss>
    <author>nospam@example.com (Jay Pipes)</author>
    <content:encoded>
&lt;p&gt;
This week, I am working on putting together test cases which validate the &lt;a href=&quot;http://jpipes.com/index.php?/archives/299-Drizzle-Replication-The-Transaction-Log.html&quot;  title=&quot;Drizzle transaction log&quot;&gt;Drizzle transaction log&lt;/a&gt;'s handling of BLOB columns.
&lt;/p&gt;
&lt;p&gt;
I ran into an interesting set of problems and am wondering how to go about handling them.  Perhaps the LazyWeb will have some solutions. &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
The problem, in short, is inconsistency in the way that the NUL character is escaped (or not escaped) in both the MySQL/Drizzle protocol and the MySQL/Drizzle client tools.  And, by client tools, I mean both everyone's favourite little mysql command-line client, but also the mysqltest client, which provides infrastructure and runtime services for the MySQL and Drizzle test suites.
&lt;/p&gt;
&lt;p&gt;
Even within the server and client protocol, there appears to be some inconsistency in how and when things are escaped.  Take a look at this interesting output from the drizzle client program (FYI, output is identical for mysql client, I checked...)
&lt;/p&gt;
&lt;pre&gt;
drizzle&gt; select 'test\0me';
+---------+
| test    |
+---------+
| test me | 
+---------+
1 row in set (0 sec)
&lt;/pre&gt;
&lt;p&gt;
You'll notice that in the first &lt;tt&gt;SELECT&lt;/tt&gt; statement, the column header is cut off &amp;mdash; i.e. the column header is not escaping the &lt;tt&gt;\0&lt;/tt&gt; NUL character in the string &lt;tt&gt;'test\0me'&lt;/tt&gt;.  However, the result data &lt;strong&gt;&lt;em&gt;does not&lt;/em&gt;&lt;/strong&gt; truncate the string but &lt;em&gt;replaces&lt;/em&gt; the NUL character with a space character.  So, I came to the conclusion that the drizzle client does not escape column headers but does do some sort of escaping for the result data. Given this conclusion, you will understand my raised eyebrow when the following &lt;tt&gt;SELECT&lt;/tt&gt; statement was displayed:
&lt;/p&gt;
&lt;pre&gt;
drizzle&gt; select 'test\0me' = 'test me';
+------------------------+
| 'test\0me' = 'test me' |
+------------------------+
|                      0 | 
+------------------------+
1 row in set (0 sec)
&lt;/pre&gt;
&lt;p&gt;
Hmmm...so maybe column headers &lt;em&gt;are&lt;/em&gt; being escaped by the MySQL/Drizzle client?  Clearly, the NUL character was escaped as the characters '\\' followed by the character '0' in the column header above.  Indeed, quite puzzling.
&lt;/p&gt;
&lt;p&gt;
OK, so the above anomaly needs to be investigated.  However, a similar issue exists for the mysqltest/drizzletest client program.  To see the problem, check the following out.  I create a simple test case with the following in it:
&lt;/p&gt;
&lt;pre&gt;
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings

SELECT 'test\0me';

CREATE TABLE t1 (fld BLOB NULL);
INSERT INTO t1 VALUES ('test\0me');
SELECT COUNT(*) FROM t1;
DROP TABLE t1;
&lt;/pre&gt;
&lt;p&gt;
Now, what you &lt;strong&gt;would expect to see&lt;/strong&gt; for the output of the above &amp;mdash; at least if you expect results similar to the MySQL/Drizzle client output &amp;mdash; is the following:
&lt;/p&gt;
&lt;pre&gt;
DROP TABLE IF EXISTS t1;
SELECT 'test\0me';
test
test me
CREATE TABLE t1 (fld BLOB NULL);
INSERT INTO t1 VALUES ('test\0me');
SELECT COUNT(*) FROM t1;
COUNT(*)
1
DROP TABLE t1;
&lt;/pre&gt;
&lt;p&gt;
That is what you would &lt;em&gt;expect&lt;/em&gt; to see in the output of course... Here is what you &lt;em&gt;actually&lt;/em&gt; get in the output:
&lt;/p&gt;
&lt;pre&gt;
DROP TABLE IF EXISTS t1;
SELECT 'test\0me';
test
test
&lt;/pre&gt;
&lt;p&gt;
So, the mysqltest/drizzletest client apparently does not escape the NUL character for the &lt;strong&gt;result data&lt;/strong&gt; at all.  It looks like it does do some escaping/replacing for the NUL character in the column header, though, otherwise the second &quot;test&quot; line would not appear.  This leads to the result file being essentially truncated as soon as a NUL character is included in any output to the mysqltest/drizzletest client.  This essentially makes the mysqltest/drizzletest client useless for testing and validating BLOB data.
&lt;/p&gt;
&lt;h2&gt;Possible Solutions?&lt;/h2&gt;
&lt;p&gt;
I think the cleanest solution would be to create a shared library of code that would be responsible for uniformly and consistently escaping data, and then linking the various clients (and server) with this library and removing all of the various escaping functions currently in the server.  This would, of course, take some time, but would be the most future proof solution.  Anyone else have ideas on solving the problem of being able to test and validate binary data via the test suite?  Cheers!
&lt;/p&gt;
&lt;/p&gt;
    </content:encoded>
                
    <pubDate>Wed,  4 Nov 2009 11:11:00 -0500</pubDate>
    <guid isPermaLink="false">http://jpipes.com/index.php?/archives/309-guid.html</guid>
    </item>
<item>
    <title>A Month of Milestones</title>
    <link>http://jpipes.com/index.php?/archives/308-A-Month-of-Milestones.html</link>
<category>MySQL</category><category>Drizzle</category>    <comments>http://jpipes.com/index.php?/archives/308-A-Month-of-Milestones.html#comments</comments>
    <wfw:comment>http://jpipes.com/wfwcomment.php?cid=308</wfw:comment>
    <slash:comments>5</slash:comments>
    <wfw:commentRss>http://jpipes.com/rss.php?version=2.0&amp;type=comments&amp;cid=308</wfw:commentRss>
    <author>nospam@example.com (Jay Pipes)</author>
    <content:encoded>
&lt;p&gt;
I'm finding myself smiling today.  I lay in bed last night thinking about a number of milestones that this month marks for me.
&lt;/p&gt;
&lt;p&gt;
October 15th marked four months since the last time I had a cigarette.  I feel good about my chances at remaining smoke-free for the remainder of my life.
&lt;/p&gt;
&lt;p&gt;
October 18th marked one year since I officially began working on the &lt;a href=&quot;http://drizzle.org/&quot;  title=&quot;Drizzle project&quot;&gt;Drizzle&lt;/a&gt; project.  Although, as &lt;a href=&quot;http://datacharmer.blogspot.com/&quot;  title=&quot;Giuseppe Maxia&quot;&gt;Giuseppe&lt;/a&gt; can attest to, I had been contributing to Drizzle before October 18th, 2008, that date was the official start. &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
I think about how much has been accomplished by the Drizzle community since that time.  The Drizzle of October 2008 is barely recognizable now.  &lt;a href=&quot;http://inaugust.com/&quot;  title=&quot;Monty Taylor&quot;&gt;Monty&lt;/a&gt;'s incredible work on the &lt;a href=&quot;https://launchpad.net/pandora-build&quot;  title=&quot;Pandora Build&quot;&gt;build system&lt;/a&gt;, &lt;a href=&quot;http://flamingspork.com&quot;  title=&quot;Stewart Smith&quot;&gt;Stewart&lt;/a&gt;'s continued removal of legacy Unireg code like the FRM files, &lt;a href=&quot;http://oddments.org/&quot;  title=&quot;Eric Day&quot;&gt;Eric Day&lt;/a&gt; joining the Sun Drizzle team and contributing amazing work on the protocol and client libraries, Monty's reworking of the plugin system, new datetime (temporal) work, &lt;a href=&quot;http://posulliv.com/&quot;  title=&quot;Padraig O'Sullivan&quot;&gt;Padraig O'Sullivan&lt;/a&gt;'s enormous contributions in the arena of the INFORMATION_SCHEMA, the optimizer, runtime, replication, and memcached, and an &lt;a href=&quot;http://launchpad.net/drizzle-automation&quot;  title=&quot;Drizzle Automation&quot;&gt;automation system&lt;/a&gt; that provides per-commit regression feedback.  It's truly fantastic to be part of a living, breathing, active project with so many special contributors who bring infectious enthusiasm to the world of database development.  I'm privileged to be a part of it.
&lt;/p&gt;
&lt;p&gt;
And finally, Tuesday the 28th marked the day that the new &lt;a href=&quot;http://jpipes.com/index.php?/archives/302-Drizzle-Replication-Changes-in-API-to-support-Group-Commit.html&quot;  title=&quot;Drizzle replication&quot;&gt;transactional replication system&lt;/a&gt; hit Drizzle's trunk.  While a ton of work is of course left to be done on the replication system, Tuesday's code hitting trunk was a big milestone that I'm really happy about.
&lt;/p&gt;
&lt;p&gt;
Anyway, just wanted to share some happiness. Cheers.
&lt;/p&gt;    </content:encoded>
                
    <pubDate>Thu, 29 Oct 2009 10:41:00 -0400</pubDate>
    <guid isPermaLink="false">http://jpipes.com/index.php?/archives/308-guid.html</guid>
    </item>
<item>
    <title>If Ever There Was a Sure-fire Tenant...</title>
    <link>http://jpipes.com/index.php?/archives/307-If-Ever-There-Was-a-Sure-fire-Tenant....html</link>
<category>Open Source</category>    <comments>http://jpipes.com/index.php?/archives/307-If-Ever-There-Was-a-Sure-fire-Tenant....html#comments</comments>
    <wfw:comment>http://jpipes.com/wfwcomment.php?cid=307</wfw:comment>
    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://jpipes.com/rss.php?version=2.0&amp;type=comments&amp;cid=307</wfw:commentRss>
    <author>nospam@example.com (Jay Pipes)</author>
    <content:encoded>
&lt;p&gt;
My wife and I have a double that we rent out to two couples.  Luckily, one of these couples has been in one side of the double for a couple years now.  They are quite stable, and are excellent renters, at least as much as a landlord likes. Stability == good for landlords.
&lt;/p&gt;
&lt;p&gt;
I was reviewing some code today, and a thought crossed my mind that sparked my landlord brain.  I was staring at the copyright and license header in a Drizzle plugin and it struck me...
&lt;/p&gt;
&lt;p&gt;
If ever there was a steady, rock-solid tenant, I would guess that it would be the occupant of this address:
&lt;/p&gt;
&lt;blockquote&gt;
51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
&lt;/blockquote&gt;
&lt;p&gt;
Now, I don't know if the &lt;a href=&quot;http://www.fsf.org/&quot;  title=&quot;Free Software Foundation&quot;&gt;Free Software Foundation&lt;/a&gt; owns the address above, or if they rent.  But, it occurred to me that if they &lt;em&gt;do&lt;/em&gt; rent the fifth floor of that building, that the owner of that building must have one of the most trustworthy and reliable tenants ever.
&lt;/p&gt;
&lt;p&gt;
I mean, we all know how much of a pain in the ass it is to move households.  You've got to notify everyone about the new address, find friends who will help move furniture for the price of a six-pack, etc.  But think of the giant problem the FSF would have if it ever decided to move. Think of the tens (hundreds?) of thousands of source code files which would suddenly have an erroneous address. I wonder if the owner of that Franklin Street building has thought of this, and has smiled, knowing just how much of a pain changing addresses would be for the FSF. Hmmm, food for thought. &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;
&lt;/p&gt;    </content:encoded>
                
    <pubDate>Wed, 28 Oct 2009 21:32:59 -0400</pubDate>
    <guid isPermaLink="false">http://jpipes.com/index.php?/archives/307-guid.html</guid>
    </item>
<item>
    <title>Drizzle Replication - The Transaction Log</title>
    <link>http://jpipes.com/index.php?/archives/299-Drizzle-Replication-The-Transaction-Log.html</link>
<category>MySQL</category><category>Drizzle</category><category>C/C++</category>    <comments>http://jpipes.com/index.php?/archives/299-Drizzle-Replication-The-Transaction-Log.html#comments</comments>
    <wfw:comment>http://jpipes.com/wfwcomment.php?cid=299</wfw:comment>
    <slash:comments>4</slash:comments>
    <wfw:commentRss>http://jpipes.com/rss.php?version=2.0&amp;type=comments&amp;cid=299</wfw:commentRss>
    <author>nospam@example.com (Jay Pipes)</author>
    <content:encoded>
&lt;style type=&quot;text/css&quot;&gt;/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */
div.syntax
{
font-family: 'Courier New', Courier, monospace; 
background:white;
}

div.syntax a
{
font-family: 'Courier New', Courier, monospace; 
font-weight: normal;
color:black;
text-decoration:underline;
}

.cpp .de1, .cpp .de2 {font-family: 'Courier New', Courier, monospace; font-weight: normal;}
.cpp  {font-family: 'Courier New', Courier, monospace;}
.cpp .imp {font-weight: bold; color: red;font-family: 'Courier New', Courier, monospace;}
.cpp li {background: #ffffff;font-family: 'Courier New', Courier, monospace;}
.cpp li.li2 {background: #f8f8f8;font-family: 'Courier New', Courier, monospace;}
.cpp .kw1 {color: #0000ff;font-family: 'Courier New', Courier, monospace;}
.cpp .kw2 {color: #0000ff;font-family: 'Courier New', Courier, monospace;}
.cpp .kw3 {color: #0000dd;font-family: 'Courier New', Courier, monospace;}
.cpp .kw4 {color: #0000ff;font-family: 'Courier New', Courier, monospace;}
.cpp .co1 {color: #008800;font-family: 'Courier New', Courier, monospace;}
.cpp .co2 {color: #008800;font-family: 'Courier New', Courier, monospace;}
.cpp .coMULTI {color: #ff0000; font-style: italic;font-family: 'Courier New', Courier, monospace;}
.cpp .es0 {color: #666666; font-weight: bold;font-family: 'Courier New', Courier, monospace;}
.cpp .br0 {color: #000000;font-family: 'Courier New', Courier, monospace;}
.cpp .st0 {color: #666666;font-family: 'Courier New', Courier, monospace;}
.cpp .nu0 {color: #0000dd;font-family: 'Courier New', Courier, monospace;}
.cpp .me1 {color: #000000;font-family: 'Courier New', Courier, monospace;}
.cpp .me2 {color: #000000;font-family: 'Courier New', Courier, monospace; font-weight: normal;}
&lt;/style&gt;
&lt;p&gt;
In this installment of my Drizzle Replication blog series, I'll be talking about &lt;strong&gt;the Transaction Log&lt;/strong&gt;.  Before reading this entry, you may want to first read up on the &lt;a href=&quot;http://jpipes.com/index.php?/archives/302-Drizzle-Replication-Changes-in-API-to-support-Group-Commit.html&quot;  title=&quot;Drizzle Replication - The Transaction Message&quot;&gt;Transaction Message&lt;/a&gt;, which is a central concept to this blog entry.
&lt;/p&gt;
&lt;p&gt;
The transaction log is just one component of Drizzle's default replication services, but it also serves as a generalized log of atomic data changes to a particular server.  In this way, it is only partially related to replication.  The transaction log is used by components of the replication services to store changes made to a server's data.  However, there is nothing that mandates that this particular transaction log be a required feature for Drizzle replication systems.  For instance, Eric Lambert is currently working on a Gearman-based replication service which, while following the same APIs, does not require the transaction log to function.  Furthermore, other, non-replication-related modules may use the transaction log themselves.  For instance, a future Recovery and/or Backup module may just as easily use the transaction log for its own purposes as well.
&lt;/p&gt;
&lt;p&gt;
Before we get into the details, it's worth noting the general goals we've had for the transaction log, as these goals may help explain some of the design choices made.  In short, the goals for the transaction log are:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Introduce &lt;strong&gt;no global contention points (mutexes/locks)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Once written, the transaction log &lt;strong&gt;may not be modified&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;The transaction log should be &lt;strong&gt;easily readable in multiple programming languages&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Overview of the Transaction Log Structure&lt;/h2&gt;
&lt;p&gt;
&lt;img src=&quot;img/transaction_log_format.png&quot; style=&quot;float: left; margin: 0px 100px 0px 0px;&quot; /&gt;
&lt;img src=&quot;img/transaction_log_entry_format.png&quot; style=&quot;float: left; margin: 0px 100px 0px 0px;&quot; /&gt;
&lt;img src=&quot;img/transaction_message_entry_format.png&quot; style=&quot;float: left; margin: 0px 100px 20px 0px;&quot; /&gt;
The format of the transaction log is simple and straightforward.  It is a single file that contains log entries, one after another.  These log entries have a type associated with them.  Currently, there are only two types of entries that can go in the transaction log: a Transaction message entry and a BLOB entry.  We will only cover the Transaction message entry in this article, as I'll leave how to deal with BLOBs for a separate article entirely.
&lt;/p&gt;
&lt;p&gt;
Each entry in the transaction log is preceded by a 4 bytes containing an integer code identifying the type of entry to follow.  The bytes which follow this type header are interpreted based on the type of entry.  For entries of type Transaction message, the graphics here show the layout of the entry in the log.  First, a 4 byte length header is written, then the serialized Transaction message, then a 4 byte checksum of the serialized Transaction message.
&lt;/p&gt;
&lt;br style=&quot;clear: both;&quot; /&gt;
&lt;h2&gt;Details of the &lt;tt&gt;TransactionLog::apply()&lt;/tt&gt; Method&lt;/h2&gt;
&lt;p&gt;
For those interested in how the transaction log is written to, I'm going to detail the &lt;tt&gt;apply()&lt;/tt&gt; method of the &lt;tt&gt;TransactionLog&lt;/tt&gt; class in &lt;tt&gt;/plugin/transaction_log/transaction_log.cc&lt;/tt&gt;.  The &lt;tt&gt;TransactionLog&lt;/tt&gt; class is simply a subclass of &lt;tt&gt;plugin::TransactionApplier&lt;/tt&gt; and therefore must implement the single pure virtual &lt;tt&gt;apply&lt;/tt&gt; method of that class interface.
&lt;/p&gt;
&lt;p&gt;
The TransactionLog class has a private &lt;tt&gt;drizzled::atomic&amp;lt;off_t&amp;gt;&lt;/tt&gt; called &lt;tt&gt;log_offset&lt;/tt&gt; which is an offset into the transaction log file that is incremented with each atomic write to the log file.  You will notice in the code below that this atomic off_t is stored locally, then incremented by the total length of the log entry to be written.  A buffer is then written to the log file using &lt;tt&gt;&lt;a href=&quot;http://opengroup.org/onlinepubs/007908799/xsh/pwrite.html&quot;  title=&quot;pwrite POSIX call&quot;&gt;pwrite()&lt;/a&gt;&lt;/tt&gt; at the original offset.  In this way, we completely avoid calling &lt;tt&gt;&lt;a href=&quot;http://opengroup.org/onlinepubs/007908775/xsh/pthread_mutex_lock.html&quot;  title=&quot;pthread_mutex_lock POSIX call&quot;&gt;pthread_mutex_lock()&lt;/a&gt;&lt;/tt&gt; or similar when writing to the log file, which should increase scalability of the transaction log.
&lt;/p&gt;
&lt;div class=&quot;syntax&quot;&gt;&lt;div class=&quot;cpp&quot; style=&quot;font-family: monospace;&quot;&gt;&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;void&lt;/span&gt; TransactionLog::&lt;span class=&quot;me2&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;const&lt;/span&gt; message::&lt;span class=&quot;me2&quot;&gt;Transaction&lt;/span&gt; &amp;amp;to_apply&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; uint8_t *buffer; &lt;span class=&quot;coMULTI&quot;&gt;/* Buffer we will write serialized header, &lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; message and trailing checksum to */&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; uint8_t *orig_buffer;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;kw4&quot;&gt;int&lt;/span&gt; error_code;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;kw4&quot;&gt;size_t&lt;/span&gt; message_byte_length= to_apply.&lt;span class=&quot;me1&quot;&gt;ByteSize&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; ssize_t written;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; off_t cur_offset;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;kw4&quot;&gt;size_t&lt;/span&gt; total_envelope_length= HEADER_TRAILER_BYTES + message_byte_length;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/* &lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160;* Attempt allocation of raw memory buffer for the header, &lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160;* message and trailing checksum bytes.&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160;*/&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; buffer= static_cast&amp;lt;uint8_t *&amp;gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw3&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;total_envelope_length&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;buffer == &lt;span class=&quot;kw2&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; errmsg_printf&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;ERRMSG_LVL_ERROR, &lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; _&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;Failed to allocate enough memory to buffer header, transaction message, and trailing checksum bytes. Tried to allocate %&amp;quot;&lt;/span&gt; PRId64&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;st0&quot;&gt;&amp;quot; bytes.&amp;#160; Error: %s&lt;span class=&quot;es0&quot;&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;, &lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; static_cast&amp;lt;int64_t&amp;gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;total_envelope_length&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;,&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw3&quot;&gt;strerror&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;errno&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; state= CRASHED;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; deactivate&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;kw1&quot;&gt;else&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; orig_buffer= buffer; &lt;span class=&quot;coMULTI&quot;&gt;/* We will free() orig_buffer, as buffer is moved during write */&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/*&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160;* Do an atomic increment on the offset of the log file position&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160;*/&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; cur_offset= log_offset.&lt;span class=&quot;me1&quot;&gt;fetch_and_add&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;static_cast&amp;lt;off_t&amp;gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;total_envelope_length&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/*&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160;* We adjust cur_offset back to the original log_offset before&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160;* the increment above...&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160;*/&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; cur_offset-= static_cast&amp;lt;off_t&amp;gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;total_envelope_length&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/*&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160;* Write the header information, which is the message type and&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160;* the length of the transaction message into the buffer&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160;*/&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; buffer= protobuf::&lt;span class=&quot;me2&quot;&gt;io&lt;/span&gt;::&lt;span class=&quot;me2&quot;&gt;CodedOutputStream&lt;/span&gt;::&lt;span class=&quot;me2&quot;&gt;WriteLittleEndian32ToArray&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;static_cast&amp;lt;uint32_t&amp;gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;ReplicationServices::&lt;span class=&quot;me2&quot;&gt;TRANSACTION&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;, buffer&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; buffer= protobuf::&lt;span class=&quot;me2&quot;&gt;io&lt;/span&gt;::&lt;span class=&quot;me2&quot;&gt;CodedOutputStream&lt;/span&gt;::&lt;span class=&quot;me2&quot;&gt;WriteLittleEndian32ToArray&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;static_cast&amp;lt;uint32_t&amp;gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;message_byte_length&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;, buffer&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/*&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160;* Now write the serialized transaction message, followed&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160;* by the optional checksum into the buffer.&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160;*/&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; buffer= to_apply.&lt;span class=&quot;me1&quot;&gt;SerializeWithCachedSizesToArray&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;buffer&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; uint32_t checksum= &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;do_checksum&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; checksum= drizzled::&lt;span class=&quot;me2&quot;&gt;hash&lt;/span&gt;::&lt;span class=&quot;me2&quot;&gt;crc32&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;reinterpret_cast&amp;lt;char *&amp;gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;buffer&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; - message_byte_length, message_byte_length&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/* We always write in network byte order */&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; buffer= protobuf::&lt;span class=&quot;me2&quot;&gt;io&lt;/span&gt;::&lt;span class=&quot;me2&quot;&gt;CodedOutputStream&lt;/span&gt;::&lt;span class=&quot;me2&quot;&gt;WriteLittleEndian32ToArray&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;checksum, buffer&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/* &lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160;* Quick safety...if an error occurs above in another writer, the log &lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160;* file will be in a crashed state.&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160;*/&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;unlikely&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;state == CRASHED&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/* &lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160; &amp;#160;* Reset the log's offset in case we want to produce a decent error message including&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160; &amp;#160;* the original offset where an error occurred.&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160; &amp;#160;*/&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; log_offset= cur_offset;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw3&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;orig_buffer&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/* Write the full buffer in one swoop */&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;kw1&quot;&gt;do&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; written= pwrite&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;log_file, orig_buffer, total_envelope_length, cur_offset&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;kw1&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;written == &lt;span class=&quot;nu0&quot;&gt;-1&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class=&quot;kw2&quot;&gt;errno&lt;/span&gt; == EINTR&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;; &lt;span class=&quot;coMULTI&quot;&gt;/* Just retry the write when interrupted by a signal... */&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;unlikely&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;written != static_cast&amp;lt;ssize_t&amp;gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;total_envelope_length&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; errmsg_printf&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;ERRMSG_LVL_ERROR, &lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; _&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;Failed to write full size of transaction.&amp;#160; Tried to write %&amp;quot;&lt;/span&gt; PRId64&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;st0&quot;&gt;&amp;quot; bytes at offset %&amp;quot;&lt;/span&gt; PRId64 &lt;span class=&quot;st0&quot;&gt;&amp;quot;, but only wrote %&amp;quot;&lt;/span&gt; PRId32 &lt;span class=&quot;st0&quot;&gt;&amp;quot; bytes.&amp;#160; Error: %s&lt;span class=&quot;es0&quot;&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;, &lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; static_cast&amp;lt;int64_t&amp;gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;total_envelope_length&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;,&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; static_cast&amp;lt;int64_t&amp;gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;cur_offset&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;,&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; static_cast&amp;lt;int64_t&amp;gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;written&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;, &lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw3&quot;&gt;strerror&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;errno&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; state= CRASHED;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/* &lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160; &amp;#160;* Reset the log's offset in case we want to produce a decent error message including&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160; &amp;#160;* the original offset where an error occurred.&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160; &amp;#160;*/&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; log_offset= cur_offset;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; deactivate&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;kw3&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;orig_buffer&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; error_code= my_sync&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;log_file, &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;unlikely&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;error_code != &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; errmsg_printf&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;ERRMSG_LVL_ERROR, &lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; _&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;Failed to sync log file. Got error: %s&lt;span class=&quot;es0&quot;&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;, &lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw3&quot;&gt;strerror&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;errno&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt; &lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2&gt;Reading the Transaction Log&lt;/h2&gt;
&lt;p&gt;
OK, so the above code shows how the transaction log is written.  What about reading the log file?  Well, it's pretty simple.  There is an example program in &lt;tt&gt;/drizzle/message/transaction_reader.cc&lt;/tt&gt; which has code showing how to do this.  Here's a snippet from that program:
&lt;/p&gt;
&lt;div class=&quot;syntax&quot;&gt;&lt;div class=&quot;cpp&quot; style=&quot;font-family: monospace;&quot;&gt;&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;int&lt;/span&gt; main&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;int&lt;/span&gt; argc, &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt;* argv&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;...&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;me1&quot;&gt;message&lt;/span&gt;::&lt;span class=&quot;me2&quot;&gt;Transaction&lt;/span&gt; transaction;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;kw4&quot;&gt;file&lt;/span&gt;= open&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;argv&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;, O_RDONLY&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;file&lt;/span&gt; == &lt;span class=&quot;nu0&quot;&gt;-1&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw3&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;stderr&lt;/span&gt;, _&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;Cannot open file: %s&lt;span class=&quot;es0&quot;&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;, argv&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;-1&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;...&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;me1&quot;&gt;protobuf&lt;/span&gt;::&lt;span class=&quot;me2&quot;&gt;io&lt;/span&gt;::&lt;span class=&quot;me2&quot;&gt;ZeroCopyInputStream&lt;/span&gt; *raw_input=&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw3&quot;&gt;new&lt;/span&gt; protobuf::&lt;span class=&quot;me2&quot;&gt;io&lt;/span&gt;::&lt;span class=&quot;me2&quot;&gt;FileInputStream&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; protobuf::&lt;span class=&quot;me2&quot;&gt;io&lt;/span&gt;::&lt;span class=&quot;me2&quot;&gt;CodedInputStream&lt;/span&gt; *coded_input=&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw3&quot;&gt;new&lt;/span&gt; protobuf::&lt;span class=&quot;me2&quot;&gt;io&lt;/span&gt;::&lt;span class=&quot;me2&quot;&gt;CodedInputStream&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;raw_input&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; *buffer= &lt;span class=&quot;kw2&quot;&gt;NULL&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; *temp_buffer= &lt;span class=&quot;kw2&quot;&gt;NULL&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; uint32_t length= &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; uint32_t previous_length= &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; uint32_t checksum= &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;kw4&quot;&gt;bool&lt;/span&gt; result= &lt;span class=&quot;kw2&quot;&gt;true&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; uint32_t message_type= &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/* Read in the length of the command */&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;kw1&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;result == &lt;span class=&quot;kw2&quot;&gt;true&lt;/span&gt; &amp;amp;&amp;amp; &lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160;coded_input-&amp;gt;ReadLittleEndian32&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&amp;amp;message_type&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; == &lt;span class=&quot;kw2&quot;&gt;true&lt;/span&gt; &amp;amp;&amp;amp;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160;coded_input-&amp;gt;ReadLittleEndian32&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&amp;amp;length&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; == &lt;span class=&quot;kw2&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;message_type != ReplicationServices::&lt;span class=&quot;me2&quot;&gt;TRANSACTION&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw3&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;stderr&lt;/span&gt;, _&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;Found a non-transaction message &amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;st0&quot;&gt;&amp;quot;in log.&amp;#160; Currently, not supported.&lt;span class=&quot;es0&quot;&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw3&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;length &amp;gt; &lt;span class=&quot;kw2&quot;&gt;INT_MAX&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw3&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;stderr&lt;/span&gt;, _&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;Attempted to read record bigger than INT_MAX&lt;span class=&quot;es0&quot;&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw3&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;buffer == &lt;span class=&quot;kw2&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/* &lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;* First time around...just malloc the length.&amp;#160; This block gets rid&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;* of a GCC warning about uninitialized temp_buffer.&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160;*/&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; temp_buffer= &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; *&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;kw3&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;static_cast&amp;lt;size_t&amp;gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;length&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/* No need to allocate if we have a buffer big enough... */&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;length &amp;gt; previous_length&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; temp_buffer= &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; *&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;kw3&quot;&gt;realloc&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;buffer, static_cast&amp;lt;size_t&amp;gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;length&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;temp_buffer == &lt;span class=&quot;kw2&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw3&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;stderr&lt;/span&gt;, _&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;Memory allocation failure trying to &amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;st0&quot;&gt;&amp;quot;allocate %&amp;quot;&lt;/span&gt; PRIu64 &lt;span class=&quot;st0&quot;&gt;&amp;quot; bytes.&lt;span class=&quot;es0&quot;&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;,&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; static_cast&amp;lt;uint64_t&amp;gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;length&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw2&quot;&gt;break&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;else&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; buffer= temp_buffer;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/* Read the Command */&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; result= coded_input-&amp;gt;ReadRaw&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;buffer, &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; length&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;result == &lt;span class=&quot;kw2&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw3&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;stderr&lt;/span&gt;, _&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;Could not read transaction message.&lt;span class=&quot;es0&quot;&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw3&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;stderr&lt;/span&gt;, _&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;GPB ERROR: %s.&lt;span class=&quot;es0&quot;&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;, &lt;span class=&quot;kw3&quot;&gt;strerror&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;errno&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw3&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;stderr&lt;/span&gt;, _&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;Raw buffer read: %s.&lt;span class=&quot;es0&quot;&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;, buffer&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw2&quot;&gt;break&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; result= transaction.&lt;span class=&quot;me1&quot;&gt;ParseFromArray&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;buffer, static_cast&amp;lt;int32_t&amp;gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;length&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;result == &lt;span class=&quot;kw2&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw3&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;stderr&lt;/span&gt;, _&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;Unable to parse command. Got error: %s.&lt;span class=&quot;es0&quot;&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;,&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; transaction.&lt;span class=&quot;me1&quot;&gt;InitializationErrorString&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;c_str&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;buffer != &lt;span class=&quot;kw2&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw3&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;stderr&lt;/span&gt;, _&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;BUFFER: %s&lt;span class=&quot;es0&quot;&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;, buffer&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw2&quot;&gt;break&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/* Print the transaction */&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; printTransaction&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;transaction&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/* Skip 4 byte checksum */&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; coded_input-&amp;gt;ReadLittleEndian32&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&amp;amp;checksum&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;do_checksum&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;checksum != drizzled::&lt;span class=&quot;me2&quot;&gt;hash&lt;/span&gt;::&lt;span class=&quot;me2&quot;&gt;crc32&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;buffer, static_cast&amp;lt;size_t&amp;gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;length&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw3&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;stderr&lt;/span&gt;, _&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;Checksum failed. Wanted %&amp;quot;&lt;/span&gt; PRIu32&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;st0&quot;&gt;&amp;quot; got %&amp;quot;&lt;/span&gt; PRIu32 &lt;span class=&quot;st0&quot;&gt;&amp;quot;&lt;span class=&quot;es0&quot;&gt;\n&lt;/span&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;,&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; checksum,&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; drizzled::&lt;span class=&quot;me2&quot;&gt;hash&lt;/span&gt;::&lt;span class=&quot;me2&quot;&gt;crc32&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;buffer, static_cast&amp;lt;size_t&amp;gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;length&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; previous_length= length;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;buffer&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw3&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;buffer&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;kw3&quot;&gt;delete&lt;/span&gt; coded_input;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;kw3&quot;&gt;delete&lt;/span&gt; raw_input;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;result == &lt;span class=&quot;kw2&quot;&gt;true&lt;/span&gt; ? &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt; : &lt;span class=&quot;nu0&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt; &lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2&gt;Shortcomings of the Transaction Log&lt;/h2&gt;
&lt;p&gt;
So far, we've generally focused on a scalable design for the transaction log and have not spent too much time on performance tuning the code &amp;mdash; and yes, performance != scalability.  There are a number of problems with the current code which we will address in future versions of the transaction log.  Namely:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reduce calls to &lt;tt&gt;malloc()&lt;/tt&gt;.  Currently, each write of a transaction message to the log file incurs a call to &lt;tt&gt;malloc()&lt;/tt&gt; to allocate enough memory to store the serialized log entry.  Clearly, this is not optimal.  We've considered a number of alternate approached to calling &lt;tt&gt;malloc()&lt;/tt&gt;, including having a scoreboard approach where a vector of memory slabs are used in a round-robin fashion.  This would introduce some locking, however.  Also, I've thought about using a hazard pointer list on the Session object to have previously-allocated memory on the Session object be used for something like this.  But, these ideas must be hashed out further.&lt;/li&gt;
&lt;li&gt;There is &lt;strong&gt;no index into the transaction log&lt;/strong&gt;.  This is not a problem for writing the transaction log, of course, but for readers of the transaction log.  I'm in the process of creating classes and a library for building indexes for a transaction log and, in addition, creating archived snapshots to enable log shipping for Drizzle replication.  I'll be pushing code for this to Launchpad later this week and will write a new article about log shipping and snapshot creation.&lt;/li&gt;
&lt;li&gt;Each call to &lt;tt&gt;apply()&lt;/tt&gt; calls &lt;tt&gt;fdatasync()/fsync()&lt;/tt&gt; on the transaction log.  Certain environments may consider this to be too strict a sync requirement, since the storage engine may already keep a transaction log file of its own that is also synced. For instance, InnoDB has a transaction log that, depending on the setting of InnoDB configuration variables, may call fdatasync() upon every transaction commit.  It would be best to have the syncing behaviour be user-adjustable &amp;mdash; for instance, a setting to allow the transaction log to be synced every X number of seconds...&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Summary and Request for Comments&lt;/h2&gt;
&lt;p&gt;
That's it for the discussion about the transaction log.  I'll post some more code examples from the replication plugins which utilize the transaction log in a later blog entry.
&lt;/p&gt;
&lt;p&gt;
What do you think of the design of the transaction log?  What would you change?  Comments are always welcome! Cheers. &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;
&lt;/p&gt;    </content:encoded>
                
    <pubDate>Tue, 27 Oct 2009 13:08:00 -0400</pubDate>
    <guid isPermaLink="false">http://jpipes.com/index.php?/archives/299-guid.html</guid>
    </item>
<item>
    <title>Drizzle Replication - Changes in API to support Group Commit</title>
    <link>http://jpipes.com/index.php?/archives/302-Drizzle-Replication-Changes-in-API-to-support-Group-Commit.html</link>
<category>MySQL</category><category>Drizzle</category><category>C/C++</category>    <comments>http://jpipes.com/index.php?/archives/302-Drizzle-Replication-Changes-in-API-to-support-Group-Commit.html#comments</comments>
    <wfw:comment>http://jpipes.com/wfwcomment.php?cid=302</wfw:comment>
    <slash:comments>5</slash:comments>
    <wfw:commentRss>http://jpipes.com/rss.php?version=2.0&amp;type=comments&amp;cid=302</wfw:commentRss>
    <author>nospam@example.com (Jay Pipes)</author>
    <content:encoded>
&lt;style type=&quot;text/css&quot;&gt;/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */
div.syntax
{
font-family: 'Courier New', Courier, monospace; 
background:white;
}

div.syntax a
{
font-family: 'Courier New', Courier, monospace; 
font-weight: normal;
color:black;
text-decoration:underline;
}

.cpp .de1, .cpp .de2 {font-family: 'Courier New', Courier, monospace; font-weight: normal;}
.cpp  {font-family: 'Courier New', Courier, monospace;}
.cpp .imp {font-weight: bold; color: red;font-family: 'Courier New', Courier, monospace;}
.cpp li {background: #ffffff;font-family: 'Courier New', Courier, monospace;}
.cpp li.li2 {background: #f8f8f8;font-family: 'Courier New', Courier, monospace;}
.cpp .kw1 {color: #0000ff;font-family: 'Courier New', Courier, monospace;}
.cpp .kw2 {color: #0000ff;font-family: 'Courier New', Courier, monospace;}
.cpp .kw3 {color: #0000dd;font-family: 'Courier New', Courier, monospace;}
.cpp .kw4 {color: #0000ff;font-family: 'Courier New', Courier, monospace;}
.cpp .co1 {color: #008800;font-family: 'Courier New', Courier, monospace;}
.cpp .co2 {color: #008800;font-family: 'Courier New', Courier, monospace;}
.cpp .coMULTI {color: #ff0000; font-style: italic;font-family: 'Courier New', Courier, monospace;}
.cpp .es0 {color: #666666; font-weight: bold;font-family: 'Courier New', Courier, monospace;}
.cpp .br0 {color: #000000;font-family: 'Courier New', Courier, monospace;}
.cpp .st0 {color: #666666;font-family: 'Courier New', Courier, monospace;}
.cpp .nu0 {color: #0000dd;font-family: 'Courier New', Courier, monospace;}
.cpp .me1 {color: #000000;font-family: 'Courier New', Courier, monospace;}
.cpp .me2 {color: #000000;font-family: 'Courier New', Courier, monospace; font-weight: normal;}
&lt;/style&gt;
&lt;p&gt;
Hi all.  It's been quite some time since &lt;a href=&quot;http://jpipes.com/index.php?/archives/300-Drizzle-Replication-The-CommandReplicator-and-CommandApplier-Plugin-API.html&quot;  title=&quot;Drizzle replication - Part II - CommandReplicator and CommandApplier&quot;&gt;my last article&lt;/a&gt; on the new replication system in &lt;a href=&quot;http://drizzle.org&quot;  title=&quot;Drizzle&quot;&gt;Drizzle&lt;/a&gt;.  My apologies for the delay in publishing the next article in the replication series.
&lt;/p&gt;
&lt;p&gt;
The delay has been due to a reworking of the replication system to fully support &quot;group commit&quot; behaviour and to support fully transactional replication.  The changes allow replicator and applier plugins to understand much more about the actual changes which occurred on the server, and to understand the transactional container properly.
&lt;/p&gt;
&lt;p&gt;
The goals of &lt;a href=&quot;http://drizzle.org&quot;  title=&quot;Drizzle&quot;&gt;Drizzle&lt;/a&gt;'s replication system are as follows:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make replication &lt;strong&gt;modular&lt;/strong&gt; and not dependent on one particular implementation&lt;/li&gt;
&lt;li&gt;Make it &lt;strong&gt;simple and fun to develop&lt;/strong&gt; plugins for Drizzle replication&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Encapsulate&lt;/strong&gt; all transmitted information in an efficient, portable, and standard format&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
This article serves to build on the last article and explain the changes to the Google Protobuffer message definitions used in the replication API.  The actual replication API described in the last article remains almost the same.  However, instead of being named CommandApplier and CommandReplicator, those plugin base classes are now named TransactionApplier and TransactionReplicator respectively.  And, instead of consuming a Command message, they consume Transaction messages.
&lt;/p&gt;
&lt;p&gt;
&lt;img src=&quot;img/transaction_message.png&quot; style=&quot;float: right; margin: 0px 0px 50px 50px;&quot;/&gt;
For my friend &lt;a href=&quot;http://www.linkedin.com/pub/edwin-desouza/7/1a4/385&quot;  title=&quot;Edwin DeSouza&quot;&gt;Edwin&lt;/a&gt;'s benefit, I'll be including lots of pretty graphics. &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;  For my developer readers, I'm including lots of example C++ code to help you best understand how to read and manipulate the Transaction and Statement messages in the new replication system.
&lt;/p&gt;
&lt;h2&gt;New Message Definitions&lt;/h2&gt;
&lt;p&gt;
As I mentioned above, the Command message &lt;a href=&quot;http://jpipes.com/index.php?/archives/298-Drizzle-Replication-The-Command-Message.html&quot;  title=&quot;Drizzle Replication - Command Message&quot;&gt;previously discussed in the first replication article&lt;/a&gt;, has been changed in favour of a more space-efficient and transactional message format.  The proto file is now called &lt;tt&gt;/drizzled/message/transaction.proto&lt;/tt&gt;.  You can look at the &lt;a href=&quot;http://bazaar.launchpad.net/~jaypipes/drizzle/replication-group-commit/annotate/head%3A/drizzled/message/transaction.proto&quot;  title=&quot;transaction.proto&quot;&gt;proto file online&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
The Command Message has become the Statement message, and a new Transaction message serves as a container for multiple Statement messages representing (for most cases) an &lt;strong&gt;atomic change in the state of the database server&lt;/strong&gt;.  I'll discuss later in the article those specific cases where a Transaction message's contents may contain only a partial atomic change to the server. 
&lt;/p&gt;
&lt;p&gt;
The image to the right depicts the Transaction message container.  As you can see, the Transaction message contains two things: a TransactionContext message and an array of one or more Statement messages.
&lt;/p&gt;
&lt;h2&gt;The TransactionContext Message&lt;/h2&gt;
&lt;p&gt;
Each Transaction message contains a single TransactionContext message.  The TransactionContext message contains information about the entire transaction.  The data members of the TransactionContext are as follows:
&lt;/p&gt;
&lt;img src=&quot;img/transaction_context_message.png&quot; style=&quot;float: left; margin: 0px 50px 50px 0px;&quot; /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;tt&gt;server_id&lt;/tt&gt; - (uint32_t) A numeric identifier for the server which executed this transaction&lt;/li&gt;
&lt;li&gt;&lt;tt&gt;transaction_id&lt;/tt&gt; - (uint64_t) A globally-unique transaction identifier&lt;/li&gt;
&lt;li&gt;&lt;tt&gt;start_timestamp&lt;/tt&gt; - (uint64_t) A nano-second precision timestamp of when the transaction began.&lt;/li&gt;
&lt;li&gt;&lt;tt&gt;end_timestamp&lt;/tt&gt; - (uint64_t) A nano-second precision timestamp of when the transaction completed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Since TransactionContext is simply a &lt;a href=&quot;http://code.google.com/apis/protocolbuffers/docs/overview.html&quot;  title=&quot;Google Protobuffers&quot;&gt;Google Protobuffer&lt;/a&gt; &lt;a href=&quot;http://code.google.com/apis/protocolbuffers/docs/reference/cpp/google.protobuf.message.html&quot;  title=&quot;Google Protobuffer Message class&quot;&gt;message&lt;/a&gt;, accessing data members is simple and straightforward.  If you're writing a replicator or applier, a reference to a const Transaction message will be supplied to you via the standard API.  For instance, let's assume we're writing a replicator and we want to filter all messages that are from the server with a server_id of 100.  Kind of a silly example, but nevertheless, it allows us to see some example code.
&lt;/p&gt;
&lt;p&gt;
As you may remember, the API for a replicator is dirt simple.  There is a &lt;tt&gt;replicate()&lt;/tt&gt; pure virtual method which accepts two parameters, the GPB message and a reference to the Applier which will &quot;apply&quot; the message to some target.  The new function signature is the same as the last one, with the term &quot;Command&quot; replaced with the term &quot;Transaction&quot;:
&lt;/p&gt;
&lt;div class=&quot;syntax&quot;&gt;&lt;div class=&quot;cpp&quot; style=&quot;font-family: monospace;&quot;&gt;&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;kw2&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;void&lt;/span&gt; replicate&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;TransactionApplier *in_applier, &lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;message::&lt;span class=&quot;me2&quot;&gt;Transaction&lt;/span&gt; &amp;amp;to_replicate&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;= &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;; &lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;
Suppose our replicator class is called MyReplicator.  Here is how to query the transaction context of the Transaction message and filter out transactions coming from server #100. &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;
&lt;/p&gt;
&lt;div class=&quot;syntax&quot;&gt;&lt;div class=&quot;cpp&quot; style=&quot;font-family: monospace;&quot;&gt;&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;void&lt;/span&gt; MyReplicator::&lt;span class=&quot;me2&quot;&gt;replicate&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;TransactionApplier *in_applier, &lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; message::&lt;span class=&quot;me2&quot;&gt;Transaction&lt;/span&gt; &amp;amp;to_replicate&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;kw4&quot;&gt;const&lt;/span&gt; message::&lt;span class=&quot;me2&quot;&gt;TransactionContext&lt;/span&gt; &amp;amp;ctx= to_replicate.&lt;span class=&quot;me1&quot;&gt;transaction_context&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;ctx.&lt;span class=&quot;me1&quot;&gt;server_id&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; != &lt;span class=&quot;nu0&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; in_applier-&amp;gt;apply&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;to_replicate&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt; &lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;
See? Pretty darn simple. &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;  OK, on to the Statement message, which is slightly more complicated.
&lt;/p&gt;
&lt;h2&gt;The Statement Message&lt;/h2&gt;
&lt;p&gt;
As noted above, the Transaction message contains an array of Statement messages.  In Protobuffer terminology, the Transaction message contains a &quot;repeated&quot; Statement data member.  The Statement message is an envelope containing the following information:
&lt;/p&gt;
&lt;img src=&quot;img/statement_message.png&quot; style=&quot;float: right; margin: 0px 0px 50px 50px;&quot;/&gt;
&lt;ul&gt;
&lt;li&gt;&lt;tt&gt;type&lt;/tt&gt; - (enum Type) The type of Statement this message represents.  Currently, the possible values of the type are as follows:
&lt;ul&gt;
&lt;li&gt;ROLLBACK&lt;/li&gt;
&lt;li&gt;INSERT&lt;/li&gt;
&lt;li&gt;UPDATE&lt;/li&gt;
&lt;li&gt;DELETE&lt;/li&gt;
&lt;li&gt;TRUNCATE_TABLE&lt;/li&gt;
&lt;li&gt;CREATE_SCHEMA&lt;/li&gt;
&lt;li&gt;ALTER_SCHEMA&lt;/li&gt;
&lt;li&gt;DROP_SCHEMA&lt;/li&gt;
&lt;li&gt;CREATE_TABLE&lt;/li&gt;
&lt;li&gt;ALTER_TABLE&lt;/li&gt;
&lt;li&gt;DROP_TABLE&lt;/li&gt;
&lt;li&gt;SET_VARIABLE&lt;/li&gt;
&lt;li&gt;RAW_SQL&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;tt&gt;start_timestamp&lt;/tt&gt; - (uint64_t) A nano-second precision timestamp of when the statement began.&lt;/li&gt;
&lt;li&gt;&lt;tt&gt;end_timestamp&lt;/tt&gt; - (uint64_t) A nano-second precision timestamp of when the statement completed.&lt;/li&gt;
&lt;li&gt;&lt;tt&gt;sql&lt;/tt&gt; - (string) Optionally stores the exact original SQL string producing this message.&lt;/li&gt;
&lt;li&gt;For certain types of Statement messages, there will also be a specialized header and data message (see below).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
To access the Statement messages in a Transaction, use something like the following code, which loops over the Transaction message's vector of Statement messages:
&lt;/p&gt;
&lt;div class=&quot;syntax&quot;&gt;&lt;div class=&quot;cpp&quot; style=&quot;font-family: monospace;&quot;&gt;&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;void&lt;/span&gt; MyReplicator::&lt;span class=&quot;me2&quot;&gt;replicate&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;TransactionApplier *in_applier, &lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; message::&lt;span class=&quot;me2&quot;&gt;Transaction&lt;/span&gt; &amp;amp;to_replicate&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;...&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;/* Grab the number of statements in the Transaction message */&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;size_t&lt;/span&gt; x;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;size_t&lt;/span&gt; num_statements= to_replicate.&lt;span class=&quot;me1&quot;&gt;statement_size&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;coMULTI&quot;&gt;/* Do something with each statement... */&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;kw1&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;x= &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;; x &amp;lt; num_statements; ++x&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;kw4&quot;&gt;const&lt;/span&gt; message::&lt;span class=&quot;me2&quot;&gt;Statement&lt;/span&gt; &amp;amp;stmt= to_replicate.&lt;span class=&quot;me1&quot;&gt;statement&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;x&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/* processStatement() does something with the statement... */&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; processStatement&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;stmt&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;...&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt; &lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2&gt;Serialized Polymorphism with the &lt;tt&gt;type&lt;/tt&gt; Member&lt;/h2&gt;
&lt;p&gt;
The &lt;tt&gt;type&lt;/tt&gt; data member is of critical importance to the Statement message, as it allows us to have a sort of polymorphism serialized within the Statement message itself.  This polymorphism allows the generic Statement message to contain specialized submessages depending on what type of event occurred on the server.
&lt;/p&gt;
&lt;p&gt;
The above paragraph probably sounds overly complicated, but in reality things are pretty simple.  As usual, it's easiest to see what's going on by looking at an example in code.  For our example, let's build out our fictional &lt;tt&gt;processStatement()&lt;/tt&gt; method from the snippet above.
&lt;/p&gt;
&lt;p&gt;
The &lt;tt&gt;processStatement()&lt;/tt&gt; method is basically a giant switch statement, switching off of the supplied Statement message parameter's &lt;tt&gt;type&lt;/tt&gt; data member property.  Here is the outline of the &lt;tt&gt;processStatement()&lt;/tt&gt; method, with only our switch statement and some comments visible which should give you an idea of how we deal with specific types of Statements:
&lt;/p&gt;
&lt;div class=&quot;syntax&quot;&gt;&lt;div class=&quot;cpp&quot; style=&quot;font-family: monospace;&quot;&gt;&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;void&lt;/span&gt; processStatement&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;const&lt;/span&gt; message::&lt;span class=&quot;me2&quot;&gt;Statement&lt;/span&gt; &amp;amp;stmt&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;kw1&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;stmt.&lt;span class=&quot;me1&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;kw1&quot;&gt;case&lt;/span&gt; message::&lt;span class=&quot;me2&quot;&gt;Statement&lt;/span&gt;::&lt;span class=&quot;me2&quot;&gt;INSERT&lt;/span&gt;:&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/* Handle statements which insert new data... */&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw2&quot;&gt;break&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;kw1&quot;&gt;case&lt;/span&gt; message::&lt;span class=&quot;me2&quot;&gt;Statement&lt;/span&gt;::&lt;span class=&quot;me2&quot;&gt;UPDATE&lt;/span&gt;:&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/* Handle statements which update existing data... */&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw2&quot;&gt;break&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;kw1&quot;&gt;case&lt;/span&gt; message::&lt;span class=&quot;me2&quot;&gt;Statement&lt;/span&gt;::&lt;span class=&quot;kw3&quot;&gt;DELETE&lt;/span&gt;:&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/* Handle statements which delete existing data... */&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw2&quot;&gt;break&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; ...&amp;#160; &amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt; &lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;
&lt;img src=&quot;img/insert_header_message.png&quot; style=&quot;float: right; margin: 0px 0px 0px 100px;&quot;/&gt;
&lt;img src=&quot;img/insert_data_message.png&quot; style=&quot;float: right; margin: 0px 0px 40px 100px;&quot;/&gt;
Let's go ahead and &quot;fill out&quot; one of the case blocks in the switch statement above.  We will handle the case where the Statement &lt;tt&gt;type&lt;/tt&gt; is &lt;/tt&gt;INSERT&lt;/tt&gt;.  Note that this &lt;strong&gt;does not necessarily mean a &lt;em&gt;SQL&lt;/em&gt; INSERT statement was executed&lt;/strong&gt;.  All this means is that an SQL statement was executed which resulted in a new record being added to a table on the server.  This means that the actual SQL statement could have been any of INSERT, INSERT ... SELECT, REPLACE INTO, or LOAD DATA INFILE.
&lt;/p&gt;
&lt;p&gt;
The &lt;tt&gt;/drizzled/message/transaction.proto&lt;/tt&gt; file will always contain lots of documentation explaining how each of the specific submessages in the Statement message class are handled.  To the right is a graphic depicting the &lt;tt&gt;InsertHeader&lt;/tt&gt; and &lt;tt&gt;InsertData&lt;/tt&gt; message classes which compose the &quot;meat&quot; of Statements that inserted new records into the database.  Whenever the Statement message's &lt;tt&gt;type&lt;/tt&gt; is &lt;tt&gt;INSERT&lt;/tt&gt;, the Statement message will contain two submessages, one called &lt;tt&gt;insert_header&lt;/tt&gt; and another called &lt;tt&gt;insert_data&lt;/tt&gt; which will be populated with the &lt;tt&gt;InsertHeader&lt;/tt&gt; and &lt;tt&gt;InsertData&lt;/tt&gt; messages.  The header message will contain information about the table and fields affected, while the data message will contain the values to be inserted into the table.
&lt;/p&gt;
&lt;p&gt;
Here is some example code which queries the header and data messages and constructs an SQL string from them:
&lt;/p&gt;
&lt;div class=&quot;syntax&quot;&gt;&lt;div class=&quot;cpp&quot; style=&quot;font-family: monospace;&quot;&gt;&lt;ol&gt;&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;void&lt;/span&gt; processStatement&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;const&lt;/span&gt; message::&lt;span class=&quot;me2&quot;&gt;Statement&lt;/span&gt; &amp;amp;stmt&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;kw1&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;stmt.&lt;span class=&quot;me1&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;span class=&quot;kw1&quot;&gt;case&lt;/span&gt; message::&lt;span class=&quot;me2&quot;&gt;Statement&lt;/span&gt;::&lt;span class=&quot;me2&quot;&gt;INSERT&lt;/span&gt;:&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/* Handle statements which insert new data... */&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw4&quot;&gt;const&lt;/span&gt; message::&lt;span class=&quot;me2&quot;&gt;InsertHeader&lt;/span&gt; &amp;amp;header= stmt.&lt;span class=&quot;me1&quot;&gt;insert_header&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw4&quot;&gt;const&lt;/span&gt; message::&lt;span class=&quot;me2&quot;&gt;InsertData&lt;/span&gt; &amp;amp;data= stmt.&lt;span class=&quot;me1&quot;&gt;insert_data&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; string destination;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; quoted_identifier= &lt;span class=&quot;st0&quot;&gt;'`'&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; destination-&amp;gt;assign&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;INSERT INTO &amp;quot;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; destination-&amp;gt;push_back&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;quoted_identifier&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; destination-&amp;gt;append&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;header.&lt;span class=&quot;me1&quot;&gt;table_metadata&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;schema_name&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; destination-&amp;gt;push_back&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;quoted_identifier&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; destination-&amp;gt;push_back&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;'.'&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; destination-&amp;gt;push_back&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;quoted_identifier&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; destination-&amp;gt;append&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;header.&lt;span class=&quot;me1&quot;&gt;table_metadata&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;table_name&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; destination-&amp;gt;push_back&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;quoted_identifier&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; destination-&amp;gt;append&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot; (&amp;quot;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/* Add field list to SQL string... */&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw4&quot;&gt;size_t&lt;/span&gt; num_fields= header.&lt;span class=&quot;me1&quot;&gt;field_metadata_size&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw4&quot;&gt;size_t&lt;/span&gt; x;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;x= &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;; x &amp;lt; num_fields; ++x&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw4&quot;&gt;const&lt;/span&gt; message::&lt;span class=&quot;me2&quot;&gt;FieldMetadata&lt;/span&gt; &amp;amp;field_metadata= header.&lt;span class=&quot;me1&quot;&gt;field_metadata&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;x&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;x != &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; destination-&amp;gt;push_back&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;','&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; destination-&amp;gt;push_back&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;quoted_identifier&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; destination-&amp;gt;append&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;field_metadata.&lt;span class=&quot;me1&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; destination-&amp;gt;push_back&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;quoted_identifier&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; destination-&amp;gt;append&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;) VALUES (&amp;quot;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;coMULTI&quot;&gt;/* Add insert values */&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw4&quot;&gt;size_t&lt;/span&gt; num_records= data.&lt;span class=&quot;me1&quot;&gt;record_size&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw4&quot;&gt;size_t&lt;/span&gt; y;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;x= &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;; x &amp;lt; num_records; ++x&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;x != &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; destination-&amp;gt;append&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;),(&amp;quot;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;y= &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;; y &amp;lt; num_fields; ++y&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;y != &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; destination-&amp;gt;push_back&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;','&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; destination-&amp;gt;push_back&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;'&lt;span class=&quot;es0&quot;&gt;\'&lt;/span&gt;'&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; destination-&amp;gt;append&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;data.&lt;span class=&quot;me1&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;x&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;insert_value&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;y&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; destination-&amp;gt;push_back&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;'&lt;span class=&quot;es0&quot;&gt;\'&lt;/span&gt;'&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; destination-&amp;gt;push_back&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;')'&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;

&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw2&quot;&gt;break&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&amp;#160; ...&amp;#160; &amp;#160;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;&lt;div class=&quot;de2&quot;&gt;&amp;#160; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class=&quot;li1&quot;&gt;&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt; &lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;
The example code above is far from production-ready, of course.  I don't take into account different field types, instead simply enclosing everything in single quotes.  Also, I don't handle errors or escaping strings.  The point isn't to be perfect, but to show you the general way to get information out of the Statement message...
&lt;/p&gt;
&lt;h2&gt;Partial Atomic Transactions&lt;/h2&gt;
&lt;p&gt;
Above, I stated that the Transaction messages sent to Replicators and Appliers represent an atomic change to the state of a server.  This is true, most of the time. &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;  There are specific situations when a Transaction message will not represent an atomic change, and you should be aware of these scenarios if you plan to write plugins which implement a replication scheme.
&lt;/p&gt;
&lt;p&gt;
There are times when it is simply inefficient or impossible to create a Transaction message that represents the actual atomic change on a server.  For instance, imagine a table having 100 million records.  Now, imagine issuing an &lt;tt&gt;UPDATE&lt;/tt&gt; against that table that potentially affected every row in the table.
&lt;/p&gt;
&lt;p&gt;
In order to transmit to replicas the atomic change to the server, one gigantic Transaction message would need to be constructed on the master server.  Not only is there a distinct chance that the master would run out of memory constructing such a large message object, but it's safe to say that the master server would suffer from performance degradation during this construction.  There must, therefore, be a way to start streaming the changes made to the master server before the actual final commit has happened on the master.
&lt;/p&gt;
&lt;p&gt;
You may have noticed two data members of the &lt;tt&gt;InsertData&lt;/tt&gt; message above named &lt;tt&gt;segment_id&lt;/tt&gt; and &lt;tt&gt;end_segment&lt;/tt&gt;.  The first is of type &lt;tt&gt;uint32_t&lt;/tt&gt; and the second is a &lt;tt&gt;bool&lt;/tt&gt;.  Together, these two data members fulfill the need to transmit transaction messages that are part of a &lt;em&gt;&lt;strong&gt;bulk data modification&lt;/strong&gt;&lt;/em&gt;.  When a reader of a Transaction message sees that the end_segment data member is false, then the reader knows that another data segment will follow the current data message and will contain more inserts, updates, or deletes for the current transaction.
&lt;/p&gt;
&lt;h2&gt;Summary and Request for Comments&lt;/h2&gt;
&lt;p&gt;
Hopefully, I've explained the changes that have been made to Drizzle's replication system well enough above, but I understand the changes to the message definitions are substantial and am available at any time to discuss the changes and assist people with their code.  You can find me on IRC, Freenode's #drizzle channel, via the &lt;a href=&quot;https://lists.launchpad.net/drizzle-discuss/&quot;  title=&quot;drizzle-discuss&quot;&gt;Drizzle discussion mailing list&lt;/a&gt;, or via email joinfu@sun.com.  I very much welcome comments.  The new replication system is just finishing up the valgrind regression tests and should hit trunk later today.
&lt;/p&gt;
&lt;p&gt;
The next article covers the new Transaction Log, which is a serialized log of the Transaction messages used in the replication system.
&lt;/p&gt;    </content:encoded>
                
    <pubDate>Tue, 27 Oct 2009 11:00:00 -0400</pubDate>
    <guid isPermaLink="false">http://jpipes.com/index.php?/archives/302-guid.html</guid>
    </item>
<item>
    <title>Yet Another Post on REPLACE</title>
    <link>http://jpipes.com/index.php?/archives/305-Yet-Another-Post-on-REPLACE.html</link>
<category>MySQL</category><category>Drizzle</category><category>C/C++</category>    <comments>http://jpipes.com/index.php?/archives/305-Yet-Another-Post-on-REPLACE.html#comments</comments>
    <wfw:comment>http://jpipes.com/wfwcomment.php?cid=305</wfw:comment>
    <slash:comments>2</slash:comments>
    <wfw:commentRss>http://jpipes.com/rss.php?version=2.0&amp;type=comments&amp;cid=305</wfw:commentRss>
    <author>nospam@example.com (Jay Pipes)</author>
    <content:encoded>
&lt;p&gt;
Sometimes, as Sergei &lt;a href=&quot;http://jpipes.com/index.php?/archives/303-The-Deal-with-REPLACE-..-Or-Is-It-UPDATE.html#c189236&quot; &gt;rightly mentioned&lt;/a&gt;, I can be, well, &quot;righteously indignant&quot; about what I perceive to be a hack.
&lt;/p&gt;
&lt;p&gt;
In this case, after Sergei repeatedly tried to set me straight about what was going on &quot;under the covers&quot; during a &lt;tt&gt;REPLACE&lt;/tt&gt; operation, I was still arguing that he was incorrect.
&lt;/p&gt;
&lt;p&gt;
Doh.
&lt;/p&gt;
&lt;p&gt;
I then realized that &lt;a href=&quot;http://jpipes.com/index.php?/archives/301-Pop-Quiz-What-Does-REPLACE-Do.html#c189128&quot; &gt;Sarah Sproenhle's original comment&lt;/a&gt; about my test table not having a primary key was the reason that I was seeing the behaviour that I had been seeing.
&lt;/p&gt;
&lt;p&gt;
My original test case was failing, expecting to see a &lt;tt&gt;DELETE&lt;/tt&gt; + an &lt;tt&gt;INSERT&lt;/tt&gt;, when a &lt;tt&gt;REPLACE INTO&lt;/tt&gt; was issued against a table.  When I placed the PRIMARY KEY on the table in my test case and re-ran the test case, it still failed because the DELETE still was not in the transaction log.  Well, it turns out that the reason was because &lt;tt&gt;ha_update_row()&lt;/tt&gt; was actually called and not &lt;tt&gt;ha_delete_row()&lt;/tt&gt; + &lt;tt&gt;ha_write_row()&lt;/tt&gt;.  And, because of the documentation for the &lt;tt&gt;REPLACE&lt;/tt&gt; command, I wasn't checking that &lt;tt&gt;ha_update_row()&lt;/tt&gt; may have been called &amp;mdash; since I didn't realize a &lt;tt&gt;REPLACE&lt;/tt&gt; could actually do an &lt;tt&gt;UPDATE&lt;/tt&gt;.
&lt;/p&gt;
&lt;p&gt;
Anyway, I wanted to post to say that most of this whole &lt;a href=&quot;http://www.urbandictionary.com/define.php?term=kerfuffle&quot;  title=&quot;Kerfuffle&quot;&gt;kerfuffle&lt;/a&gt; was my fault.  Though I think that both the online and code documentation should reflect the fact that a REPLACE can do an UPDATE, the source of the failure was not what I originally wrote.  In contrast, ha_write_row() does indeed return ER_FOUND_DUPP_KEY appropriately during a REPLACE call.
&lt;/p&gt;
&lt;p&gt;
Mmmmm, that piece of humble pie was delicious.
&lt;/p&gt;    </content:encoded>
                
    <pubDate>Fri, 23 Oct 2009 11:11:13 -0400</pubDate>
    <guid isPermaLink="false">http://jpipes.com/index.php?/archives/305-guid.html</guid>
    </item>
<item>
    <title>The Deal with REPLACE .. Or Is It UPDATE?</title>
    <link>http://jpipes.com/index.php?/archives/303-The-Deal-with-REPLACE-..-Or-Is-It-UPDATE.html</link>
<category>MySQL</category><category>Drizzle</category><category>C/C++</category>    <comments>http://jpipes.com/index.php?/archives/303-The-Deal-with-REPLACE-..-Or-Is-It-UPDATE.html#comments</comments>
    <wfw:comment>http://jpipes.com/wfwcomment.php?cid=303</wfw:comment>
    <slash:comments>7</slash:comments>
    <wfw:commentRss>http://jpipes.com/rss.php?version=2.0&amp;type=comments&amp;cid=303</wfw:commentRss>
    <author>nospam@example.com (Jay Pipes)</author>
    <content:encoded>
&lt;p&gt;
Yesterday, I &lt;a href=&quot;http://jpipes.com/index.php?url=archives/301-Pop-Quiz-What-Does-REPLACE-Do.html&quot;  title=&quot;What does REPLACE do?&quot;&gt;posed a question&lt;/a&gt; to the ZanyWeb about what exactly a &lt;tt&gt;REPLACE&lt;/tt&gt; statement does &lt;em&gt;behind the scenes in the storage engine&lt;/em&gt;.  There were many excellent comments and these comments exposed some misunderstandings (including some of my own misconceptions) about the &lt;tt&gt;REPLACE&lt;/tt&gt; statement itself and what goes on behind the scenes in the storage engine.
&lt;/p&gt;
&lt;p&gt;
The question I asked was this: if I execute the following statements in a client, what would you expect would happen &lt;strong&gt;behind the scenes in the storage engine&lt;/strong&gt;? 
&lt;/p&gt;
&lt;pre&gt;
CREATE TABLE t1 (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, padding VARCHAR(200) NOT NULL
);

INSERT INTO t1 VALUES (1, &quot;I love testing.&quot;);
INSERT INTO t1 VALUES (2, &quot;I hate testing.&quot;);

REPLACE INTO t1 VALUE (2, &quot;I love testing.&quot;);
&lt;/pre&gt;
&lt;p&gt;
Based purely on the manual, one would &lt;em&gt;expect&lt;/em&gt;, as &lt;a href=&quot;http://hideandsql.com/&quot;  title=&quot;Ryan Thiessen&quot;&gt;Ryan Thiessen&lt;/a&gt; expressed in his &lt;a href=&quot;http://jpipes.com/index.php?url=archives/301-Pop-Quiz-What-Does-REPLACE-Do.html&amp;serendipity[csuccess]=true#c189136&quot; &gt;comment&lt;/a&gt;
&lt;/p&gt;
&lt;blockquote&gt;
try to insert once, detect a failure and then delete/insert in failure case.
&lt;/blockquote&gt;
&lt;p&gt;
or, as Ryan put it in pseudo-code:
&lt;/p&gt;
&lt;pre&gt;
INSERT INTO t1 VALUES (1, &quot;I love testing.&quot;);
INSERT INTO t1 VALUES (2, &quot;I hate testing.&quot;);
INSERT INTO t1 VALUE (2, &quot;I love testing.&quot;);
if error() { DELETE FROM t1 WHERE id = 2; INSERT INTO t1 VALUE (2, &quot;I love testing.&quot;); }
&lt;/pre&gt;
&lt;p&gt;
Unfortunately, this is not the case.  At least, it is not &lt;em&gt;always&lt;/em&gt; the case.
&lt;/p&gt;
&lt;h2&gt;&lt;tt&gt;ha_write_row()&lt;/tt&gt; vs. &lt;tt&gt;ha_update_row()&lt;/tt&gt;&lt;/h2&gt;
&lt;p&gt;
In MySQL, as well as in Drizzle, there is a pluggable storage engine API.  This API consists primarily of two classes: In MySQL, one class is called &lt;tt&gt;handlerton&lt;/tt&gt; and the other is called &lt;tt&gt;handler&lt;/tt&gt; &amp;mdash; in Drizzle, these classes are called &lt;tt&gt;StorageEngine&lt;/tt&gt; and &lt;tt&gt;Cursor&lt;/tt&gt; (&lt;strong&gt;Cur&lt;/strong&gt;rent &lt;strong&gt;S&lt;/strong&gt;et &lt;strong&gt;O&lt;/strong&gt;f &lt;strong&gt;R&lt;/strong&gt;ecords), because that is what they actually represent.
&lt;/p&gt;
&lt;p&gt;
Without going into too many details, the Cursor (handler) interface has four calls which are relevant to this discussion:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;tt&gt;int Cursor::ha_write_row(unsigned char *new_record)&lt;/tt&gt; &amp;mdash; inserts a new record into the table pointed to by the Cursor&lt;/li&gt;
&lt;li&gt;&lt;tt&gt;int Cursor::ha_update_row(unsigned char *old_record, unsigned char *new_record)&lt;/tt&gt; &amp;mdash; update an existing record in the table pointed to by the Cursor&lt;/li&gt;
&lt;li&gt;&lt;tt&gt;int Cursor::ha_delete_row(unsigned char *old_record)&lt;/tt&gt; &amp;mdash; delete an existing record in the table pointed to by the Cursor&lt;/li&gt;
&lt;li&gt;&lt;tt&gt;virtual int Cursor::extra(ha_extra_function operation)&lt;/tt&gt; &amp;mdash; indicates to the Cursor that it should handle an operation in a certain way.  If this sounds vague to you, it is, so read on...&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;OK, So What &lt;em&gt;Does&lt;/em&gt; Happen?&lt;/h2&gt;
&lt;p&gt;
What &lt;em&gt;actually&lt;/em&gt; happens behind the scenes for the code above is the following &quot;optimized&quot; execution path, again in pseudo-code:
&lt;/p&gt;
&lt;pre&gt;
&lt;span style=&quot;color: green;&quot;&gt;// &lt;b&gt;(0)&lt;/b&gt; Enter mysql_insert() and prepare to do an INSERT&lt;/span&gt;
mysql_insert();

&lt;span style=&quot;color: green;&quot;&gt;// &lt;b&gt;(1)&lt;/b&gt; tell engine that a write can replace an existing record&lt;/span&gt;
Cursor::extra(HA_EXTRA_WRITE_CAN_REPLACE);

&lt;span style=&quot;color: green;&quot;&gt;// &lt;b&gt;(2)&lt;/b&gt; tell engine to ignore duplicate keys&lt;/span&gt;
Cursor::extra(HA_EXTRA_IGNORE_DUP_KEY);

&lt;span style=&quot;color: green;&quot;&gt;// &lt;b&gt;(3)&lt;/b&gt; For each record to be inserted...&lt;/span&gt;
for each record begin:

  &lt;span style=&quot;color: green;&quot;&gt;// &lt;b&gt;(4)&lt;/b&gt; Insert the record by calling ha_write_row()&lt;/span&gt;
  Cursor::ha_write_row();

  &lt;span style=&quot;color: green;&quot;&gt;// &lt;b&gt;(5)&lt;/b&gt; Cursor tries to &quot;insert&quot; the record&lt;/span&gt;
  error= Cursor::write_row();

  &lt;span style=&quot;color: green;&quot;&gt;// &lt;b&gt;(6)&lt;/b&gt; If the write fails, then DELETE, the record and try to INSERT again.&lt;/span&gt;
  if error is true:

    Cursor::ha_delete_row();
    Cursor::ha_write_row();
&lt;/pre&gt;
&lt;p&gt;
The above code looks very similar to what Ryan has already said he expected the underlying code to look like, no?  The problem is the calls to &lt;tt&gt;Cursor::extra()&lt;/tt&gt; (steps 1 and 2) and what happens inside InnoDB (step 5) when &lt;tt&gt;Cursor::write_row()&lt;/tt&gt; is called.
&lt;/p&gt;
&lt;p&gt;
InnoDB tries to insert the record and realizes that the new record violates an existing primary key value &lt;strong&gt;but since MySQL has already told it to ignore duplicate key violations, InnoDB updates the existing row and &lt;em&gt;returns successfully from write_row()&lt;/em&gt;!&lt;/strong&gt;.
&lt;/p&gt;
&lt;p&gt;
Unfortunately, because of this &quot;optimization&quot;, &lt;tt&gt;Cursor::ha_write_row()&lt;/tt&gt;, which is the kernel's wrapper around the virtualized storage engine's &lt;tt&gt;Cursor::write_row&lt;/tt&gt; call is &lt;em&gt;completely unaware that an &lt;tt&gt;UPDATE&lt;/tt&gt; and not an &lt;tt&gt;INSERT&lt;/tt&gt; has occurred&lt;/em&gt;.  Why is this a problem?  Well, what happens after a call to &lt;tt&gt;Cursor::write_row()&lt;/tt&gt; succeeds?  That's correct: post-change logging occurs.  In other words, &lt;strong&gt;logging for row-based replication occurs&lt;/strong&gt;.  Well, &lt;tt&gt;Cursor::ha_write_row()&lt;/tt&gt; then logs an &lt;em&gt;&lt;tt&gt;INSERT&lt;/tt&gt;&lt;/em&gt; and not the appropriate &lt;em&gt;&lt;tt&gt;UPDATE&lt;/tt&gt;&lt;/em&gt;.  Oops.
&lt;/p&gt;
&lt;p&gt;
There are three major things to note about the above logic:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;This is undocumented behaviour.  According to the manual, a &lt;tt&gt;REPLACE&lt;/tt&gt; statement works like an &lt;tt&gt;INSERT&lt;/tt&gt;, except if a primary or unique key is violated, the original row is &lt;tt&gt;DELETE&lt;/tt&gt;d and the new row is &lt;tt&gt;INSERT&lt;/tt&gt;ed.&lt;/li&gt;
&lt;li&gt;This breaks the defined public Cursor (known as handler in MySQL) interface for ha_write_row() since &lt;strong&gt;rows may be updated when ha_update_row() is NOT called&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The code has &lt;strong&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Side_effect_(computer_science)&quot;  title=&quot;Code Side Effects&quot;&gt;side effects&lt;/a&gt;&lt;/strong&gt;, namely that the change to the state of the server is unknown to the Cursor: an update occurred but the Cursor believes an insert occurred.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;When Optimizations Aren't&lt;/h2&gt;
&lt;p&gt;
This kind of coding can be argued to be an &quot;optimization&quot;.  I will argue that it is not an optimization, but is overly clever and reduces the clarity of the code thereby making the code unnecessarily difficult to trace and follow.  Personally, I wasted days of research time trying to understand how a call to ha_write_row() was actually &lt;strong&gt;updating&lt;/strong&gt; an existing record.
&lt;/p&gt;
&lt;p&gt;
In my opinion,  a proper optimization would be to:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make the internal code function exactly as the documentation says it does.&lt;/li&gt;
&lt;li&gt;Adapt the documentation for &lt;tt&gt;REPLACE&lt;/tt&gt; and state that REPLACE is not as efficient as &lt;tt&gt;INSERT .. ON DUPLICATE KEY UPDATE&lt;/tt&gt; and whenever possible, prefer the latter statement over the former.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Does &lt;tt&gt;REPLACE&lt;/tt&gt; belong in Drizzle?&lt;/h2&gt;
&lt;p&gt;
One of the reasons that &lt;tt&gt;REPLACE&lt;/tt&gt; may exist in MySQL is to make the &lt;tt&gt;INSERT&lt;/tt&gt; statement idempotent when run on a replication slave when run in mixed or statement-based mode.  Don't believe me?  Here is a code snippet and comment from the &lt;tt&gt;sql/log_event.cc&lt;/tt&gt; file in MySQL 5.4:
&lt;/p&gt;
&lt;pre&gt;
Write_rows_log_event::do_before_row_operations(const Slave_reporting_capability *const)
...
  &lt;span style=&quot;color: green;&quot;&gt;/**
     todo: to introduce a property for the event (handler?) which forces
     applying the event in the replace (idempotent) fashion.
  */&lt;/span&gt;
  if (bit_is_set(slave_exec_mode, SLAVE_EXEC_MODE_IDEMPOTENT) == 1 ||
      m_table-&gt;s-&gt;db_type()-&gt;db_type == DB_TYPE_NDBCLUSTER)
  {
    &lt;span style=&quot;color: green;&quot;&gt;/*
      We are using REPLACE semantics and not INSERT IGNORE semantics
      when writing rows, that is: new rows replace old rows.  We need to
      inform the storage engine that it should use this behaviour.
    */&lt;/span&gt;
    
    &lt;span style=&quot;color: green;&quot;&gt;/* Tell the storage engine that we are using REPLACE semantics. */&lt;/span&gt;
    thd-&gt;lex-&gt;duplicates= DUP_REPLACE;
    
    &lt;span style=&quot;color: green;&quot;&gt;/*
      Pretend we're executing a REPLACE command: this is needed for
      InnoDB and NDB Cluster since they are not (properly) checking the
      lex-&gt;duplicates flag.
    */&lt;/span&gt;
    thd-&gt;lex-&gt;sql_command= SQLCOM_REPLACE;
    &lt;span style=&quot;color: green;&quot;&gt;/* 
       Do not raise the error flag in case of hitting to an unique attribute
    */&lt;/span&gt;
    m_table-&gt;file-&gt;extra(HA_EXTRA_IGNORE_DUP_KEY);
...
&lt;/pre&gt;
&lt;p&gt;
By contrast to MySQL 5.4, Drizzle's replication system is a reflection of the &lt;strong&gt;atomic changes made to the state of a server&lt;/strong&gt;.  These changes are, by definition, deterministic, and applying a transaction log to a Drizzle replica can result in one &lt;em&gt;and only one&lt;/em&gt; state in the resulting server.  In Drizzle, having the application of the transaction log be idempotent is not necessary, as the transaction log stream is always deterministic.  For instance, if an &lt;tt&gt;INSERT ... ON DUPLICATE KEY UPDATE&lt;/tt&gt; is issued against a Drizzle server, the replication system shall create &lt;em&gt;either&lt;/em&gt; an InsertStatement &lt;strong&gt;or&lt;/strong&gt; an UpdateStatement message, depending on what precisely occurred on the server, and these messages are logged in Drizzle's transaction log.  There is no fudging of statements.  What happened on the server is logged as an exact change in the state of the server, nothing more.
&lt;/p&gt;
&lt;p&gt;
So...anyway, because of the above &quot;optimization&quot;, I'm now left with a tricky problem: continue to pay the interest on this &lt;a href=&quot;http://en.wikipedia.org/wiki/Technical_debt&quot;  title=&quot;technical debt&quot;&gt;Technical Debt&lt;/a&gt; or rework the Cursor interface so that behaviour is always idempotent via the wrapper interface and has no side effects.  I'm not sure what I will do...but this has delayed me substantially. &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/sad.png&quot; alt=&quot;:-(&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;
&lt;/p&gt;
&lt;/p&gt;    </content:encoded>
                
    <pubDate>Thu, 22 Oct 2009 11:20:43 -0400</pubDate>
    <guid isPermaLink="false">http://jpipes.com/index.php?/archives/303-guid.html</guid>
    </item>
<item>
    <title>Pop Quiz - What Does REPLACE Do?</title>
    <link>http://jpipes.com/index.php?/archives/301-Pop-Quiz-What-Does-REPLACE-Do.html</link>
<category>MySQL</category><category>Drizzle</category>    <comments>http://jpipes.com/index.php?/archives/301-Pop-Quiz-What-Does-REPLACE-Do.html#comments</comments>
    <wfw:comment>http://jpipes.com/wfwcomment.php?cid=301</wfw:comment>
    <slash:comments>31</slash:comments>
    <wfw:commentRss>http://jpipes.com/rss.php?version=2.0&amp;type=comments&amp;cid=301</wfw:commentRss>
    <author>nospam@example.com (Jay Pipes)</author>
    <content:encoded>
&lt;p&gt;
Hi ZanyWeb.  Here's a pop quiz for you, and the answer may surprise you.
&lt;/p&gt;
&lt;p&gt;
The &lt;a href=&quot;http://dev.mysql.com/doc/refman/5.0/en/replace.html&quot;  title=&quot;REPLACE syntax  - MySQL manual&quot;&gt;MySQL manual states&lt;/a&gt; the following about the REPLACE statement:
&lt;/p&gt;
&lt;blockquote&gt;
&lt;strong&gt;REPLACE&lt;/strong&gt; works exactly like &lt;strong&gt;INSERT&lt;/strong&gt;, except that if an old row in the table has the same value as a new row for a &lt;strong&gt;PRIMARY KEY&lt;/strong&gt; or a &lt;strong&gt;UNIQUE&lt;/strong&gt;  index, the old row is deleted before the new row is inserted.
&lt;/blockquote&gt;
&lt;p&gt;
Sounds pretty clear to me.  &lt;em&gt;If a row with the same primary key exists, it is deleted and then a new row is inserted&lt;/em&gt;.
&lt;/p&gt;
&lt;p&gt;
So, given the above, if I execute the following statements in a client, what would you expect would happen behind the scenes in the storage engine?
&lt;/p&gt;
&lt;pre&gt;
CREATE TABLE t1 (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, padding VARCHAR(200) NOT NULL
);

INSERT INTO t1 VALUES (1, &quot;I love testing.&quot;);
INSERT INTO t1 VALUES (2, &quot;I hate testing.&quot;);

REPLACE INTO t1 VALUE (2, &quot;I love testing.&quot;);
&lt;/pre&gt;
&lt;p&gt;
If you're like me, you would expect the above to actually execute the following changes:
&lt;/p&gt;
&lt;pre&gt;
CREATE TABLE t1 (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, padding VARCHAR(200) NOT NULL
);

INSERT INTO t1 VALUES (1, &quot;I love testing.&quot;);
INSERT INTO t1 VALUES (2, &quot;I hate testing.&quot;);
DELETE FROM t1 WHERE id = 2;
INSERT INTO t1 VALUE (2, &quot;I love testing.&quot;);
&lt;/pre&gt;
&lt;p&gt;
But, this is &lt;strong&gt;not actually what happens&lt;/strong&gt;.
&lt;/p&gt;
&lt;p&gt;
Would anyone like to guess what actually happens?  Add your guess to the comments on this entry.  I'll post the answer later today. &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;
&lt;/p&gt;    </content:encoded>
                
    <pubDate>Wed, 21 Oct 2009 11:52:35 -0400</pubDate>
    <guid isPermaLink="false">http://jpipes.com/index.php?/archives/301-guid.html</guid>
    </item>
<item>
    <title>Drizzle Replication - The CommandReplicator and CommandApplier Plugin API</title>
    <link>http://jpipes.com/index.php?/archives/300-Drizzle-Replication-The-CommandReplicator-and-CommandApplier-Plugin-API.html</link>
<category>MySQL</category><category>Drizzle</category><category>C/C++</category>    <comments>http://jpipes.com/index.php?/archives/300-Drizzle-Replication-The-CommandReplicator-and-CommandApplier-Plugin-API.html#comments</comments>
    <wfw:comment>http://jpipes.com/wfwcomment.php?cid=300</wfw:comment>
    <slash:comments>1</slash:comments>
    <wfw:commentRss>http://jpipes.com/rss.php?version=2.0&amp;type=comments&amp;cid=300</wfw:commentRss>
    <author>nospam@example.com (Jay Pipes)</author>
    <content:encoded>
&lt;p&gt;
&lt;div style=&quot;background-color: #f7f7f7; border: solid 1px #ccc; padding: 20px 100px;&quot;&gt;
&lt;strong&gt;IMPORTANT&lt;/strong&gt;:&lt;br /&gt;
This article is out of date and the replication API has been updated.  Please see the &lt;a href=&quot;http://jpipes.com/index.php?/archives/302-Drizzle-Replication-Changes-in-API-to-support-Group-Commit.html&quot;  title=&quot;Drizzle Replication - Transaction Message&quot;&gt;follow-up article&lt;/a&gt; for the most up to date information!
&lt;/div&gt;
OK, so here is the next installment in the Drizzle replication article series.  Today, I'll be talking about the flow of the Command message object through the CommandReplicator and CommandApplier APIs.  If you missed the first article about the structure of the Command message and Google Protobuffers, you may want to &lt;a href=&quot;http://jpipes.com/index.php?/archives/298-Drizzle-Replication-The-Command-Message.html&quot;  title=&quot;Drizzle Replicaiton - The Command message&quot;&gt;read that first&lt;/a&gt;.  We'll only be talking in this article about what happens &lt;strong&gt;on one server&lt;/strong&gt;.  We will be discussing the Command Log in the next article, and then discuss how messages are passed from one server to another.  But, before we discuss those things, it is critical to first understand the CommandReplicator and CommandApplier plugin classes, which are two of the abstract interfaces out of which replication modules can be built (and from which a number of modules have already been built).
&lt;/p&gt;
&lt;p&gt;
In this article, I'll be showing code that was written by myself and by &lt;a href=&quot;http://posulliv.com/&quot;  title=&quot;Padraig O'Sullivan&quot;&gt;Padraig O'Sullivan&lt;/a&gt;, another Drizzle contributor.
&lt;/p&gt;
&lt;h2&gt;Flow of Command messages&lt;/h2&gt;

&lt;div style=&quot;float: right; margin: 0px 0px 30px 30px; border: solid 1px #ccc; background-color: #f7f7f7; width: 450px; padding: 10px 30px;&quot;&gt;
&lt;h3 style=&quot;text-align: center;&quot;&gt;SIDEBAR: Namespaces in Drizzle&lt;/h3&gt;
&lt;p&gt;
The astute reader may have noticed that there is quite a big difference in the organization of the Drizzle codebase versus MySQL.  Drizzle uses C++ namespaces to make the code easier to read and understand.  
&lt;/p&gt;
&lt;p&gt;
New code written for Drizzle is always namespaced in a namespace corresponding to the exact directory structure in which you find the source files for a particular class.  For instance, all plugin interfaces classes (abstract base classes) are in the &lt;tt&gt;drizzled::plugin&lt;/tt&gt; namespace and are found in &lt;tt&gt;/drizzled/plugin/&lt;/tt&gt;.  All protobuffer message classes are defined in &lt;tt&gt;/drizzled/message/&lt;/tt&gt; and are in the namespace &lt;tt&gt;drizzled::message&lt;/tt&gt;.  We feel organizing the code like so, and using C++ namespaces, makes the code clearer and easier to read.  You can read more about Drizzle's coding style, including how we use namespaces &lt;a href=&quot;http://drizzle.org/wiki/Coding_Standards&quot;  title=&quot;Drizzle Coding Standards&quot;&gt;on our wiki&lt;/a&gt;.
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Command messages are created by a component within the Drizzle kernel whenever any SQL statement which modifies the state of the server is executed.  This component is called ReplicationServices.  This component is a singleton object and manages communication between the kernel and two kinds of plugins, called CommandReplicator and CommandApplier. The component is declared in &lt;tt&gt;drizzled/replication_services.h&lt;/tt&gt; and defined in &lt;tt&gt;drizzled/replication_services.cc&lt;/tt&gt;.
&lt;/p&gt;
&lt;p&gt;
The advantage of the ReplicationServices component frees replication module developers from having to understand &lt;em&gt;anything&lt;/em&gt; about what's going on in the kernel.  You don't have to understand anything about the Session object, how statements are executed in the kernel, or even how storage engines are actually applying changes to their data.  All you need to learn is the structure of the Command message (covered in the &lt;a href=&quot;http://jpipes.com/index.php?/archives/298-Drizzle-Replication-The-Command-Message.html&quot;  title=&quot;Drizzle Replication - Command Message&quot;&gt;previous article&lt;/a&gt;) and the very, very simple CommandReplicator and CommandApplier plugin APIs.  So, let's look at those APIs. &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;
&lt;/p&gt;
&lt;h2&gt;The CommandReplicator Plugin API&lt;/h2&gt;
&lt;p&gt;
Here is the abstract base class &lt;tt&gt;drizzled::plugin::CommandReplicator&lt;/tt&gt;, available in &lt;tt&gt;drizzled/plugin/command_replicator.h&lt;/tt&gt;.
&lt;/p&gt;
&lt;pre&gt;
&lt;span style=&quot;color: green;&quot;&gt;
/**
 * Class which replicates Command messages
 */&lt;/span&gt;
class CommandReplicator
{
public:
  CommandReplicator() {}
  virtual ~CommandReplicator() {}
  &lt;span style=&quot;color: green;&quot;&gt;
  /**
   * Replicate a Command message to a CommandApplier.
   *
   * @note
   *
   * It is important to note that memory allocation for the 
   * supplied pointer is not guaranteed after the completion 
   * of this function -- meaning the caller can dispose of the
   * supplied message.  Therefore, replicators and appliers 
   * implementing an asynchronous replication system must copy
   * the supplied message to their own controlled memory storage
   * area.
   *
   * @param Pointer to the applier of the command message
   * @param Command message to be replicated
   */&lt;/span&gt;
  virtual void replicate(CommandApplier *in_applier, drizzled::message::Command &amp;to_replicate)= 0;
};
&lt;/pre&gt;
&lt;p&gt;
See, I told you it was simple &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;  There is an additional &lt;tt&gt;isActive()&lt;/tt&gt; method currently in this API, but this will disappear in the coming months as that method wil be &quot;moving up&quot; to a base Plugin class.  You can ignore it for right now.  The only other method which &lt;tt&gt;CommandReplicator&lt;/tt&gt; plugins must implement is the &lt;tt&gt;replicate()&lt;/tt&gt; method.
&lt;/p&gt;
&lt;p&gt;
The &lt;tt&gt;replicate()&lt;/tt&gt; method accepts only two parameters.  The first is a pointer to an object which implements the CommandApplier interface (inherits from &lt;tt&gt;drizzled::plugin::CommandApplier&lt;/tt&gt;).  The second is the Command message that the ReplicationServices component constructs when a data-modification event occurs on the server.
&lt;/p&gt;
&lt;h2&gt;The CommandApplier Plugin API&lt;/h2&gt;
&lt;p&gt;
Before I show some implementation of CommandReplicators, let's first quickly take a look at the &lt;tt&gt;drizzled::plugin::CommandApplier&lt;/tt&gt; interface.  It is equally simple.
&lt;/p&gt;
&lt;pre&gt;
&lt;span style=&quot;color: green;&quot;&gt;
/**
 * Base class for appliers of Command messages
 */&lt;/span&gt;
class CommandApplier
{
public:
  CommandApplier() {}
  virtual ~CommandApplier() {}
  &lt;span style=&quot;color: green;&quot;&gt;
 /**
   * Apply something to a target.
   *
   * @note
   *
   * It is important to note that memory allocation for the 
   * supplied pointer is not guaranteed after the completion 
   * of this function -- meaning the caller can dispose of the
   * supplied message.  Therefore, appliers which are
   * implementing an asynchronous replication system must copy
   * the supplied message to their own controlled memory storage
   * area.
   *
   * @param Command message to be applied
   */&lt;/span&gt;
  virtual void apply(const drizzled::message::Command &amp;to_apply)= 0;
};
&lt;/pre&gt;
&lt;p&gt;
The CommandApplier quite predictably implements a single method: &lt;tt&gt;apply()&lt;/tt&gt;, which accepts a single parameter of a Command message.  Yes, it's that simple.
&lt;/p&gt;
&lt;h2&gt;Putting it All Together&lt;/h2&gt;
&lt;p&gt;
Before we get to the example implementation of the above plugin interfaces, it's worth pointing out that Drizzle's replication system allows multiple CommandReplicator and CommandApplier plugins to register themselves with the ReplicationServices component.  The &lt;tt&gt;ReplicationServices::push()&lt;/tt&gt; internal method simply loops through the active replicators and appliers, calling the replicate() method, passing in a constructed Command message and a pointer to each registered applier.  Here is the code showing this process:
&lt;/p&gt;
&lt;pre&gt;
void ReplicationServices::push(message::Command &amp;to_push)
{
  vector&lt;plugin::CommandReplicator *&gt;::iterator repl_iter= replicators.begin();
  vector&lt;plugin::CommandApplier *&gt;::iterator appl_start_iter, appl_iter;
  appl_start_iter= appliers.begin();

  plugin::CommandReplicator *cur_repl;
  plugin::CommandApplier *cur_appl;

  while (repl_iter != replicators.end())
  {
    cur_repl= *repl_iter;
    if (! cur_repl-&gt;isActive())
    {
      ++repl_iter;
      continue;
    }
    
    appl_iter= appl_start_iter;
    while (appl_iter != appliers.end())
    {
      cur_appl= *appl_iter;

      if (! cur_appl-&gt;isActive())
      {
        ++appl_iter;
        continue;
      }

      cur_repl-&gt;replicate(cur_appl, to_push);
      &lt;span style=&quot;color: green;&quot;&gt;
      /* 
       * We update the timestamp for the last applied Command so that
       * publisher plugins can ask the replication services when the
       * last known applied Command was using the getLastAppliedTimestamp()
       * method.
       */&lt;/span&gt;
      last_applied_timestamp.fetch_and_store(to_push.timestamp());
      ++appl_iter;
    }
    ++repl_iter;
  }
}
&lt;/pre&gt;
&lt;p&gt;
Pretty simple, no?  There's a couple big things to point out about the code you've seen so far.  First, Drizzle is focused on providing clean, simple, and encapsulated interfaces for plugin developers.  There's no need for plugin developers to understand the often-messy and poorly documented internals of the kernel.  A plugin developer only needs to do two things:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Understand the well-documented &lt;a href=&quot;http://code.google.com/apis/protocolbuffers/docs/reference/overview.html&quot;  title=&quot;GPB Documentation&quot;&gt;Google Protobuffer message API&lt;/a&gt; and have a copy of the replication.proto file which contains the blueprint for the Command message&lt;/li&gt;
&lt;li&gt;Implement either the &lt;tt&gt;drizzled::plugin::CommandReplicator::replicate()&lt;/tt&gt; or &lt;tt&gt;drizzled::plugin::CommandApplier::apply()&lt;/tt&gt; method&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Secondly, the interface allows individuals and companies to completely customize how Drizzle replication works for them.  You want replication to do X, Y, and Z?  Fine, no problem.  We give you some example plugins which clearly demonstrate the interfaces, and you can take it from there, without worrying about messing up the kernel. &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;
So, now that you've seen the plugin interfaces, let's discuss how these plugin interfaces are implemented in a couple plugins that are distributed with Drizzle right now.
&lt;/p&gt;
&lt;h3&gt;The FilteredReplicator Plugin&lt;/h2&gt;
&lt;p&gt;
After I wrote the default replicator plugin (which literally does nothing but the following:
&lt;/p&gt;
&lt;pre&gt;
void DefaultReplicator::replicate(plugin::CommandApplier *in_applier, message::Command &amp;to_replicate)
{
  &lt;span style=&quot;color: green;&quot;&gt;
  /* 
   * We do absolutely nothing but call the applier's apply() method, passing
   * along the supplied Command.  Yep, told you it was simple...
   *
   * Perfectly fine to use const_cast&lt;&gt; below.  All that does is allow the replicator
   * to conform to the CommandApplier::apply() API call which dictates that the applier
   * shall never modify the supplied Command message argument.  Since the replicator 
   * itself *can* modify the supplied Command message, we use const_cast&lt;&gt; here to
   * set the message to a readonly state that the compiler will like.
   */&lt;/span&gt;
  in_applier-&gt;apply(const_cast&lt;const message::Command&amp;&gt;(to_replicate));
}
&lt;/pre&gt;
&lt;p&gt;
&lt;a href=&quot;http://posulliv.com/?p=118&quot;  title=&quot;Padraig O'Sullivan - FilteredReplicator - Drizzle&quot;&gt;Padraig O'Sullivan took the reins and wrote&lt;/a&gt; a &lt;tt&gt;FilteredReplicator&lt;/tt&gt; plugin which allows a DBA to filter Command messages by schema name, table name, and a regular expression.  His FilteredReplicator is much more interesting than the default replicator, so let's take a look at some of his code.  Here is the &lt;tt&gt;replicate()&lt;/tt&gt; method from the FilteredReplicator plugin:
&lt;/p&gt;
&lt;pre&gt;
void FilteredReplicator::replicate(plugin::CommandApplier *in_applier, 
                                   message::Command &amp;to_replicate)
{
  string schema_name;
  string table_name;

  &lt;span style=&quot;color: green;&quot;&gt;
  /*
   * First, we check to see if the command consists of raw SQL. If so,
   * we need to parse this SQL and determine whether to filter the event
   * based on the information we obtain from the parsed SQL.
   * If not raw SQL, check if this event should be filtered or not
   * based on the schema and table names in the command message.
   */&lt;/span &gt;
  if (to_replicate.type() == message::Command::RAW_SQL)
  {
    parseQuery(to_replicate.sql(),
               schema_name,
               table_name);
  }
  else
  {
    schema_name.assign(to_replicate.schema());
    table_name.assign(to_replicate.table());
  }

  &lt;span style=&quot;color: green;&quot;&gt;/*
   * Convert the schema name and table name strings to lowercase so that it
   * does not matter what case the table or schema name was specified in. We
   * also keep all entries in the vectors of schemas and tables to filter in
   * lowercase.
   */&lt;/span&gt;
  std::transform(schema_name.begin(), schema_name.end(),
                 schema_name.begin(), ::tolower);
  std::transform(table_name.begin(), table_name.end(),
                 table_name.begin(), ::tolower);

  if (isSchemaFiltered(schema_name) ||
      isTableFiltered(table_name))
  {
    return;
  }

  &lt;span style=&quot;color: green;&quot;&gt;/*
   * We can now simply call the applier's apply() method, passing
   * along the supplied command.
   */&lt;/span&gt;
  in_applier-&gt;apply(to_replicate);
}
&lt;/pre&gt;
&lt;p&gt;
The above code is quite easy to read and understand.  I encourage you to check out the rest of Padraig's &lt;a href=&quot;http://posulliv.com/?p=118&quot;  title=&quot;Padraig O'Sullivan - FilteredReplicator - Drizzle&quot;&gt;implementation&lt;/a&gt; in &lt;tt&gt;/plugin/filtered_replicator/filtered_replicator.cc&lt;/tt&gt; and see just how easy it is to start writing new Drizzle replication modules.
&lt;/p&gt;
&lt;h3&gt;The CommandLog::apply() Method&lt;/h3&gt;
&lt;p&gt;
To demonstrate a CommandApplier implementation, I present the apply() method of the &lt;tt&gt;CommandLog&lt;/tt&gt; plugin, which inherits from &lt;tt&gt;drizzled::plugin::CommandApplier&lt;/tt&gt;.  Without going into too much about the Command Log, which is the subject of the next article, I'll let you take a look at just the apply() method, to see how a CommandApplier does its main job (see &lt;tt&gt;/plugin/command_log/command_log.cc&lt;/tt&gt;):
&lt;/p&gt;
&lt;pre&gt;
void CommandLog::apply(const message::Command &amp;to_apply)
{
  string buffer(&quot;&quot;); &lt;span style=&quot;color: green;&quot;&gt;/* Buffer we will write serialized command to */&lt;/span&gt;

  static const uint32_t HEADER_TRAILER_BYTES= sizeof(uint64_t) + &lt;span style=&quot;color: green;&quot;&gt;/* 8-byte length header */&lt;/span&gt;
                                              sizeof(uint32_t); &lt;span style=&quot;color: green;&quot;&gt;/* 4 byte checksum trailer */&lt;/span&gt;

  size_t length;
  ssize_t written;
  off_t cur_offset;

  to_apply.SerializeToString(&amp;buffer);

  length= buffer.length(); 

  &lt;span style=&quot;color: green;&quot;&gt;
  /*
   * Do an atomic increment on the offset of the log file position
   */&lt;/span&gt;
  cur_offset= log_offset.fetch_and_add((off_t) (HEADER_TRAILER_BYTES + length));

  &lt;span style=&quot;color: green;&quot;&gt;
  /*
   * We adjust cur_offset back to the original log_offset before
   * the increment above...
   */&lt;/span&gt;
  cur_offset-= (off_t) (HEADER_TRAILER_BYTES + length);

  &lt;span style=&quot;color: green;&quot;&gt;
  /* 
   * Quick safety...if an error occurs below, the log file will
   * not be active, therefore a caller could have been ready
   * to write...but the log is crashed.
   */&lt;/span&gt;
  if (unlikely(state == CRASHED))
    return;

  &lt;span style=&quot;color: green;&quot;&gt;/* We always write in network byte order */&lt;/span&gt;
  unsigned char nbo_length[8];
  int8store(nbo_length, length);

  &lt;span style=&quot;color: green;&quot;&gt;/* Write the length header */&lt;/span&gt;
  do
  {
    written= pwrite(log_file, nbo_length, sizeof(uint64_t), cur_offset);
  }
  while (written == -1 &amp;&amp;amp; errno == EINTR); &lt;span style=&quot;color: green;&quot;&gt;/* Just retry the write when interrupted by a signal... */&lt;/span&gt;

  if (unlikely(written != sizeof(uint64_t)))
  {
    errmsg_printf(ERRMSG_LVL_ERROR, 
                  _(&quot;Failed to write full size of command.  Tried to write %&quot; PRId64 &quot; bytes at offset %&quot; PRId64 &quot;, but only wrote %&quot; PRId64 &quot; bytes.  Error: %s\n&quot;), 
                  sizeof(int64_t), 
                  (int64_t) cur_offset,
                  (int64_t) written, 
                  strerror(errno));
    state= CRASHED;
    &lt;span style=&quot;color: green;&quot;&gt;
    /* 
     * Reset the log's offset in case we want to produce a decent error message including
     * the original offset where an error occurred.
     */&lt;/span&gt;
    log_offset= cur_offset;
    is_active= false;
    return;
  }

  cur_offset+= (off_t) written;

  &lt;span style=&quot;color: green;&quot;&gt;
  /* 
   * Quick safety...if an error occurs above in another writer, the log 
   * file will be in a crashed state.
   */&lt;/span&gt;
  if (unlikely(state == CRASHED))
  {
    &lt;span style=&quot;color: green;&quot;&gt;
    /* 
     * Reset the log's offset in case we want to produce a decent error message including
     * the original offset where an error occurred.
     */&lt;/span&gt;
    log_offset= cur_offset;
    return;
  }

  &lt;span style=&quot;color: green;&quot;&gt;/* Write the command message itself */&lt;/span&gt;
  do
  {
    written= pwrite(log_file, buffer.c_str(), length, cur_offset);
  }
  while (written == -1 &amp;&amp;amp; errno == EINTR); &lt;span style=&quot;color: green;&quot;&gt;/* Just retry the write when interrupted by a signal... */&lt;/span&gt;

  if (unlikely(written != (ssize_t) length))
  {
    errmsg_printf(ERRMSG_LVL_ERROR, 
                  _(&quot;Failed to write full serialized command.  Tried to write %&quot; PRId64 &quot; bytes at offset %&quot; PRId64 &quot;, but only wrote %&quot; PRId64 &quot; bytes.  Error: %s\n&quot;), 
                  (int64_t) length, 
                  (int64_t) cur_offset,
                  (int64_t) written, 
                  strerror(errno));
    state= CRASHED;
    log_offset= cur_offset;
    is_active= false;
  }

  cur_offset+= (off_t) written;

  &lt;span style=&quot;color: green;&quot;&gt;
  /* 
   * Quick safety...if an error occurs above in another writer, the log 
   * file will be in a crashed state.
   */&lt;/span&gt;
  if (unlikely(state == CRASHED))
  {
    &lt;span style=&quot;color: green;&quot;&gt;
    /* 
     * Reset the log's offset in case we want to produce a decent error message including
     * the original offset where an error occurred.
     */&lt;/span&gt;
    log_offset= cur_offset;
    return;
  }

  uint32_t checksum= 0;

  if (do_checksum)
  {
    checksum= crc32(0L, (unsigned char *) buffer.c_str(), length);
  }

  &lt;span style=&quot;color: green;&quot;&gt;/* We always write in network byte order */&lt;/span&gt;
  unsigned char nbo_checksum[4];
  int4store(nbo_checksum, checksum);

  &lt;span style=&quot;color: green;&quot;&gt;/* Write the checksum trailer */&lt;/span&gt;
  do
  {
    written= pwrite(log_file, nbo_checksum, sizeof(uint32_t), cur_offset);
  }
  while (written == -1 &amp;&amp;amp; errno == EINTR); /* Just retry the write when interrupted by a signal... */

  if (unlikely(written != (ssize_t) sizeof(uint32_t)))
  {
    errmsg_printf(ERRMSG_LVL_ERROR, 
                  _(&quot;Failed to write full checksum of command.  Tried to write %&quot; PRId64 &quot; bytes at offset %&quot; PRId64 &quot;, but only wrote %&quot; PRId64 &quot; bytes.  Error: %s\n&quot;), 
                  (int64_t) sizeof(uint32_t), 
                  (int64_t) cur_offset,
                  (int64_t) written, 
                  strerror(errno));
    state= CRASHED;
    log_offset= cur_offset;
    is_active= false;
    return;
  }
}
&lt;/pre&gt;
&lt;h2&gt;Conclusion, for Now...&lt;/h2&gt;
&lt;p&gt;
I do hope this article has been useful in getting to know how the Drizzle replication system passes the Command message around within a single server.  You got to see the replicator and applier plugin APIs and example implementations of those APIs in the form of the FilteredReplicator and CommandLog classes.  Next, we'll be looking in detail at the Command Log itself, its format, and writing/reading from it.
&lt;/p&gt;
&lt;p&gt;
Please do email me (joinfu@sun.com) or feel free to post to the &lt;a href=&quot;https://launchpad.net/~drizzle-discuss&quot;  title=&quot;Drizzle Discuss&quot;&gt;Drizzle Discussion list&lt;/a&gt; any criticism, suggestions, or requests.  I'm eager to hear from you. &lt;img src=&quot;http://jpipes.com/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;
&lt;/p&gt;    </content:encoded>
                
    <pubDate>Fri, 14 Aug 2009 10:55:00 -0400</pubDate>
    <guid isPermaLink="false">http://jpipes.com/index.php?/archives/300-guid.html</guid>
    </item>
</channel>
</rss>
