Ayende @ Rahien

Oren Eini aka Ayende Rahien CEO of Hibernating Rhinos LTD, which develops RavenDB, a NoSQL Open Source Document Database.

You can reach me by:

oren@ravendb.net

+972 52-548-6969

, @ Q j

Posts: 6,868 | Comments: 49,216

filter by tags archive

The BIG Merge

time to read 3 min | 413 words

Merging is one of my least favorite activities, this is especially true when we are talking about a big merge. You might have noticed that I have been talking lately about some big changes that we are making to NH Prof. And now the time has come to merge it all back together.

Well, big changes is quite an understatement, to be fair. what we did is rip apart the entire model the application used to work with. We moved from a push model to a pull model, and that had quite a lot of implications throughout the code base.

Of course, we also did some work on the trunk while we worked on that, so before we can even think about reintegrating the branch, we have to do a merge from the trunk to the branch, which resulted in:

image

Now, the problem is that this is totally stupid.

Nitpicker corner:
   And yes, I am using Subversion, and before the Git fanboys totally jump on me, I am seriously considering moving to Git to ease this sort of pain.
   And yes, I should have done reverse merges to the  branch all along, so before the Subversion fanboys totally jump on me, I know that.

It is stupid because there are some changes that has been made in parallel in both branches, there are some changes that involve deleting or renaming files that are just not being merged. And yes, I am using SVN 1.5. So, after resolving all the conflicts, I have to do a manual check over this, to make sure that we didn’t miss a merge because of that. I am at the point of so much Argh! that I can’t really keep it inside, hence this post.

A common example that I know is going to hit me is something like FormattedStatement, which is a pretty important class. In the branch, that was changed to be SqlStatement, and I renamed the file as well. Subversion doesn’t merge changes across that. And yes, I used svn rename for that (via Visual SVN).

And, to add insult to injury, doing this manual checking means a lot of going over the network, which means that this is slow.

How to fix a bug

time to read 1 min | 170 words

Yesterday I added a bug to Rhino Service Bus. It was a nasty one, and a slippery one. It relates to threading nastiness with MSMQ, and the details aren’t really interesting.

What is interesting is how I fixed it. You can see the commit log here:

image 

At some point, it became quite clear that trying to fix the bug isn’t going to work. I reset the repository back to before I introduced that bug (gotta love source control!) and started reintroducing my change in a very controlled manner.

I am back with the same functionality that I had before I reset the code base, and with no bug. Total time to do this was about 40 minutes or so. I spent quite a bit longer than that just trying to fix up that.

Lesson learned, remember to cut your losses early :-)

time to read 1 min | 70 words

It is so much fun to see things that I worked on coming alive. The official announcement is here, with all the boring details. You can skip all of that and go read the code directly using SVN by hitting: https://svnbridge.svn.codeplex.com/svn

Switch svnbridge for your project, and you are done. Note that this is https. And yes, it should work with git-svn as well.

Way cool!

time to read 3 min | 521 words

Without getting to the centralized vs. decentralized SCM argument (I understand the differences, I just don't grok them), patch management is important in many scenarios. Contributing to OSS projects is a major one, I admit, but I have previous used these techniques to be able to take emergency fixes on productions and merge them into the development trunk.

The question came up in the NHibernate Contrib mailing list, and Josh Robb has commented on that at length. I thought that it would be a good idea to take that and expand on this a bit.

The problem:

We want to submit a changeset to a project, without having direct access to its source control. The solution is to generate a patch and send it to the destination.

So far, it is simple. It gets complex when you need to deal with more than a single changeset that hasn't been merged to the root.

Let us say that we have several changesets that we have generated. Let us see how we treat them, according to the different scenarios we encounter. A scenario, in this case, is the dependence between the changesets.

Scenario #1 - No dependencies between the patches.

This is a common scenario if you are working on several things in parallel. A classic case is when you are fixing several bugs. In most cases, the changes in each bug fix are unrelated to each other, and can be applied independently.

In this case, you usually generate separate patches for each changeset. This allow to evaluate each patch in isolation, which significantly ease the acceptance of each patch.

This lead us to the First Rule of Patches: keep them small. It is easier to go through seven small patches than 1 big one.

Scenario #2 - No dependencies between the patches, but touching the same files.

This is the case if two changesets has touched the same file, but there is no logical dependency between the patches. In this case, we still want to get separate patches. Usually, I generate one patch, revert to base, work on the second one, generate a patch, etc...

Scenario #3 - Logical dependencies between the patches

One patch relies on behavior / API created in another patch. In this case, the best solution is to create a patch for each distinct behavior, and number them, so it is still possible to review them in isolation, but the merge order is clear.

Scenario #4 - Several revisions of the same patch

In this case, you sumbitted a patch, but continued to work on the same feature/bug and have a new patch before the first one was applied. In this case, the later patch supercede the previous one, which can now be discarded. You need to be careful with this scenario, because too much disconnected work can create huge patches. It is better to review you work and see if you are in situation #3 or really situation #4.

Anything that I missed?

time to read 2 min | 370 words

Well, here is how my last few days were spent. Trying to get SvnBridge to work on Mono 1.9.1. (Note that we are talking about working locally, when the hosted version will go live, it will obviously be accessible from everything and anything that can talk to an SVN server).

After getting it to compile and run (not a trivial process, I must say, I used a surprisingly high number of MS CLR stuff, but we will leave that to another post), I had managed to get some basic functionality working, and I was able to successfully checkout the source of SvnBridge itself.

image

Unfortunately, when I tried to commit those changes, I run into several... problems.

Without beating too much around the bush, the issue was that authentication errors against the TFS web service API. More specifically, in the error handling of those authentications errors.

In several parts of SvnBridge, we have code similar to this:

try
{
    return tfsWebService.DoSomething();
}
catch(WebException we)
{
    HttpWebResponse r = we.Response as r;
    if( r != null && r.StatusCode == HttpStatusCode.Unauthorized )
          throw new NetworkAccessDeniedException(we);       
}

The problematic part is bolded and in red. As I already mentioned, there is a subtle but incredibly annoying difference between Mono and .Net. This means that code such as this will never work. The issue is that the Mono implementation of HttpWebResponse check to verify that no access is done to a disposed object. Precisely like a well behaved object should. The .Net implementation does not.

By the time that the SOAP stack implementation (on both sides) gives you the web exception, the web response has been disposed. But on the Mono side of things, you can't even find out why.

As a result, I made up this logo.

image

I have reported the issue to the Mono guys, and hopefully they will get this fixed.

Git to CodePlex

time to read 1 min | 113 words

Well, it works, finally.

image

I had major issues getting commits to work. Eventually I figured out that git-svn does not send hashes of the files as all other SVN clients that I have tested so far. I was focused on finding corruption much earlier in the game, and drowned in the details.

I am not sure why it is committing a single change twice, but it is showing the same behavior on standard SVN servers, so I think that I am fine.

And here is the final test:

image

:-D

FUTURE POSTS

No future posts left, oh my!

RECENT SERIES

  1. Reviewing mimalloc (2):
    22 Jul 2019 - Part II
  2. Production postmortem (26):
    07 Jun 2019 - Printer out of paper and the RavenDB hang
  3. Reviewing Sled (3):
    23 Apr 2019 - Part III
  4. RavenDB 4.2 Features (5):
    21 Mar 2019 - Diffing revisions
  5. Workflow design (4):
    06 Mar 2019 - Making the business people happy
View all series

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats