Monday, March 21, 2016

Merging Multiple AJAX threads using a "Joining Mutex"

I had previously posted this article with a snippet of example code. That blog entry was accidently deleted so I am reposting an update version of it now.

What is a "Joining Mutex" and why would you need it?

var AfterAllThreadsExecute = function() { alert("Hello World");}

for(var i=0; i < records.length; i++) {
        // dispatchAjaxCall(ThreadMutexHandle, recordId)
 dispatchAjaxCall(JoiningMutex.contextJoinCreate('TestContext',AfterAllThreadsExecute, records[i].ID);

within the dispatchAjaxCall(myMutexHandle) {

 // do AJAX stuff here ...

 // now signal to the Mutex (via our reference handle) that this thread has finish running
A listing of the initial code is below. The latest code is used within the i2b2 web client in the i2b2/hive/hive_helpers.js file and can be found at
// created this object to allow the joining of forked execution paths (Waiting for Multiple AJAX calls)
JoiningMutex = { 
 _contexts: {},
 _contextGenID: 0,
 _createContextProxy: function(contextRef) {
  // create a proxy object (via closure) to encapsulate data 
  // and route actions to the JoinMutex singleton
  var cl_JoinMutextRef = contextRef;
  function JoiningMutexContextProxy() {
   this._JoiningMutexContext = cl_JoinMutextRef;
   this._alreadyRun = false; = function() { return; };
   this.openThreads = function() { return this._JoiningMutexContext.openThreads; };
   this.executeOnce = function() { return this._JoiningMutexContext.executeOnce; };
   this.executionCount = function() { return this._JoiningMutexContext.executionCount; };
   this.isActive = function() { return; };
   this.ThreadFinished = function() {
    if (! {
     return {error: true, errorObj: undefined, errorMsg: 'JoiningMutexProxy.ThreadFinished() failed because the giving context is no longer active'};
    if (this._JoiningMutexContext._alreadyRun) {
     return {error: true, errorObj: undefined, errorMsg: 'JoiningMutexProxy.ThreadFinished() failed because the MutexProxy has already been run'};
    if (this._JoiningMutexContext.openThreads > 0) {
     this._alreadyRun = true;
     if (this._JoiningMutexContext.openThreads == 0) {
      // all threads finished
      if (this._JoiningMutexContext.executeOnce) {
       // this is going to be our only run of the callback function = false;
      return true;
     } else {
      // everything is OK but there are still outstanding threads to finish
      return false;
    } else {
     return {error: true, errorObj: undefined, errorMsg: 'JoiningMutexProxy.ThreadFinished() failed because there are no outstanding thread executions'};
  return new JoiningMutexContextProxy;
 contextCreate: function(sContextName, fZeroRunFunction, bSingleRun) {
  // make sure context is new
  var validName = sContextName;
  try {
   if (!validName) {
    validName = "AUTOGEN-"+this._contextGenID;
   if (this._contexts[validName]) {
    return {error: true, errorObj: undefined, errorMsg: 'JoiningMutex.contextCreate() failed because the giving context name already exists'};
   // verify that the name can be used as an object identifier (with throw an error if invalid)
   this._contexts[validName] = true;
   delete this._contexts[validName];
  } catch(e) {
   return {error: true, errorObj: e, errorMsg: 'an error occurred within JoiningMutex.contextCreate()'};
  // create new context object
  function JoiningMutexContext(inName, inFinishFunction, inSingleExecution) { = inName;
   this.callbackFinished = inFinishFunction;
   this.openThreads = 0;
   this.executeOnce = inSingleExecution;
   this.executionCount = 0; = true;
  var bSingleRun = Boolean.parseTo(bSingleRun);
  this._contexts[validName] = new JoiningMutexContext(validName, fZeroRunFunction, bSingleRun);
  // add ourselves to the thread count
  var cl_JoinMutextRef = this._contexts[validName];
  return this._createContextProxy(cl_JoinMutextRef);
 contextJoin: function(sContextName) {
  // make sure context already exists
  var validName = sContextName;
  if (!this._contexts[validName]) {
   return {error: true, errorObj: undefined, errorMsg: 'JoiningMutex.contextCreate() failed because the context name does not exist'};
  var cl_JoinMutextRef = this._contexts[validName];
  // Add this thread to the count
  return this._createContextProxy(cl_JoinMutextRef);
 contextJoinCreate: function(sContextName, fZeroRunFunction, bSingleRun) {
  // Join context or create it if it exists
  var ctx = false;
  if (!sContextName || !this._contexts[sContextName]) {
   ctx =, sContextName, fZeroRunFunction, bSingleRun);
  } else {
   ctx =, sContextName);
  return ctx;
 contextDestroy: function(sContextName) {
  if (!sContextName || !this._contexts[sContextName]) {
   return false;
  } else {
   // Garbage collection will not execute until all 
   // the JoiningMutexContextProxy are deleted so 
   // invalidate the context as well as delete it!
   this._contexts[sContextName].active = false;
   this._contexts[sContextName].callbackFinished = function() { return null; };
   delete this._contexts[sContextName];
   return true;

Wednesday, April 8, 2015

How did Firefox generate 50GB of crash reports?!

More interesting is that each crash report is small (several KB each) - meaning that Firefox created nearly 3 MILLION files in a single directory! Forget trying to view that directory in Windows explorer - the desktop will freeze. Most interesting is how long it takes to delete 3 million files from the command line: 5 hours and 26 minutes...  and that is on a workstation with 10,000 RPM drives!

What I am perplexed about is how Firefox managed to generate 3 million files and take up 50 GB of disk space without me realizing.  Very strange.

The files were found at:

C:\Users\username\AppData\Roaming\Mozilla\Firefox\Crash Reports\pending

Wednesday, March 11, 2015

"Blurred Lines" Violated Copyright, Why Was RIAA-style Justice Not Served?

Musician vs. Musician Lawsuits Play Out Like...

Yep, it is officialRobin Thicke's "Blurred Lines" was not only the longest running hit single of 2013 but is also an infringement of Marvin Gaye's song "Got to Give It Up". The court and jury did not go as far as saying that the song was "willful infringement" which would have opened the door for much larger fines.

So you might be wondering how much the guilty parties were forced to pay? The total copyright damages were $4 million and forfeiture of $3.3 million in profits. They were also fined $9,000 in statutory damages... just to make it clear they were wrong. This sums up a grand total of $7,309,000 USD or about $0.49 per copyright violation (according to Wikipedia's article about the song stated it sold 14.8 million copies).

We'll come back to that in a minute.

Musician vs. Listeners Lawsuits Play Out Like...

The RIAA has sued individuals for as much as $4.5 million and been awarded $675,000 against individuals sharing 30 songs (see Sony BMG v. Tenenbaum). In that case the court said that awarding $22,500 per song (only 15% of the total maximum penalty for willful violations) "comports with due process". The RIAA has not been totally evil, looking at Capitol Records, Inc. v. Thomas-Rasset you can see that they discounted a $1.9 million infringement award down to $54k (or from $80,000 per violation to $2,250 per violation).

So now I present the following thought. Why don't the courts treat musicians like the RIAA and other pro-copyright organizations treat their customers? If musicians are truly ok with their record labels going out and putting a $675k debt on a 20 year old college student who shares 30 songs, why don't they hold one another to the same standard? The college student wasn't trying to make money on his copyright infringement, whereas the writers of "Blurred Lines" were looking to make Scrooge McDuck amounts of money.

How Musician vs. Musician Lawsuits SHOULD Play Out

I am no legal expert but - in directing many successful patent prosecutions - I will say I know a bit about intellectual property laws. That being said, here's my opinion on how things should have played out.


It appears the court has found that "Blurred Lines" counts as an infringing work with remedies described in Section 504 of the current copyright laws. It appears that the lawsuit was filed asking for § 504(a)(1) damages ["the copyright owner’s actual damages and any additional profits of the infringer, as provided by subsection (b)"] wherein subsection (b) states "The copyright owner is entitled to recover the actual damages suffered by him or her as a result of the infringement, and any profits of the infringer that are attributable to the infringement and are not taken into account in computing the actual damages.In establishing the infringer’s profits,the copyright owner is required to present proof only of the infringer’s gross revenue, and the infringer is required to prove his or her deductible expenses and the elements of profit attributable to factors other than the copyrighted work.
My understanding is that this is not how consumers are sued. They appear to be sued under § 504(a)(2) which awards damages according to subsection (c). Unfortunately, § 504(c) applies to each work that is infringed and does not address how many times it was infringed (i.e. how many copies). I have also read in various places that if more than one work was violated that penalties would apply on a per-copy basis.
<TL;DR Legalese>

Remember when I said that the current judgement awarded comes out to $0.49 per copyright violation? That's because copyright is a set of rights that a person has over the fruits of their original work. Of those rights, two are quite relevant to this case. The exclusive right to reproduction of the original work, and the exclusive right to make derivative works (like remixes) of the original work. When a derivative work is made it gets its own copyright. The new copyright includes its own right-to-reproduce however, if the derivative work was not authorized then it is a single infringement of the original work. When the derivative work is reproduced (a copy is made) it can be argued (and has been so in the past) that each copy made is an act of violating the original work's exclusive right to make derivatives. Thus, 14.8 million copies sold is the same as getting busted with 14.8 million bootleg movies or a hard drive filled with 14.8 million illegally downloaded songs... but I digress.

Lets say that Robin Thicke and friends were proven to have infringed a second copyrighted work, then each copy of "Blurred Lines" sold could be counted as a separate (non-willful) violation with a penalty ranging between $750 and $30,000. Now here is the fun part, lets pretend we are the RIAA and multiply 14.8 million copies by $30,000 and file a $444 billion dollar lawsuit! Yes, the math is correct! The infringing musicians should not worry as the courts will most likely reduce the damages to a more reasonable $33.3 billion ($2,250 per copy just like everyone else).

Copyright Reform Needed

I think explicitly moving copyright remedies from "per-work" back to "per-copy" would be an effective way to force copyright reform. The cost per violation would drop and infringing consumers would be charged amounts that actually reflect the economic damage their file-sharing activities cause to musicians and record labels. In the end, the economic impact of a $33.3B judgement to major record label is about the same impact as a $675k judgement has on a 20 year old college student. After all, if seeking copyright justice is about destroying peoples lives, shouldn't it destroy the lives of multi-millionaires just as effectively?

Here are some more links for thought:

Wednesday, December 7, 2011

My team goes crazy in emails about reporting time off in a new Google calendar

Here's another day in the office. Everything is fine until one person takes off the "being professional" mask and all hell breaks out. I just had to join in the fun and add my 2 cents (and a zombie apocalypse reference)

Hey guys,

I'm not sure what happened to our google "Time Off" calendar, but it got all kinds of messed up. So, I had to delete it and start a new one. It is attached to each of your Gmail accounts. If you could put in any time you will be away from the office for the foreseeable future, that would be great.



Yes... so what I am looking at is the new, blank one, I assume. Ok, thanks.

I will add arbitrary and obscure antiquated religious holiday dates to Jxxxxx and Nxxxxx. There is a Guru Gobind day on January 5th.

Just kidding.



Calendars are for wussies.


[trim about 8 more hilarious email responses]


Einstein, Hawking and many people more brilliant that I have concluded that information cannot travel faster than light. However, recent scientific publications ( have raised questions about superluminal neutrinos breaking a fundamental law of physics stating that nothing can travel faster than the speed of light.

If it really is possible for subatomic particles to move faster than light then our fundamental understanding of time is critically flawed. Humanity's collective knowledge and understanding of reality is based on the concept that current events cannot be affected or influenced by future events. Even the philosophy of religion falls apart: cause and effect can be reversed, free will is nothing more than the present being influenced by future events and worse.

In the face of possible evidence contrary to accepted proofs that all of humanity is based upon, I am not sure if using ANY calenders would be the most prudent thing to do for our upcoming product launch. However, if it helps maintain a veneer of normality for the masses I will oblige the request. I will be working in the office until supporting evidence of superluminal neutrinos is proven, after which, I will be working remotely from my zombie bunker.

Cautiously your,

Monday, March 29, 2010

Sad but true joke about the world we live in...

From Pippa Sibley's column: Language of hope shows world divide

The UN sent a survey to the member nations with the following question: "Would you please state your honest opinion about the solution for the food shortage in the rest of the world?" Instead of responses, they received requests for clarification because nobody understood all the words in the question:

* African nations didn't understand the meaning of "food"
* Western European nations didn't understand the meaning of "shortage"
* Eastern European nations didn't understand the meaning of "honest"
* China didn't understand the meaning of "opinion"
* Middle Eastern nations didn't understand the meaning of "solution"
* South American nations didn't understand the meaning of "please"
* The United States didn't understand the meaning of "the rest of the world"

Friday, January 8, 2010

The most arcane bug of them all... Divide by Zero

It's interesting that even in modern times we still encounter the dreaded Divide by Zero error. I stumbled across this error recently in the Scriptaculous slider library.

There it was waiting to pounce from line 153 in the slider.js file upon any unsuspecting code that so happened to call the translateToPx() function. Here it is exposed to the harsh light of day:

  translateToPx: function(value) {
return Math.round(
((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
(value - this.range.start)) + "px";

There! There is the beating of it's hideous heart! For if a slider is initialized with a range whose start value is the same as its end value a most wicked zero is spawned from hell and possesses the denominator. IN THE NAME OF ALL THAT IS GOOD I CAST YEA BACK INTO THE HELL OF COMPLEX NUMBERS!

  translateToPx: function(value) {
try {
return Math.round(
((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
(value - this.range.start)) + "px";
} catch (e) {
return "0px";

Wednesday, October 8, 2008

Cute Thoughts

A few original quotes by myself and others...

"A candy bowl on a desk is the cubicle farm's equivalent of a salt lick." -HCEO

"Wall St has the best of both worlds, privatized profits and socialized losses" -unknown

Tuesday, September 30, 2008

Yet another reason is not worth your time...

This email I got today provides me yet another reason is not worth my time...

Great news! We have found new jobs matching your job search criteria!

Here are the results that were found on 9/30/2008:

Your saved search titled "C-Level Executive, Vice-President, Director" matched new jobs based on your search criteria. Listed below are the top 10 match(es)... (Just click on the job title to view a job.)

1. Sep, 30, Mechanic, Energi Personnel
2. Sep, 30, Weight Loss Management, Consultant
3. Sep, 30, MECHANICS, Company Confidential
4. Sep, 30, Prevention/ Tobacco Specialist
5. Sep, 30, Horse Stall Cleaner/Groomer, Post Electric Inc
6. Sep, 30, RN, Permian Endoscopy Center
7. Sep, 30, Director - Maintenance, Operat, Company Confidential
9. Sep, 30, Clerical/Secretarial Customer, Company Confidential
10. Sep, 30, Management assistant store ma, Company Confidential

This email notification may contain only a partial list of all your saved search results.
Click here to see all results.

Saturday, September 6, 2008

Nortel goes Machievelian against Cisco with new TV advertisement

Wow, I just saw a TV spot that would make Machiavelli proud. After little research I find out some very, very interesting facts. The very thing a they teach you good advertisement should do. Bravo ad guys, job VERY well done!

The ad I'm talking about is visually, very simple, and consists of people sitting in front of stacks of money. We aren't talking little stacks of money, more like "I just knocked off an armored truck"-sized stacks of money. As the camera slowly pans in, and melodramatic music plays, each of those people simply say the total amount of the stack sitting in front of them. "192,186 Dollars", "678,477 Dollars", "356,931 Dollars", "1,358,907 Dollars". On that last one the accountant sitting next to him chimes in "and 41 cents". I thought to myself "that was a well-played humorous twist". As the commercial played, and I felt the music and camera work do its magic on my emotions, I put down the box of takeout chinese I had been stuffing into my face and paid close attention to the details of the TV spot. I roll my eyes as I realize I am probably watching the latest Republican "fear Obama spot". As usual, my mind races to find the punchline before it's shown. "Obama will raise taxes for the working class..." No, these are all business people and the numbers are too large... "Obama's tax increases will hurt small business owners..." that's a bit cheesy, but would the Republicans really be so desperate, especially after such a strong showing by Palin coming off the recent Republican convention? Ok, I can't figure it out where this is going, I am very interested in what the punchline is (as well as doing a tear-down analysis of the commercial as an example of a well done advertisement). Ah yes, the music crescendos and cuts out and in the next shot, the first guy shown looks up from his pile of money and says "I don't think I want to pay this any more." And then comes the punchline, The Cisco Energy "Tax". My eyebrows quickly crawled two inches up my forehead and my jaw drops. WHAT THE HELL IS THAT?!?! I quickly cracked my usual mischievous grin, laughed and said in disbelief "Who the hell is attacking Cisco?!?!" and at the same time got my answer on the screen, Nortel.

Ok, my current projects are moving at a break neck speeds and I have a backlog of clients and new projects, so I am a few months behind on reading my computer industry magazines, but I hadn't noticed any Nortel ads pushing the energy-efficiency angle. Two minutes later, I am at my desk Googling "Cisco energy tax" and getting back only 6,260 hits. "This has got to be something that's really, really new. Something worth blogging about." So here I am, sharing with you what I've found - and reverse engineering it with you in the way only a hacker could. First, lets start with the actual video on YouTube.

Thursday, July 31, 2008

First Post!!!

So, after ages of putting it off and making excuses like "I'll host the blog on my own server" I have finally broken down and setup a blog here at Blogger. I'll host it proper on my domain at a later time.