Issue 1:
Motivation

Currently, Druid has three web consoles:

The coordinator console at http://coordinator:8081/#/, whose source lives at https://github.com/druid-io/druid-console

The overlord console at http://overlord:8090/.

The old coordinator console at http://coordinator:8081/old-console/.

Each one has a distinct design and there are very few cross-links between them. This leads to a disjointed user experience. Also, the fact that the sources for console (1) are not in the Druid repo make it difficult to keep it up-to-date.

A unified console would improve the user experience and would make it easier for Druid developers to keep it up-to-date as Druid's APIs evolve. The change also provides an opportunity to update their design and functionality a bit.

Proposed change

The proposed change is to create a new unified web console that subsumes the functionality of the three existing consoles. The unified UI would have its code live inside the Druid repository, making it easier to keep up to date.

The UI may end up being based on Druid SQL system tables (http://druid.io/docs/latest/querying/sql#retrieving-metadata), which would allow it to be more flexible than a console based on the currently-available coordinator and overlord APIs. The currently-available APIs were designed to support the existing consoles and return exactly what they need to know, but the system tables are more generic, and could power a more flexible new UI. (Imagine being able to show the distribution of data on historical nodes just for a particular datasource -- that kind of thing.) It would also allow the UI to more easily gain new powers as new columns or tables are added to system tables.

Since a unified UI would presumably need to access APIs on both the coordinator and overlord, we would need to either use proxying or CORS to allow that to happen. Proxying makes more sense, imo, since CORS requires extra configuration and some kind of consistent domain, which is not necessarily common amongst Druid deployments (many of which would use raw IPs). It could be hosted on the coordinator if the coordinator makes a proxy available to the overlord and broker. Or, it could be hosted on the router, which can already proxy to the coordinator, overlord, and broker (the former two via the optional management proxy). Or, it could be hosted on a new node type (CliWebConsole?). But we have enough node types already…

New or changed public interfaces

No new or changed APIs, but there would be a new human interface.

Migration plan and compatibility

Keep the existing consoles as-is and offer the new console as a new option. But deprecate the existing consoles and plan to remove them in a future version.

Rejected alternatives

None.

Issue 2:
Complement of roaring bit map returns incorrect result.

It seems that complement does not work on the last bit of the roaring bitmap.

I used following test code and all tests passed with concise bitmap but failed with roaring bitmap.

Result shows the last bit of roaring bitmap is unchanged even after complement operation.

public class RoaringBitmapTest
{
@Parameterized.Parameters
public static Iterable<Object[]> constructorFeeder()
{
return ImmutableList.of(
new Object[]{new ConciseBitmapFactory()},
new Object[]{new RoaringBitmapFactory()}
);
}

private final BitmapFactory testBitmapFactory;
public RoaringBitmapTest(BitmapFactory bitmapFactory)
{

this.testBitmapFactory = bitmapFactory;
}

@Test
public void testComplement1()
{
final MutableBitmap mutableBitmap = testBitmapFactory.makeEmptyMutableBitmap();
mutableBitmap.add(0);
mutableBitmap.add(2);
mutableBitmap.add(7);
ImmutableBitmap testBitmap = testBitmapFactory.makeImmutableBitmap(mutableBitmap);
ImmutableBitmap immutableBitmap = testBitmapFactory.complement(testBitmap, 8);
String result = immutableBitmap.toString().replaceAll("\\s","").split("\\[|\\]|\\{|\\}")[1];
Assert.assertEquals("1,3,4,5,6", result);
}

@Test
public void testComplement2()
{
final MutableBitmap mutableBitmap = testBitmapFactory.makeEmptyMutableBitmap();
mutableBitmap.add(0);
mutableBitmap.add(2);
ImmutableBitmap testBitmap = testBitmapFactory.makeImmutableBitmap(mutableBitmap);
ImmutableBitmap immutableBitmap = testBitmapFactory.complement(testBitmap, 4);
String result = immutableBitmap.toString().replaceAll("\\s","").split("\\[|\\]|\\{|\\}")[1];
Assert.assertEquals("1,3", result);
}

@Test
public void testComplement3()
{
final MutableBitmap mutableBitmap = testBitmapFactory.makeEmptyMutableBitmap();
mutableBitmap.add(4);
mutableBitmap.add(5);
ImmutableBitmap testBitmap = testBitmapFactory.makeImmutableBitmap(mutableBitmap);
ImmutableBitmap immutableBitmap = testBitmapFactory.complement(testBitmap, 10);
String result = immutableBitmap.toString().replaceAll("\\s","").split("\\[|\\]|\\{|\\}")[1];
Assert.assertEquals("0,1,2,3,6,7,8,9", result);
}
}