[jira] [Commented] (THRIFT-1297) Compiled javascript code does not write falsy values

2012-04-02 Thread Christoph Tavan (Commented) (JIRA)

[ 
https://issues.apache.org/jira/browse/THRIFT-1297?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13244360#comment-13244360
 ] 

Christoph Tavan commented on THRIFT-1297:
-

After some research I think this one is also a duplicate of THRIFT-1277.

> Compiled javascript code does not write falsy values
> 
>
> Key: THRIFT-1297
> URL: https://issues.apache.org/jira/browse/THRIFT-1297
> Project: Thrift
>  Issue Type: Bug
>  Components: JavaScript - Compiler, Node.js - Compiler
>Affects Versions: 0.7
> Environment: Windows 0.7 thrift compiler (pre built)
> http://www.apache.org/dyn/closer.cgi?path=/thrift/0.7.0/thrift-0.7.0.exe
> Thrift 0.7 compiled on Ubuntu shows same symptoms
>Reporter: Joris van der Wel
>Priority: Critical
>  Labels: compiler, javascript, regression
>
> I compiled cassandra.thrift using "thrift --gen js:node cassandra.thrift".
> When I use this code this results in the following error from cassandra / 
> thrift:
> {code}
> { name: 'TApplicationException',  type: 7,
>   message: 'Required field \'reversed\' was not found in serialized data! 
> Struct : SliceRange(start:null, finish:null, reversed:false, count:100)' }
> {code}
> If I look in the generated code, I find 
> {code}
> SliceRange.prototype.write = function(output) {
>   output.writeStructBegin('SliceRange');
>   if (this.start) {
> output.writeFieldBegin('start', Thrift.Type.STRING, 1);
> output.writeString(this.start);
> output.writeFieldEnd();
>   }
>   if (this.finish) {
> output.writeFieldBegin('finish', Thrift.Type.STRING, 2);
> output.writeString(this.finish);
> output.writeFieldEnd();
>   }
>   if (this.reversed) {
> output.writeFieldBegin('reversed', Thrift.Type.BOOL, 3);
> output.writeBool(this.reversed);
> output.writeFieldEnd();
>   }
>   if (this.count) {
> output.writeFieldBegin('count', Thrift.Type.I32, 4);
> output.writeI32(this.count);
> output.writeFieldEnd();
>   }
>   output.writeFieldStop();
>   output.writeStructEnd();
>   return;
> };
> {code}
> this.reversed is false and subsequently does not get sent
> If I look at the compiled version that was generated by 0.6.1 I see:
> {code}
> SliceRange.prototype.write = function(output){ 
>   output.writeStructBegin('SliceRange')
>   if (null != this.start) {
> output.writeFieldBegin('start', Thrift.Type.STRING, 1)
> output.writeString(this.start)
> output.writeFieldEnd()
>   }
>   if (null != this.finish) {
> output.writeFieldBegin('finish', Thrift.Type.STRING, 2)
> output.writeString(this.finish)
> output.writeFieldEnd()
>   }
>   if (null != this.reversed) {
> output.writeFieldBegin('reversed', Thrift.Type.BOOL, 3)
> output.writeBool(this.reversed)
> output.writeFieldEnd()
>   }
>   if (null != this.count) {
> output.writeFieldBegin('count', Thrift.Type.I32, 4)
> output.writeI32(this.count)
> output.writeFieldEnd()
>   }
>   output.writeFieldStop()
>   output.writeStructEnd()
>   return
> }
> {code}
> null is also not be completely correct, the solution would be:
> {code}
> ...
> if (undefined !== this.reversed)
> ...
> {code}
> Unless this change was intentional and breaks things because cassandra is 
> perhaps using an old thrift version?

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: 
https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira




[jira] [Commented] (THRIFT-1297) Compiled javascript code does not write falsy values

2012-03-28 Thread Larregoity (Commented) (JIRA)

[ 
https://issues.apache.org/jira/browse/THRIFT-1297?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13240547#comment-13240547
 ] 

Larregoity commented on THRIFT-1297:


Thanks for the work around.
Unfortunately, for booleans, wrapping using new Boolean(bool) this is not 
enough:

 var bool = false;
 new Boolean(bool)  is not falsy, so it will be written.

But as in lib.js, the writeBool method is:
 writeBool: function(value) {
this.tstack.push(value ? 1 : 0);
},
The value pushed on the wire will always be 1.

I work around this issue using:

var oldWriteBool = Thrift.Protocol.prototype.writeBool;
var newWriteBool = function (value) {
var fixedValue = value;
if (value instanceof Boolean) {
fixedValue = value.valueOf();
}
oldWriteBool.call(this, fixedValue);
}
Thrift.Protocol.prototype.writeBool = newWriteBool;

and then I can pass false booleans by wrapping them into new Boolean.


> Compiled javascript code does not write falsy values
> 
>
> Key: THRIFT-1297
> URL: https://issues.apache.org/jira/browse/THRIFT-1297
> Project: Thrift
>  Issue Type: Bug
>  Components: JavaScript - Compiler, Node.js - Compiler
>Affects Versions: 0.7
> Environment: Windows 0.7 thrift compiler (pre built)
> http://www.apache.org/dyn/closer.cgi?path=/thrift/0.7.0/thrift-0.7.0.exe
> Thrift 0.7 compiled on Ubuntu shows same symptoms
>Reporter: Joris van der Wel
>Priority: Critical
>  Labels: compiler, javascript, regression
>
> I compiled cassandra.thrift using "thrift --gen js:node cassandra.thrift".
> When I use this code this results in the following error from cassandra / 
> thrift:
> {code}
> { name: 'TApplicationException',  type: 7,
>   message: 'Required field \'reversed\' was not found in serialized data! 
> Struct : SliceRange(start:null, finish:null, reversed:false, count:100)' }
> {code}
> If I look in the generated code, I find 
> {code}
> SliceRange.prototype.write = function(output) {
>   output.writeStructBegin('SliceRange');
>   if (this.start) {
> output.writeFieldBegin('start', Thrift.Type.STRING, 1);
> output.writeString(this.start);
> output.writeFieldEnd();
>   }
>   if (this.finish) {
> output.writeFieldBegin('finish', Thrift.Type.STRING, 2);
> output.writeString(this.finish);
> output.writeFieldEnd();
>   }
>   if (this.reversed) {
> output.writeFieldBegin('reversed', Thrift.Type.BOOL, 3);
> output.writeBool(this.reversed);
> output.writeFieldEnd();
>   }
>   if (this.count) {
> output.writeFieldBegin('count', Thrift.Type.I32, 4);
> output.writeI32(this.count);
> output.writeFieldEnd();
>   }
>   output.writeFieldStop();
>   output.writeStructEnd();
>   return;
> };
> {code}
> this.reversed is false and subsequently does not get sent
> If I look at the compiled version that was generated by 0.6.1 I see:
> {code}
> SliceRange.prototype.write = function(output){ 
>   output.writeStructBegin('SliceRange')
>   if (null != this.start) {
> output.writeFieldBegin('start', Thrift.Type.STRING, 1)
> output.writeString(this.start)
> output.writeFieldEnd()
>   }
>   if (null != this.finish) {
> output.writeFieldBegin('finish', Thrift.Type.STRING, 2)
> output.writeString(this.finish)
> output.writeFieldEnd()
>   }
>   if (null != this.reversed) {
> output.writeFieldBegin('reversed', Thrift.Type.BOOL, 3)
> output.writeBool(this.reversed)
> output.writeFieldEnd()
>   }
>   if (null != this.count) {
> output.writeFieldBegin('count', Thrift.Type.I32, 4)
> output.writeI32(this.count)
> output.writeFieldEnd()
>   }
>   output.writeFieldStop()
>   output.writeStructEnd()
>   return
> }
> {code}
> null is also not be completely correct, the solution would be:
> {code}
> ...
> if (undefined !== this.reversed)
> ...
> {code}
> Unless this change was intentional and breaks things because cassandra is 
> perhaps using an old thrift version?

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: 
https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira




[jira] [Commented] (THRIFT-1297) Compiled javascript code does not write falsy values

2012-02-10 Thread Kenny (Commented) (JIRA)

[ 
https://issues.apache.org/jira/browse/THRIFT-1297?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13205754#comment-13205754
 ] 

Kenny commented on THRIFT-1297:
---

Thanks for the workaround Joris. This is still broken. I finally ran WireShark 
captures to see why my i32s were ending up 'undefined' in Erlang when passed as 
0.

Called getEvents(___, 0):
[1,"getEvents",1,0,{"1":{"i64":7426226942022814}}]

Called getEvents(___, 1):
[1,"getEvents",1,0,{"1":{"i64":7426226942022814},"2":{"i32":1}}]

Called getEvents(___, new Number(0):
[1,"getEvents",1,0,{"1":{"i64":7426226942022814},"2":{"i32":0}}]

> Compiled javascript code does not write falsy values
> 
>
> Key: THRIFT-1297
> URL: https://issues.apache.org/jira/browse/THRIFT-1297
> Project: Thrift
>  Issue Type: Bug
>  Components: JavaScript - Compiler, Node.js - Compiler
>Affects Versions: 0.7
> Environment: Windows 0.7 thrift compiler (pre built)
> http://www.apache.org/dyn/closer.cgi?path=/thrift/0.7.0/thrift-0.7.0.exe
> Thrift 0.7 compiled on Ubuntu shows same symptoms
>Reporter: Joris van der Wel
>Priority: Critical
>  Labels: compiler, javascript, regression
>
> I compiled cassandra.thrift using "thrift --gen js:node cassandra.thrift".
> When I use this code this results in the following error from cassandra / 
> thrift:
> {code}
> { name: 'TApplicationException',  type: 7,
>   message: 'Required field \'reversed\' was not found in serialized data! 
> Struct : SliceRange(start:null, finish:null, reversed:false, count:100)' }
> {code}
> If I look in the generated code, I find 
> {code}
> SliceRange.prototype.write = function(output) {
>   output.writeStructBegin('SliceRange');
>   if (this.start) {
> output.writeFieldBegin('start', Thrift.Type.STRING, 1);
> output.writeString(this.start);
> output.writeFieldEnd();
>   }
>   if (this.finish) {
> output.writeFieldBegin('finish', Thrift.Type.STRING, 2);
> output.writeString(this.finish);
> output.writeFieldEnd();
>   }
>   if (this.reversed) {
> output.writeFieldBegin('reversed', Thrift.Type.BOOL, 3);
> output.writeBool(this.reversed);
> output.writeFieldEnd();
>   }
>   if (this.count) {
> output.writeFieldBegin('count', Thrift.Type.I32, 4);
> output.writeI32(this.count);
> output.writeFieldEnd();
>   }
>   output.writeFieldStop();
>   output.writeStructEnd();
>   return;
> };
> {code}
> this.reversed is false and subsequently does not get sent
> If I look at the compiled version that was generated by 0.6.1 I see:
> {code}
> SliceRange.prototype.write = function(output){ 
>   output.writeStructBegin('SliceRange')
>   if (null != this.start) {
> output.writeFieldBegin('start', Thrift.Type.STRING, 1)
> output.writeString(this.start)
> output.writeFieldEnd()
>   }
>   if (null != this.finish) {
> output.writeFieldBegin('finish', Thrift.Type.STRING, 2)
> output.writeString(this.finish)
> output.writeFieldEnd()
>   }
>   if (null != this.reversed) {
> output.writeFieldBegin('reversed', Thrift.Type.BOOL, 3)
> output.writeBool(this.reversed)
> output.writeFieldEnd()
>   }
>   if (null != this.count) {
> output.writeFieldBegin('count', Thrift.Type.I32, 4)
> output.writeI32(this.count)
> output.writeFieldEnd()
>   }
>   output.writeFieldStop()
>   output.writeStructEnd()
>   return
> }
> {code}
> null is also not be completely correct, the solution would be:
> {code}
> ...
> if (undefined !== this.reversed)
> ...
> {code}
> Unless this change was intentional and breaks things because cassandra is 
> perhaps using an old thrift version?

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: 
https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira




[jira] [Commented] (THRIFT-1297) Compiled javascript code does not write falsy values

2011-10-27 Thread Joris van der Wel (Commented) (JIRA)

[ 
https://issues.apache.org/jira/browse/THRIFT-1297?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13137153#comment-13137153
 ] 

Joris van der Wel commented on THRIFT-1297:
---

I just ran into this again and spent a day tracking down what was going on.
I noticed some more things:

Setting a value to falsy, results in the value not being sent over the network. 
If this value is required, it results in an exception on the server (c++ non 
blocking) which closes the socket.

It also happens for function parameters. On my c++ server, thrift ended up 
giving me an uninitialized value, so the effect was seemingly random.

I currently work around it by using new Number(0), new String(''), etc (which 
are not falsy).
But this bug pretty much breaks thrifts node.js support

> Compiled javascript code does not write falsy values
> 
>
> Key: THRIFT-1297
> URL: https://issues.apache.org/jira/browse/THRIFT-1297
> Project: Thrift
>  Issue Type: Bug
>  Components: JavaScript - Compiler, Node.js - Compiler
>Affects Versions: 0.7
> Environment: Windows 0.7 thrift compiler (pre built)
> http://www.apache.org/dyn/closer.cgi?path=/thrift/0.7.0/thrift-0.7.0.exe
> Thrift 0.7 compiled on Ubuntu shows same symptoms
>Reporter: Joris van der Wel
>Priority: Critical
>  Labels: compiler, javascript, regression
>
> I compiled cassandra.thrift using "thrift --gen js:node cassandra.thrift".
> When I use this code this results in the following error from cassandra / 
> thrift:
> {code}
> { name: 'TApplicationException',  type: 7,
>   message: 'Required field \'reversed\' was not found in serialized data! 
> Struct : SliceRange(start:null, finish:null, reversed:false, count:100)' }
> {code}
> If I look in the generated code, I find 
> {code}
> SliceRange.prototype.write = function(output) {
>   output.writeStructBegin('SliceRange');
>   if (this.start) {
> output.writeFieldBegin('start', Thrift.Type.STRING, 1);
> output.writeString(this.start);
> output.writeFieldEnd();
>   }
>   if (this.finish) {
> output.writeFieldBegin('finish', Thrift.Type.STRING, 2);
> output.writeString(this.finish);
> output.writeFieldEnd();
>   }
>   if (this.reversed) {
> output.writeFieldBegin('reversed', Thrift.Type.BOOL, 3);
> output.writeBool(this.reversed);
> output.writeFieldEnd();
>   }
>   if (this.count) {
> output.writeFieldBegin('count', Thrift.Type.I32, 4);
> output.writeI32(this.count);
> output.writeFieldEnd();
>   }
>   output.writeFieldStop();
>   output.writeStructEnd();
>   return;
> };
> {code}
> this.reversed is false and subsequently does not get sent
> If I look at the compiled version that was generated by 0.6.1 I see:
> {code}
> SliceRange.prototype.write = function(output){ 
>   output.writeStructBegin('SliceRange')
>   if (null != this.start) {
> output.writeFieldBegin('start', Thrift.Type.STRING, 1)
> output.writeString(this.start)
> output.writeFieldEnd()
>   }
>   if (null != this.finish) {
> output.writeFieldBegin('finish', Thrift.Type.STRING, 2)
> output.writeString(this.finish)
> output.writeFieldEnd()
>   }
>   if (null != this.reversed) {
> output.writeFieldBegin('reversed', Thrift.Type.BOOL, 3)
> output.writeBool(this.reversed)
> output.writeFieldEnd()
>   }
>   if (null != this.count) {
> output.writeFieldBegin('count', Thrift.Type.I32, 4)
> output.writeI32(this.count)
> output.writeFieldEnd()
>   }
>   output.writeFieldStop()
>   output.writeStructEnd()
>   return
> }
> {code}
> null is also not be completely correct, the solution would be:
> {code}
> ...
> if (undefined !== this.reversed)
> ...
> {code}
> Unless this change was intentional and breaks things because cassandra is 
> perhaps using an old thrift version?

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: 
https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira




[jira] [Commented] (THRIFT-1297) Compiled javascript code does not write falsy values

2011-08-26 Thread Joris van der Wel (JIRA)

[ 
https://issues.apache.org/jira/browse/THRIFT-1297?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13091857#comment-13091857
 ] 

Joris van der Wel commented on THRIFT-1297:
---

I am not sure what is considered null in thrift.

My issue is that .write is not called at all when the expression is falsy 
(null, false, undefined, 0, '', NaN). I think the value is not sent over the 
network at all. If that is considered as null by the receiving end, it could be 
the same issue.

If null and a non existing value are not considered the same, it is a different 
issue and strict equality would be needed (!== ===)


> Compiled javascript code does not write falsy values
> 
>
> Key: THRIFT-1297
> URL: https://issues.apache.org/jira/browse/THRIFT-1297
> Project: Thrift
>  Issue Type: Bug
>  Components: JavaScript - Compiler
>Affects Versions: 0.7
> Environment: Windows 0.7 thrift compiler (pre built)
> http://www.apache.org/dyn/closer.cgi?path=/thrift/0.7.0/thrift-0.7.0.exe
> Thrift 0.7 compiled on Ubuntu shows same symptoms
>Reporter: Joris van der Wel
>Priority: Critical
>  Labels: compiler, javascript, regression
>
> I compiled cassandra.thrift using "thrift --gen js:node cassandra.thrift".
> When I use this code this results in the following error from cassandra / 
> thrift:
> {code}
> { name: 'TApplicationException',  type: 7,
>   message: 'Required field \'reversed\' was not found in serialized data! 
> Struct : SliceRange(start:null, finish:null, reversed:false, count:100)' }
> {code}
> If I look in the generated code, I find 
> {code}
> SliceRange.prototype.write = function(output) {
>   output.writeStructBegin('SliceRange');
>   if (this.start) {
> output.writeFieldBegin('start', Thrift.Type.STRING, 1);
> output.writeString(this.start);
> output.writeFieldEnd();
>   }
>   if (this.finish) {
> output.writeFieldBegin('finish', Thrift.Type.STRING, 2);
> output.writeString(this.finish);
> output.writeFieldEnd();
>   }
>   if (this.reversed) {
> output.writeFieldBegin('reversed', Thrift.Type.BOOL, 3);
> output.writeBool(this.reversed);
> output.writeFieldEnd();
>   }
>   if (this.count) {
> output.writeFieldBegin('count', Thrift.Type.I32, 4);
> output.writeI32(this.count);
> output.writeFieldEnd();
>   }
>   output.writeFieldStop();
>   output.writeStructEnd();
>   return;
> };
> {code}
> this.reversed is false and subsequently does not get sent
> If I look at the compiled version that was generated by 0.6.1 I see:
> {code}
> SliceRange.prototype.write = function(output){ 
>   output.writeStructBegin('SliceRange')
>   if (null != this.start) {
> output.writeFieldBegin('start', Thrift.Type.STRING, 1)
> output.writeString(this.start)
> output.writeFieldEnd()
>   }
>   if (null != this.finish) {
> output.writeFieldBegin('finish', Thrift.Type.STRING, 2)
> output.writeString(this.finish)
> output.writeFieldEnd()
>   }
>   if (null != this.reversed) {
> output.writeFieldBegin('reversed', Thrift.Type.BOOL, 3)
> output.writeBool(this.reversed)
> output.writeFieldEnd()
>   }
>   if (null != this.count) {
> output.writeFieldBegin('count', Thrift.Type.I32, 4)
> output.writeI32(this.count)
> output.writeFieldEnd()
>   }
>   output.writeFieldStop()
>   output.writeStructEnd()
>   return
> }
> {code}
> null is also not be completely correct, the solution would be:
> {code}
> ...
> if (undefined !== this.reversed)
> ...
> {code}
> Unless this change was intentional and breaks things because cassandra is 
> perhaps using an old thrift version?

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira




[jira] [Commented] (THRIFT-1297) Compiled javascript code does not write falsy values

2011-08-26 Thread Jake Farrell (JIRA)

[ 
https://issues.apache.org/jira/browse/THRIFT-1297?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13091828#comment-13091828
 ] 

Jake Farrell commented on THRIFT-1297:
--

Is this the same issue as THRIFT-1277 ?

> Compiled javascript code does not write falsy values
> 
>
> Key: THRIFT-1297
> URL: https://issues.apache.org/jira/browse/THRIFT-1297
> Project: Thrift
>  Issue Type: Bug
>  Components: JavaScript - Compiler
>Affects Versions: 0.7
> Environment: Windows 0.7 thrift compiler (pre built)
> http://www.apache.org/dyn/closer.cgi?path=/thrift/0.7.0/thrift-0.7.0.exe
> Thrift 0.7 compiled on Ubuntu shows same symptoms
>Reporter: Joris van der Wel
>Priority: Critical
>  Labels: compiler, javascript, regression
>
> I compiled cassandra.thrift using "thrift --gen js:node cassandra.thrift".
> When I use this code this results in the following error from cassandra / 
> thrift:
> {code}
> { name: 'TApplicationException',  type: 7,
>   message: 'Required field \'reversed\' was not found in serialized data! 
> Struct : SliceRange(start:null, finish:null, reversed:false, count:100)' }
> {code}
> If I look in the generated code, I find 
> {code}
> SliceRange.prototype.write = function(output) {
>   output.writeStructBegin('SliceRange');
>   if (this.start) {
> output.writeFieldBegin('start', Thrift.Type.STRING, 1);
> output.writeString(this.start);
> output.writeFieldEnd();
>   }
>   if (this.finish) {
> output.writeFieldBegin('finish', Thrift.Type.STRING, 2);
> output.writeString(this.finish);
> output.writeFieldEnd();
>   }
>   if (this.reversed) {
> output.writeFieldBegin('reversed', Thrift.Type.BOOL, 3);
> output.writeBool(this.reversed);
> output.writeFieldEnd();
>   }
>   if (this.count) {
> output.writeFieldBegin('count', Thrift.Type.I32, 4);
> output.writeI32(this.count);
> output.writeFieldEnd();
>   }
>   output.writeFieldStop();
>   output.writeStructEnd();
>   return;
> };
> {code}
> this.reversed is false and subsequently does not get sent
> If I look at the compiled version that was generated by 0.6.1 I see:
> {code}
> SliceRange.prototype.write = function(output){ 
>   output.writeStructBegin('SliceRange')
>   if (null != this.start) {
> output.writeFieldBegin('start', Thrift.Type.STRING, 1)
> output.writeString(this.start)
> output.writeFieldEnd()
>   }
>   if (null != this.finish) {
> output.writeFieldBegin('finish', Thrift.Type.STRING, 2)
> output.writeString(this.finish)
> output.writeFieldEnd()
>   }
>   if (null != this.reversed) {
> output.writeFieldBegin('reversed', Thrift.Type.BOOL, 3)
> output.writeBool(this.reversed)
> output.writeFieldEnd()
>   }
>   if (null != this.count) {
> output.writeFieldBegin('count', Thrift.Type.I32, 4)
> output.writeI32(this.count)
> output.writeFieldEnd()
>   }
>   output.writeFieldStop()
>   output.writeStructEnd()
>   return
> }
> {code}
> null is also not be completely correct, the solution would be:
> {code}
> ...
> if (undefined !== this.reversed)
> ...
> {code}
> Unless this change was intentional and breaks things because cassandra is 
> perhaps using an old thrift version?

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira