var loader = { show : function( element ) { $( element ) .addClass( 'loader' ); }, hide : function( element ) { $( element ) .removeClass( 'loader' ); } }; var sammy = $.sammy ( function() { this.bind ( 'run', function( event, config ) { if( 0 === config.start_url.length ) { location.href = '#/'; return false; } } ); this.bind ( 'ping', function( event ) { $.ajax ( { url : $( this.params.element ).attr( 'rel' ) + '?wt=json&ts=' + (new Date).getTime(), dataType : 'json', context: this.params.element, beforeSend : function( arr, form, options ) { loader.show( this ); }, success : function( response, text_status, xhr ) { $( this ) .removeAttr( 'title' ); $( this ).parents( 'li' ) .removeClass( 'error' ); var qtime_element = $( '.qtime', this ); if( 0 === qtime_element.size() ) { qtime_element = $( ' ()' ); $( this ) .append ( qtime_element ); } $( 'span', qtime_element ) .html( response.responseHeader.QTime + 'ms' ); }, error : function( xhr, text_status, error_thrown ) { $( this ) .attr( 'title', '/admin/ping is not configured (' + xhr.status + ': ' + error_thrown + ')' ); $( this ).parents( 'li' ) .addClass( 'error' ); }, complete : function( xhr, text_status ) { loader.hide( this ); } } ); return false; } ); // activate_core this.before ( {}, function() { $( 'li[id].active', app.menu_element ) .removeClass( 'active' ); $( 'ul li.active', app.menu_element ) .removeClass( 'active' ); if( this.params.splat ) { var active_element = $( '#' + this.params.splat[0], app.menu_element ); active_element .addClass( 'active' ); if( this.params.splat[1] ) { $( '.' + this.params.splat[1], active_element ) .addClass( 'active' ); } if( !active_element.hasClass( 'global' ) ) { this.active_core = active_element; } } } ); // #/cloud this.get ( /^#\/(cloud)$/, function( context ) { var content_element = $( '#content' ); $.get ( 'tpl/cloud.html', function( template ) { content_element .html( template ); var zookeeper_element = $( '#zookeeper', content_element ); $.ajax ( { url : app.config.zookeeper_path, dataType : 'json', context : $( '.content', zookeeper_element ), beforeSend : function( xhr, settings ) { this .html( '
' + threadDumpData[i].lock + '
'; } if( threadDumpData[i].stackTrace && 0 !== threadDumpData[i].stackTrace.length ) { classes.push( 'stacktrace' ); var stack_trace = threadDumpData[i].stackTrace .join( '' +
xhr.responseText.replace( /\/g, '>' ) +
'
'
);
this.html( code );
if( 'success' === text_status )
{
hljs.highlightBlock( code.get(0) );
}
}
}
);
}
dataimport_fetch_config();
$( '.toggle', config_element )
.die( 'click' )
.live
(
'click',
function( event )
{
$( this ).parents( '.block' )
.toggleClass( 'hidden' );
return false;
}
)
var reload_config_element = $( '.reload_config', config_element );
reload_config_element
.die( 'click' )
.live
(
'click',
function( event )
{
$.ajax
(
{
url : core_basepath + '/select?qt=' + current_handler + '&command=reload-config',
dataType : 'xml',
context: $( this ),
beforeSend : function( xhr, settings )
{
this
.addClass( 'loader' );
},
success : function( response, text_status, xhr )
{
this
.addClass( 'success' );
window.setTimeout
(
function()
{
reload_config_element
.removeClass( 'success' );
},
5000
);
},
error : function( xhr, text_status, error_thrown )
{
this
.addClass( 'error' );
},
complete : function( xhr, text_status )
{
this
.removeClass( 'loader' );
dataimport_fetch_config();
}
}
);
return false;
}
)
// state
function dataimport_fetch_status()
{
$.ajax
(
{
url : core_basepath + '/select?qt=' + current_handler + '&command=status',
dataType : 'xml',
beforeSend : function( xhr, settings )
{
},
success : function( response, text_status, xhr )
{
var state_element = $( '#current_state', content_element );
var status = $( 'str[name="status"]', response ).text();
var rollback_element = $( 'str[name="Rolledback"]', response );
var messages_count = $( 'lst[name="statusMessages"] str', response ).size();
var started_at = $( 'str[name="Full Dump Started"]', response ).text();
if( !started_at )
{
started_at = (new Date()).toGMTString();
}
function dataimport_compute_details( response, details_element )
{
var details = [];
var requests = parseInt( $( 'str[name="Total Requests made to DataSource"]', response ).text() );
if( NaN !== requests )
{
details.push
(
'Requests: ' +
requests
);
}
var fetched = parseInt( $( 'str[name="Total Rows Fetched"]', response ).text() );
if( NaN !== fetched )
{
details.push
(
'Fetched: ' +
fetched
);
}
var skipped = parseInt( $( 'str[name="Total Documents Skipped"]', response ).text() );
if( NaN !== requests )
{
details.push
(
'Skipped: ' +
skipped
);
}
var processed = parseInt( $( 'str[name="Total Documents Processed"]', response ).text() );
if( NaN !== processed )
{
details.push
(
'Processed: ' +
processed
);
}
details_element
.html( details.join( ', ' ) );
}
state_element
.removeClass( 'indexing' )
.removeClass( 'success' )
.removeClass( 'failure' );
$( '.info', state_element )
.removeClass( 'loader' );
if( 0 !== rollback_element.size() )
{
state_element
.addClass( 'failure' )
.show();
$( '.info strong', state_element )
.text( $( 'str[name=""]', response ).text() );
console.debug( 'rollback @ ', rollback_element.text() );
}
else if( 'idle' === status && 0 !== messages_count )
{
state_element
.addClass( 'success' )
.show();
$( '.time', state_element )
.text( started_at )
.timeago();
$( '.info strong', state_element )
.text( $( 'str[name=""]', response ).text() );
dataimport_compute_details( response, $( '.info .details', state_element ) );
}
else if( 'busy' === status )
{
state_element
.addClass( 'indexing' )
.show();
$( '.time', state_element )
.text( started_at )
.timeago();
$( '.info', state_element )
.addClass( 'loader' );
$( '.info strong', state_element )
.text( 'Indexing ...' );
dataimport_compute_details( response, $( '.info .details', state_element ) );
window.setTimeout( dataimport_fetch_status, 2000 );
}
else
{
state_element.hide();
}
},
error : function( xhr, text_status, error_thrown )
{
console.debug( arguments );
},
complete : function( xhr, text_status )
{
}
}
);
}
dataimport_fetch_status();
// form
$( 'form', form_element )
.die( 'submit' )
.live
(
'submit',
function( event )
{
$.ajax
(
{
url : core_basepath + '/select?qt=' + current_handler + '&command=full-import',
dataType : 'xml',
beforeSend : function( xhr, settings )
{
},
success : function( response, text_status, xhr )
{
console.debug( response );
dataimport_fetch_status();
},
error : function( xhr, text_status, error_thrown )
{
console.debug( arguments );
},
complete : function( xhr, text_status )
{
}
}
);
return false;
}
);
}
);
}
);
this.bind
(
'plugins_load',
function( event, params )
{
var callback = function()
{
params.callback( app.plugin_data.plugin_data, app.plugin_data.sort_table, app.plugin_data.types );
}
if( app.plugin_data )
{
callback( app.plugin_data );
return true;
}
var core_basepath = params.active_core.attr( 'data-basepath' );
$.ajax
(
{
url : core_basepath + '/admin/mbeans?stats=true&wt=json',
dataType : 'json',
beforeSend : function( xhr, settings )
{
},
success : function( response, text_status, xhr )
{
var types = [];
var sort_table = {};
var plugin_data = {};
var types_obj = {};
var plugin_key = null;
for( var i = 0; i < response['solr-mbeans'].length; i++ )
{
if( !( i % 2 ) )
{
plugin_key = response['solr-mbeans'][i];
}
else
{
plugin_data[plugin_key] = response['solr-mbeans'][i];
}
}
for( var key in plugin_data )
{
sort_table[key] = {
url : [],
component : [],
handler : []
};
for( var part_key in plugin_data[key] )
{
if( 0 < part_key.indexOf( '.' ) )
{
types_obj[key] = true;
sort_table[key]['handler'].push( part_key );
}
else if( 0 === part_key.indexOf( '/' ) )
{
types_obj[key] = true;
sort_table[key]['url'].push( part_key );
}
else
{
types_obj[key] = true;
sort_table[key]['component'].push( part_key );
}
}
}
for( var type in types_obj )
{
types.push( type );
}
types.sort();
app.plugin_data = {
'plugin_data' : plugin_data,
'sort_table' : sort_table,
'types' : types
}
$.get
(
'tpl/plugins.html',
function( template )
{
$( '#content' )
.html( template );
callback( app.plugin_data );
}
);
},
error : function( xhr, text_status, error_thrown)
{
},
complete : function( xhr, text_status )
{
}
}
);
}
);
// #/:core/plugins/$type
this.get
(
/^#\/([\w\d]+)\/(plugins)\/(\w+)$/,
function( context )
{
var content_element = $( '#content' );
var type = context.params.splat[2].toUpperCase();
var context_path = context.path.split( '?' ).shift();
sammy.trigger
(
'plugins_load',
{
active_core : this.active_core,
callback : function( plugin_data, plugin_sort, types )
{
var frame_element = $( '#frame', content_element );
var navigation_element = $( '#navigation ul', content_element );
var navigation_content = [];
for( var i = 0; i < types.length; i++ )
{
var type_url = context.params.splat[0] + '/' +
context.params.splat[1] + '/' +
types[i].toLowerCase();
navigation_content.push
(
'P | ' + "\n"; type_content += parts['position'].join( "\n" ) + "\n"; type_content += '
---|
T | ' + "\n"; type_content += parts['text'].join( "\n" ) + "\n"; type_content += '
T | ' + "\n"; type_content += parts['type'].join( "\n" ) + "\n"; type_content += '
R | ' + "\n"; type_content += parts['start-end'].join( "\n" ) + "\n"; type_content += '
' +
xhr.responseText.replace( /\/g, '>' ) +
'
'
);
this.html( code );
if( 'success' === text_status )
{
hljs.highlightBlock( code.get(0) );
}
}
}
);
}
);
// #/:core
this.get
(
/^#\/([\w\d]+)$/,
function( context )
{
var core_basepath = this.active_core.attr( 'data-basepath' );
var content_element = $( '#content' );
content_element
.removeClass( 'single' );
var core_menu = $( 'ul', this.active_core );
if( !core_menu.data( 'admin-extra-loaded' ) )
{
core_menu.data( 'admin-extra-loaded', new Date() );
$.get
(
core_basepath + '/admin/file/?file=admin-extra.menu-top.html',
function( menu_extra )
{
core_menu
.prepend( menu_extra );
}
);
$.get
(
core_basepath + '/admin/file/?file=admin-extra.menu-bottom.html',
function( menu_extra )
{
core_menu
.append( menu_extra );
}
);
}
$.get
(
'tpl/dashboard.html',
function( template )
{
content_element
.html( template );
var dashboard_element = $( '#dashboard' );
$.ajax
(
{
url : core_basepath + '/admin/luke?wt=json',
dataType : 'json',
context : $( '#statistics', dashboard_element ),
beforeSend : function( xhr, settings )
{
$( 'h2', this )
.addClass( 'loader' );
$( '.message', this )
.show()
.html( 'Loading ...' );
$( '.content' )
.hide();
},
success : function( response, text_status, xhr )
{
$( '.message', this )
.empty()
.hide();
$( '.content', this )
.show();
var data = {
'index_num-docs' : response['index']['numDocs'],
'index_max-doc' : response['index']['maxDoc'],
'index_last-modified' : response['index']['lastModified']
};
for( var key in data )
{
$( '.' + key, this )
.show();
$( '.value.' + key, this )
.html( data[key] );
}
var optimized_element = $( '.value.index_optimized', this );
if( response['index']['optimized'] )
{
optimized_element
.addClass( 'ico-1' );
$( 'span', optimized_element )
.html( 'yes' );
}
else
{
optimized_element
.addClass( 'ico-0' );
$( 'span', optimized_element )
.html( 'no' );
}
var current_element = $( '.value.index_current', this );
if( response['index']['current'] )
{
current_element
.addClass( 'ico-1' );
$( 'span', current_element )
.html( 'yes' );
}
else
{
current_element
.addClass( 'ico-0' );
$( 'span', current_element )
.html( 'no' );
}
var deletions_element = $( '.value.index_has-deletions', this );
if( response['index']['hasDeletions'] )
{
deletions_element.prev()
.show();
deletions_element
.show()
.addClass( 'ico-0' );
$( 'span', deletions_element )
.html( 'yes' );
}
$( 'a', optimized_element )
.die( 'click' )
.live
(
'click',
function( event )
{
$.ajax
(
{
url : core_basepath + '/update?optimize=true&waitFlush=true&wt=json',
dataType : 'json',
context : $( this ),
beforeSend : function( xhr, settings )
{
this
.addClass( 'loader' );
},
success : function( response, text_status, xhr )
{
this.parents( 'dd' )
.removeClass( 'ico-0' )
.addClass( 'ico-1' );
},
error : function( xhr, text_status, error_thrown)
{
console.warn( 'd0h, optimize broken!' );
},
complete : function( xhr, text_status )
{
this
.removeClass( 'loader' );
}
}
);
}
);
$( '.timeago', this )
.timeago();
},
error : function( xhr, text_status, error_thrown )
{
this
.addClass( 'disabled' );
$( '.message', this )
.show()
.html( 'Luke is not configured' );
},
complete : function( xhr, text_status )
{
$( 'h2', this )
.removeClass( 'loader' );
}
}
);
$.ajax
(
{
url : core_basepath + '/replication?command=details&wt=json',
dataType : 'json',
context : $( '#replication', dashboard_element ),
beforeSend : function( xhr, settings )
{
$( 'h2', this )
.addClass( 'loader' );
$( '.message', this )
.show()
.html( 'Loading' );
$( '.content', this )
.hide();
},
success : function( response, text_status, xhr )
{
$( '.message', this )
.empty()
.hide();
$( '.content', this )
.show();
$( '.replication', context.active_core )
.show();
var data = response.details;
var is_slave = 'undefined' !== typeof( data.slave );
var headline = $( 'h2 span', this );
var details_element = $( '#details', this );
var current_type_element = $( ( is_slave ? '.slave' : '.master' ), this );
if( is_slave )
{
this
.addClass( 'slave' );
headline
.html( headline.html() + ' (Slave)' );
}
else
{
this
.addClass( 'master' );
headline
.html( headline.html() + ' (Master)' );
}
$( '.version div', current_type_element )
.html( data.indexVersion );
$( '.generation div', current_type_element )
.html( data.generation );
$( '.size div', current_type_element )
.html( data.indexSize );
if( is_slave )
{
var master_element = $( '.master', details_element );
$( '.version div', master_element )
.html( data.slave.masterDetails.indexVersion );
$( '.generation div', master_element )
.html( data.slave.masterDetails.generation );
$( '.size div', master_element )
.html( data.slave.masterDetails.indexSize );
if( data.indexVersion !== data.slave.masterDetails.indexVersion )
{
$( '.version', details_element )
.addClass( 'diff' );
}
else
{
$( '.version', details_element )
.removeClass( 'diff' );
}
if( data.generation !== data.slave.masterDetails.generation )
{
$( '.generation', details_element )
.addClass( 'diff' );
}
else
{
$( '.generation', details_element )
.removeClass( 'diff' );
}
}
},
error : function( xhr, text_status, error_thrown)
{
this
.addClass( 'disabled' );
$( '.message', this )
.show()
.html( 'Replication is not configured' );
},
complete : function( xhr, text_status )
{
$( 'h2', this )
.removeClass( 'loader' );
}
}
);
$.ajax
(
{
url : core_basepath + '/dataimport?command=details&wt=json',
dataType : 'json',
context : $( '#dataimport', dashboard_element ),
beforeSend : function( xhr, settings )
{
$( 'h2', this )
.addClass( 'loader' );
$( '.message', this )
.show()
.html( 'Loading' );
},
success : function( response, text_status, xhr )
{
$( '.message', this )
.empty()
.hide();
$( 'dl', this )
.show();
var data = {
'status' : response['status'],
'info' : response['statusMessages']['']
};
for( var key in data )
{
$( '.' + key, this )
.show();
$( '.value.' + key, this )
.html( data[key] );
}
},
error : function( xhr, text_status, error_thrown)
{
this
.addClass( 'disabled' );
$( '.message', this )
.show()
.html( 'Dataimport is not configured' );
},
complete : function( xhr, text_status )
{
$( 'h2', this )
.removeClass( 'loader' );
}
}
);
$.ajax
(
{
url : core_basepath + '/admin/file/?file=admin-extra.html',
dataType : 'html',
context : $( '#admin-extra', dashboard_element ),
beforeSend : function( xhr, settings )
{
$( 'h2', this )
.addClass( 'loader' );
$( '.message', this )
.show()
.html( 'Loading' );
$( '.content', this )
.hide();
},
success : function( response, text_status, xhr )
{
$( '.message', this )
.hide()
.empty();
$( '.content', this )
.show()
.html( response );
},
error : function( xhr, text_status, error_thrown)
{
this
.addClass( 'disabled' );
$( '.message', this )
.show()
.html( 'We found no "admin-extra.html" file.' );
},
complete : function( xhr, text_status )
{
$( 'h2', this )
.removeClass( 'loader' );
}
}
);
}
);
}
);
// #/
this.get
(
/^#\/$/,
function( context )
{
var content_element = $( '#content' );
$( '#index', app.menu_element )
.addClass( 'active' );
content_element
.html( '' );
$.ajax
(
{
url : 'tpl/index.html',
context : $( '#index', content_element ),
beforeSend : function( arr, form, options )
{
},
success : function( template )
{
this
.html( template );
var jvm_memory = $.extend
(
{
'free' : null,
'total' : null,
'max' : null,
'used' : null,
'raw' : {
'free' : null,
'total' : null,
'max' : null,
'used' : null,
'used%' : null
}
},
app.dashboard_values['jvm']['memory']
);
var parse_memory_value = function( value )
{
if( value !== Number( value ) )
{
var units = 'BKMGTPEZY';
var match = value.match( /^(\d+([,\.]\d+)?) (\w)\w?$/ );
var value = parseFloat( match[1] ) * Math.pow( 1024, units.indexOf( match[3].toUpperCase() ) );
}
return value;
};
var memory_data = {
'memory-bar-max' : parse_memory_value( jvm_memory['raw']['max'] || jvm_memory['max'] ),
'memory-bar-total' : parse_memory_value( jvm_memory['raw']['total'] || jvm_memory['total'] ),
'memory-bar-used' : parse_memory_value( jvm_memory['raw']['used'] || jvm_memory['used'] )
};
for( var key in memory_data )
{
$( '.value.' + key, this )
.html( memory_data[key] );
}
var data = {
'start_time' : app.dashboard_values['jvm']['jmx']['startTime'],
'host' : app.dashboard_values['core']['host'],
'jvm' : app.dashboard_values['jvm']['name'] + ' (' + app.dashboard_values['jvm']['version'] + ')',
'solr_spec_version' : app.dashboard_values['lucene']['solr-spec-version'],
'solr_impl_version' : app.dashboard_values['lucene']['solr-impl-version'],
'lucene_spec_version' : app.dashboard_values['lucene']['lucene-spec-version'],
'lucene_impl_version' : app.dashboard_values['lucene']['lucene-impl-version']
};
if( app.dashboard_values['core']['directory']['cwd'] )
{
data['cwd'] = app.dashboard_values['core']['directory']['cwd'];
}
for( var key in data )
{
var value_element = $( '.' + key + ' dd', this );
value_element
.html( data[key] );
value_element.closest( 'li' )
.show();
}
var commandLineArgs = app.dashboard_values['jvm']['jmx']['commandLineArgs'];
if( 0 !== commandLineArgs.length )
{
var cmd_arg_element = $( '.command_line_args dt', this );
var cmd_arg_key_element = $( '.command_line_args dt', this );
var cmd_arg_element = $( '.command_line_args dd', this );
for( var key in commandLineArgs )
{
cmd_arg_element = cmd_arg_element.clone();
cmd_arg_element.html( commandLineArgs[key] );
cmd_arg_key_element
.after( cmd_arg_element );
}
cmd_arg_key_element.closest( 'li' )
.show();
$( '.command_line_args dd:last', this )
.remove();
$( '.command_line_args dd:odd', this )
.addClass( 'odd' );
}
$( '.timeago', this )
.timeago();
$( 'li:visible:odd', this )
.addClass( 'odd' );
// -- memory bar
var max_height = Math.round( $( '#memory-bar-max', this ).height() );
var total_height = Math.round( ( memory_data['memory-bar-total'] * max_height ) / memory_data['memory-bar-max'] );
var used_height = Math.round( ( memory_data['memory-bar-used'] * max_height ) / memory_data['memory-bar-max'] );
var memory_bar_total_value = $( '#memory-bar-total span', this ).first();
$( '#memory-bar-total', this )
.height( total_height );
$( '#memory-bar-used', this )
.height( used_height );
if( used_height < total_height + memory_bar_total_value.height() )
{
memory_bar_total_value
.addClass( 'upper' )
.css( 'margin-top', memory_bar_total_value.height() * -1 );
}
var memory_percentage = ( ( memory_data['memory-bar-used'] / memory_data['memory-bar-max'] ) * 100 ).toFixed(1);
var headline = $( '#memory h2 span', this );
headline
.html( headline.html() + ' (' + memory_percentage + '%)' );
$( '#memory-bar .value', this )
.each
(
function()
{
var self = $( this );
var byte_value = parseInt( self.html() );
self
.attr( 'title', 'raw: ' + byte_value + ' B' );
byte_value /= 1024;
byte_value /= 1024;
byte_value = byte_value.toFixed( 2 ) + ' MB';
self
.html( byte_value );
}
);
},
error : function( xhr, text_status, error_thrown )
{
},
complete : function( xhr, text_status )
{
}
}
);
}
);
}
);
var solr_admin = function( app_config )
{
menu_element = null,
is_multicore = null,
cores_data = null,
active_core = null,
environment_basepath = null,
config = app_config,
params = null,
dashboard_values = null,
schema_browser_data = null,
plugin_data = null,
this.init_menu = function()
{
$( '.ping a', menu_element )
.live
(
'click',
function()
{
sammy.trigger
(
'ping',
{ element : this }
);
return false;
}
);
}
this.init_cores = function()
{
var self = this;
$.ajax
(
{
url : config.solr_path + config.core_admin_path + '?wt=json',
dataType : 'json',
beforeSend : function( arr, form, options )
{
$( '#content' )
.html( '