1 | /* |
---|
2 | Licensed to the Apache Software Foundation (ASF) under one or more |
---|
3 | contributor license agreements. See the NOTICE file distributed with |
---|
4 | this work for additional information regarding copyright ownership. |
---|
5 | The ASF licenses this file to You under the Apache License, Version 2.0 |
---|
6 | (the "License"); you may not use this file except in compliance with |
---|
7 | the License. You may obtain a copy of the License at |
---|
8 | |
---|
9 | http://www.apache.org/licenses/LICENSE-2.0 |
---|
10 | |
---|
11 | Unless required by applicable law or agreed to in writing, software |
---|
12 | distributed under the License is distributed on an "AS IS" BASIS, |
---|
13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
---|
14 | See the License for the specific language governing permissions and |
---|
15 | limitations under the License. |
---|
16 | */ |
---|
17 | |
---|
18 | var timer_element = null; |
---|
19 | var timer_timeout = null; |
---|
20 | |
---|
21 | var core_basepath = null; |
---|
22 | var navigation_element = null; |
---|
23 | var replication_element = null; |
---|
24 | |
---|
25 | var convert_duration_to_seconds = function( str ) |
---|
26 | { |
---|
27 | var ret = 0; |
---|
28 | var parts = new String( str ).split( ':' ).reverse(); |
---|
29 | var parts_count = parts.length; |
---|
30 | |
---|
31 | for( var i = 0; i < parts_count; i++ ) |
---|
32 | { |
---|
33 | ret += parseInt( parts[i], 10 ) * Math.pow( 60, i ); |
---|
34 | } |
---|
35 | |
---|
36 | return ret; |
---|
37 | } |
---|
38 | |
---|
39 | var convert_seconds_to_readable_time = function( value ) |
---|
40 | { |
---|
41 | var text = []; |
---|
42 | value = parseInt( value ); |
---|
43 | |
---|
44 | var minutes = Math.floor( value / 60 ); |
---|
45 | var hours = Math.floor( minutes / 60 ); |
---|
46 | |
---|
47 | if( 0 !== hours ) |
---|
48 | { |
---|
49 | text.push( hours + 'h' ); |
---|
50 | value -= hours * 60 * 60; |
---|
51 | minutes -= hours * 60; |
---|
52 | } |
---|
53 | |
---|
54 | if( 0 !== minutes ) |
---|
55 | { |
---|
56 | text.push( minutes + 'm' ); |
---|
57 | value -= minutes * 60; |
---|
58 | } |
---|
59 | |
---|
60 | if( 0 !== value ) |
---|
61 | { |
---|
62 | text.push( value + 's' ); |
---|
63 | } |
---|
64 | |
---|
65 | return text.join( ' ' ); |
---|
66 | } |
---|
67 | |
---|
68 | var init_timer = function( next_tick ) |
---|
69 | { |
---|
70 | if( timer_timeout ) |
---|
71 | { |
---|
72 | window.clearTimeout( timer_timeout ); |
---|
73 | } |
---|
74 | update_timer( next_tick ); |
---|
75 | } |
---|
76 | |
---|
77 | var update_timer = function( next_tick ) |
---|
78 | { |
---|
79 | if( 0 === next_tick ) |
---|
80 | { |
---|
81 | replication_fetch_status(); |
---|
82 | return false; |
---|
83 | } |
---|
84 | |
---|
85 | $( 'p .tick', timer_element ) |
---|
86 | .text( convert_seconds_to_readable_time( next_tick ) ); |
---|
87 | |
---|
88 | timer_timeout = window.setTimeout |
---|
89 | ( |
---|
90 | 'update_timer( ' + --next_tick + ' )', |
---|
91 | 1000 |
---|
92 | ); |
---|
93 | } |
---|
94 | |
---|
95 | var clear_timer = function() |
---|
96 | { |
---|
97 | if( timer_timeout ) |
---|
98 | { |
---|
99 | window.clearTimeout( timer_timeout ); |
---|
100 | timer_element.hide(); |
---|
101 | } |
---|
102 | } |
---|
103 | |
---|
104 | var replication_fetch_status = function() |
---|
105 | { |
---|
106 | $.ajax |
---|
107 | ( |
---|
108 | { |
---|
109 | url : core_basepath + '/replication?command=details&wt=json', |
---|
110 | dataType : 'json', |
---|
111 | beforeSend : function( xhr, settings ) |
---|
112 | { |
---|
113 | $( '.refresh-status span', navigation_element ) |
---|
114 | .addClass( 'loader' ); |
---|
115 | |
---|
116 | clear_timer(); |
---|
117 | }, |
---|
118 | success : function( response, text_status, xhr ) |
---|
119 | { |
---|
120 | $( '.refresh-status span', navigation_element ) |
---|
121 | .removeClass( 'loader' ); |
---|
122 | |
---|
123 | var data = response.details; |
---|
124 | var is_slave = 'true' === data.isSlave; |
---|
125 | |
---|
126 | replication_element |
---|
127 | .addClass( is_slave ? 'slave' : 'master' ); |
---|
128 | |
---|
129 | if( is_slave ) |
---|
130 | { |
---|
131 | var error_element = $( '#error', replication_element ); |
---|
132 | |
---|
133 | if( data.slave.ERROR ) |
---|
134 | { |
---|
135 | error_element |
---|
136 | .html( data.slave.ERROR ) |
---|
137 | .show(); |
---|
138 | } |
---|
139 | else |
---|
140 | { |
---|
141 | error_element |
---|
142 | .hide() |
---|
143 | .empty(); |
---|
144 | } |
---|
145 | |
---|
146 | var progress_element = $( '#progress', replication_element ); |
---|
147 | |
---|
148 | var start_element = $( '#start', progress_element ); |
---|
149 | $( 'span', start_element ) |
---|
150 | .text( data.slave.replicationStartTime ); |
---|
151 | |
---|
152 | var eta_element = $( '#eta', progress_element ); |
---|
153 | $( 'span', eta_element ) |
---|
154 | .text( convert_seconds_to_readable_time( data.slave.timeRemaining ) ); |
---|
155 | |
---|
156 | var bar_element = $( '#bar', progress_element ); |
---|
157 | $( '.files span', bar_element ) |
---|
158 | .text( data.slave.numFilesToDownload ); |
---|
159 | $( '.size span', bar_element ) |
---|
160 | .text( data.slave.bytesToDownload ); |
---|
161 | |
---|
162 | var speed_element = $( '#speed', progress_element ); |
---|
163 | $( 'span', speed_element ) |
---|
164 | .text( data.slave.downloadSpeed ); |
---|
165 | |
---|
166 | var done_element = $( '#done', progress_element ); |
---|
167 | $( '.files span', done_element ) |
---|
168 | .text( data.slave.numFilesDownloaded ); |
---|
169 | $( '.size span', done_element ) |
---|
170 | .text( data.slave.bytesDownloaded ); |
---|
171 | $( '.percent span', done_element ) |
---|
172 | .text( parseInt(data.slave.totalPercent ) ); |
---|
173 | |
---|
174 | var percent = parseInt( data.slave.totalPercent ); |
---|
175 | if( 0 === percent ) |
---|
176 | { |
---|
177 | done_element |
---|
178 | .css( 'width', '1px' ); |
---|
179 | } |
---|
180 | else |
---|
181 | { |
---|
182 | done_element |
---|
183 | .css( 'width', percent + '%' ); |
---|
184 | } |
---|
185 | |
---|
186 | var current_file_element = $( '#current-file', replication_element ); |
---|
187 | $( '.file', current_file_element ) |
---|
188 | .text( data.slave.currentFile ); |
---|
189 | $( '.done', current_file_element ) |
---|
190 | .text( data.slave.currentFileSizeDownloaded ); |
---|
191 | $( '.total', current_file_element ) |
---|
192 | .text( data.slave.currentFileSize ); |
---|
193 | $( '.percent', current_file_element ) |
---|
194 | .text( parseInt( data.slave.currentFileSizePercent ) ); |
---|
195 | |
---|
196 | if( !data.slave.indexReplicatedAtList ) |
---|
197 | { |
---|
198 | data.slave.indexReplicatedAtList = []; |
---|
199 | } |
---|
200 | |
---|
201 | if( !data.slave.replicationFailedAtList ) |
---|
202 | { |
---|
203 | data.slave.replicationFailedAtList = []; |
---|
204 | } |
---|
205 | |
---|
206 | var iterations_element = $( '#iterations', replication_element ); |
---|
207 | var iterations_list = $( '.iterations ul', iterations_element ); |
---|
208 | |
---|
209 | var iterations_data = []; |
---|
210 | var iterations_obj = {}; |
---|
211 | |
---|
212 | for( var i in data.slave.indexReplicatedAtList ) |
---|
213 | { |
---|
214 | var date = data.slave.indexReplicatedAtList[i]; |
---|
215 | if( !iterations_obj[date] ) |
---|
216 | { |
---|
217 | iterations_obj[date] = true; |
---|
218 | iterations_data.push( date ); |
---|
219 | } |
---|
220 | } |
---|
221 | |
---|
222 | for( var i in data.slave.replicationFailedAtList ) |
---|
223 | { |
---|
224 | var date = data.slave.replicationFailedAtList[i]; |
---|
225 | if( !iterations_obj[date] ) |
---|
226 | { |
---|
227 | iterations_obj[date] = true; |
---|
228 | iterations_data.push( date ); |
---|
229 | } |
---|
230 | } |
---|
231 | |
---|
232 | iterations_data.sort().reverse(); |
---|
233 | |
---|
234 | if( 0 !== iterations_data.length ) |
---|
235 | { |
---|
236 | var iterations = []; |
---|
237 | for( var i = 0; i < iterations_data.length; i++ ) |
---|
238 | { |
---|
239 | iterations.push( '<li data-date="' + iterations_data[i] + '">' + iterations_data[i] + '</li>' ); |
---|
240 | } |
---|
241 | |
---|
242 | iterations_list |
---|
243 | .html( iterations.join( "\n" ) ) |
---|
244 | .show(); |
---|
245 | |
---|
246 | $( data.slave.indexReplicatedAtList ) |
---|
247 | .each |
---|
248 | ( |
---|
249 | function( key, value ) |
---|
250 | { |
---|
251 | $( 'li[data-date="' + value + '"]', iterations_list ) |
---|
252 | .addClass( 'replicated' ); |
---|
253 | } |
---|
254 | ); |
---|
255 | |
---|
256 | if( data.slave.indexReplicatedAt ) |
---|
257 | { |
---|
258 | $( 'li[data-date="' + data.slave.indexReplicatedAt + '"]', iterations_list ) |
---|
259 | .addClass( 'latest' ); |
---|
260 | } |
---|
261 | |
---|
262 | $( data.slave.replicationFailedAtList ) |
---|
263 | .each |
---|
264 | ( |
---|
265 | function( key, value ) |
---|
266 | { |
---|
267 | $( 'li[data-date="' + value + '"]', iterations_list ) |
---|
268 | .addClass( 'failed' ); |
---|
269 | } |
---|
270 | ); |
---|
271 | |
---|
272 | if( data.slave.replicationFailedAt ) |
---|
273 | { |
---|
274 | $( 'li[data-date="' + data.slave.replicationFailedAt + '"]', iterations_list ) |
---|
275 | .addClass( 'latest' ); |
---|
276 | } |
---|
277 | |
---|
278 | if( 0 !== $( 'li:hidden', iterations_list ).size() ) |
---|
279 | { |
---|
280 | $( 'a', iterations_element ) |
---|
281 | .show(); |
---|
282 | } |
---|
283 | else |
---|
284 | { |
---|
285 | $( 'a', iterations_element ) |
---|
286 | .hide(); |
---|
287 | } |
---|
288 | } |
---|
289 | } |
---|
290 | |
---|
291 | var details_element = $( '#details', replication_element ); |
---|
292 | var current_type_element = $( ( is_slave ? '.slave' : '.master' ), details_element ); |
---|
293 | |
---|
294 | $( '.version div', current_type_element ) |
---|
295 | .html( data.indexVersion ); |
---|
296 | $( '.generation div', current_type_element ) |
---|
297 | .html( data.generation ); |
---|
298 | $( '.size div', current_type_element ) |
---|
299 | .html( data.indexSize ); |
---|
300 | |
---|
301 | if( is_slave ) |
---|
302 | { |
---|
303 | var master_element = $( '.master', details_element ); |
---|
304 | $( '.version div', master_element ) |
---|
305 | .html( data.slave.masterDetails.indexVersion ); |
---|
306 | $( '.generation div', master_element ) |
---|
307 | .html( data.slave.masterDetails.generation ); |
---|
308 | $( '.size div', master_element ) |
---|
309 | .html( data.slave.masterDetails.indexSize ); |
---|
310 | |
---|
311 | if( data.indexVersion !== data.slave.masterDetails.indexVersion ) |
---|
312 | { |
---|
313 | $( '.version', details_element ) |
---|
314 | .addClass( 'diff' ); |
---|
315 | } |
---|
316 | else |
---|
317 | { |
---|
318 | $( '.version', details_element ) |
---|
319 | .removeClass( 'diff' ); |
---|
320 | } |
---|
321 | |
---|
322 | if( data.generation !== data.slave.masterDetails.generation ) |
---|
323 | { |
---|
324 | $( '.generation', details_element ) |
---|
325 | .addClass( 'diff' ); |
---|
326 | } |
---|
327 | else |
---|
328 | { |
---|
329 | $( '.generation', details_element ) |
---|
330 | .removeClass( 'diff' ); |
---|
331 | } |
---|
332 | } |
---|
333 | |
---|
334 | if( is_slave ) |
---|
335 | { |
---|
336 | var settings_element = $( '#settings', replication_element ); |
---|
337 | |
---|
338 | if( data.slave.masterUrl ) |
---|
339 | { |
---|
340 | $( '.masterUrl dd', settings_element ) |
---|
341 | .html( response.details.slave.masterUrl ) |
---|
342 | .parents( 'li' ).show(); |
---|
343 | } |
---|
344 | |
---|
345 | var polling_content = ' '; |
---|
346 | var polling_ico = 'ico-1'; |
---|
347 | |
---|
348 | if( 'true' === data.slave.isPollingDisabled ) |
---|
349 | { |
---|
350 | polling_ico = 'ico-0'; |
---|
351 | |
---|
352 | $( '.disable-polling', navigation_element ).hide(); |
---|
353 | $( '.enable-polling', navigation_element ).show(); |
---|
354 | } |
---|
355 | else |
---|
356 | { |
---|
357 | $( '.disable-polling', navigation_element ).show(); |
---|
358 | $( '.enable-polling', navigation_element ).hide(); |
---|
359 | |
---|
360 | if( data.slave.pollInterval ) |
---|
361 | { |
---|
362 | polling_content = '(interval: ' + data.slave.pollInterval + ')'; |
---|
363 | } |
---|
364 | } |
---|
365 | |
---|
366 | $( '.isPollingDisabled dd', settings_element ) |
---|
367 | .removeClass( 'ico-0' ) |
---|
368 | .removeClass( 'ico-1' ) |
---|
369 | .addClass( polling_ico ) |
---|
370 | .html( polling_content ) |
---|
371 | .parents( 'li' ).show(); |
---|
372 | |
---|
373 | if( 'true' === data.slave.isReplicating ) |
---|
374 | { |
---|
375 | replication_element |
---|
376 | .addClass( 'replicating' ); |
---|
377 | |
---|
378 | $( '.replicate-now', navigation_element ).hide(); |
---|
379 | $( '.abort-replication', navigation_element ).show(); |
---|
380 | |
---|
381 | window.setTimeout( replication_fetch_status, 1000 ); |
---|
382 | } |
---|
383 | else |
---|
384 | { |
---|
385 | replication_element |
---|
386 | .removeClass( 'replicating' ); |
---|
387 | |
---|
388 | $( '.replicate-now', navigation_element ).show(); |
---|
389 | $( '.abort-replication', navigation_element ).hide(); |
---|
390 | |
---|
391 | |
---|
392 | if( 'false' === data.slave.isPollingDisabled && data.slave.pollInterval ) |
---|
393 | { |
---|
394 | timer_element = $( '.timer', navigation_element ); |
---|
395 | approx_element = $( '.approx', timer_element ); |
---|
396 | |
---|
397 | var next_tick = convert_duration_to_seconds( data.slave.pollInterval ); |
---|
398 | approx_element.show(); |
---|
399 | |
---|
400 | if( data.slave.nextExecutionAt ) |
---|
401 | { |
---|
402 | var nextExecutionAt = new SolrDate( data.slave.nextExecutionAt ); |
---|
403 | var currentDate = new SolrDate( data.slave.currentDate ); |
---|
404 | |
---|
405 | if( nextExecutionAt.getTime() > currentDate.getTime() ) |
---|
406 | { |
---|
407 | next_tick = ( nextExecutionAt.getTime() - currentDate.getTime() ) / 1000; |
---|
408 | approx_element.hide(); |
---|
409 | |
---|
410 | $( 'small', timer_element ) |
---|
411 | .text( data.slave.nextExecutionAt ) |
---|
412 | .show(); |
---|
413 | } |
---|
414 | } |
---|
415 | |
---|
416 | init_timer( next_tick ); |
---|
417 | |
---|
418 | timer_element |
---|
419 | .show(); |
---|
420 | } |
---|
421 | } |
---|
422 | } |
---|
423 | |
---|
424 | var master_settings_element = $( '#master-settings', replication_element ); |
---|
425 | var master_data = is_slave ? data.slave.masterDetails.master : data.master; |
---|
426 | |
---|
427 | var replication_icon = 'ico-0'; |
---|
428 | if( 'true' === master_data.replicationEnabled ) |
---|
429 | { |
---|
430 | replication_icon = 'ico-1'; |
---|
431 | |
---|
432 | $( '.disable-replication', navigation_element ).show(); |
---|
433 | $( '.enable-replication', navigation_element ).hide(); |
---|
434 | } |
---|
435 | else |
---|
436 | { |
---|
437 | $( '.disable-replication', navigation_element ).hide(); |
---|
438 | $( '.enable-replication', navigation_element ).show(); |
---|
439 | } |
---|
440 | |
---|
441 | $( '.replicationEnabled dd', master_settings_element ) |
---|
442 | .removeClass( 'ico-0' ) |
---|
443 | .removeClass( 'ico-1' ) |
---|
444 | .addClass( replication_icon ) |
---|
445 | .parents( 'li' ).show(); |
---|
446 | |
---|
447 | $( '.replicateAfter dd', master_settings_element ) |
---|
448 | .html( master_data.replicateAfter.join( ', ' ) ) |
---|
449 | .parents( 'li' ).show(); |
---|
450 | |
---|
451 | if( master_data.confFiles ) |
---|
452 | { |
---|
453 | var conf_files = []; |
---|
454 | var conf_data = master_data.confFiles.split( ',' ); |
---|
455 | |
---|
456 | for( var i = 0; i < conf_data.length; i++ ) |
---|
457 | { |
---|
458 | var item = conf_data[i]; |
---|
459 | |
---|
460 | if( - 1 !== item.indexOf( ':' ) ) |
---|
461 | { |
---|
462 | info = item.split( ':' ); |
---|
463 | item = '<abbr title="' + info[0] + ' » ' + info[1] + '">' + ( is_slave ? info[1] : info[0] ) + '</abbr>'; |
---|
464 | } |
---|
465 | |
---|
466 | conf_files.push( item ); |
---|
467 | } |
---|
468 | |
---|
469 | $( '.confFiles dd', master_settings_element ) |
---|
470 | .html( conf_files.join( ', ' ) ) |
---|
471 | .parents( 'li' ).show(); |
---|
472 | } |
---|
473 | |
---|
474 | |
---|
475 | $( '.block', replication_element ).last() |
---|
476 | .addClass( 'last' ); |
---|
477 | }, |
---|
478 | error : function( xhr, text_status, error_thrown ) |
---|
479 | { |
---|
480 | $( '#content' ) |
---|
481 | .html( 'sorry, no replication-handler defined!' ); |
---|
482 | }, |
---|
483 | complete : function( xhr, text_status ) |
---|
484 | { |
---|
485 | } |
---|
486 | } |
---|
487 | ); |
---|
488 | } |
---|
489 | |
---|
490 | // #/:core/replication |
---|
491 | sammy.get |
---|
492 | ( |
---|
493 | /^#\/([\w\d-]+)\/(replication)$/, |
---|
494 | function( context ) |
---|
495 | { |
---|
496 | core_basepath = this.active_core.attr( 'data-basepath' ); |
---|
497 | var content_element = $( '#content' ); |
---|
498 | |
---|
499 | $.get |
---|
500 | ( |
---|
501 | 'tpl/replication.html', |
---|
502 | function( template ) |
---|
503 | { |
---|
504 | content_element |
---|
505 | .html( template ); |
---|
506 | |
---|
507 | replication_element = $( '#replication', content_element ); |
---|
508 | navigation_element = $( '#navigation', replication_element ); |
---|
509 | |
---|
510 | replication_fetch_status(); |
---|
511 | |
---|
512 | $( '#iterations a', content_element ) |
---|
513 | .die( 'click' ) |
---|
514 | .live |
---|
515 | ( |
---|
516 | 'click', |
---|
517 | function( event ) |
---|
518 | { |
---|
519 | $( this ).parents( '.iterations' ) |
---|
520 | .toggleClass( 'expanded' ); |
---|
521 | |
---|
522 | return false; |
---|
523 | } |
---|
524 | ); |
---|
525 | |
---|
526 | $( 'button', navigation_element ) |
---|
527 | .die( 'click' ) |
---|
528 | .live |
---|
529 | ( |
---|
530 | 'click', |
---|
531 | function( event ) |
---|
532 | { |
---|
533 | var button = $( this ); |
---|
534 | var command = button.data( 'command' ); |
---|
535 | |
---|
536 | if( button.hasClass( 'refresh-status' ) && !button.hasClass( 'loader' ) ) |
---|
537 | { |
---|
538 | replication_fetch_status(); |
---|
539 | } |
---|
540 | else if( command ) |
---|
541 | { |
---|
542 | $.get |
---|
543 | ( |
---|
544 | core_basepath + '/replication?command=' + command + '&wt=json', |
---|
545 | function() |
---|
546 | { |
---|
547 | replication_fetch_status(); |
---|
548 | } |
---|
549 | ); |
---|
550 | } |
---|
551 | return false; |
---|
552 | } |
---|
553 | ); |
---|
554 | } |
---|
555 | ); |
---|
556 | } |
---|
557 | ); |
---|