2016-04-14 16:24:03 +00:00
|
|
|
package me.mrCookieSlime.Slimefun.api;
|
|
|
|
|
2019-08-25 16:06:36 +00:00
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.HashSet;
|
|
|
|
import java.util.Iterator;
|
|
|
|
import java.util.Map;
|
|
|
|
import java.util.Set;
|
2019-08-31 13:07:27 +00:00
|
|
|
import java.util.logging.Level;
|
2016-04-14 16:24:03 +00:00
|
|
|
|
2019-08-25 16:06:36 +00:00
|
|
|
import org.bukkit.Bukkit;
|
|
|
|
import org.bukkit.ChatColor;
|
|
|
|
import org.bukkit.Chunk;
|
|
|
|
import org.bukkit.Location;
|
|
|
|
import org.bukkit.Material;
|
2016-04-14 16:24:03 +00:00
|
|
|
import org.bukkit.block.Block;
|
|
|
|
import org.bukkit.command.CommandSender;
|
|
|
|
import org.bukkit.entity.Player;
|
|
|
|
|
2016-04-24 12:26:52 +00:00
|
|
|
import me.mrCookieSlime.CSCoreLibPlugin.general.Chat.TellRawMessage;
|
|
|
|
import me.mrCookieSlime.CSCoreLibPlugin.general.Chat.TellRawMessage.HoverAction;
|
2019-08-31 09:36:45 +00:00
|
|
|
import me.mrCookieSlime.Slimefun.SlimefunPlugin;
|
2016-04-24 12:26:52 +00:00
|
|
|
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
2019-08-27 19:46:50 +00:00
|
|
|
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
|
2016-04-24 12:26:52 +00:00
|
|
|
|
2016-04-14 16:24:03 +00:00
|
|
|
public class TickerTask implements Runnable {
|
|
|
|
|
2019-08-30 07:21:49 +00:00
|
|
|
public boolean halted = false;
|
2017-03-31 12:47:43 +00:00
|
|
|
|
2019-06-20 08:12:34 +00:00
|
|
|
public Map<Location, Location> move = new HashMap<>();
|
|
|
|
public Map<Location, Boolean> delete = new HashMap<>();
|
2019-08-31 13:07:27 +00:00
|
|
|
public Map<Location, Long> blockTimings = new HashMap<>();
|
2016-04-14 16:24:03 +00:00
|
|
|
|
2019-06-20 08:12:34 +00:00
|
|
|
private Set<BlockTicker> tickers = new HashSet<>();
|
2016-04-14 16:24:03 +00:00
|
|
|
|
2019-08-29 20:46:03 +00:00
|
|
|
private int skipped = 0;
|
|
|
|
private int chunks = 0;
|
|
|
|
private int machines = 0;
|
2016-04-14 16:24:03 +00:00
|
|
|
private long time = 0;
|
|
|
|
|
2019-08-30 07:21:49 +00:00
|
|
|
private Map<String, Integer> chunkItemCount = new HashMap<>();
|
|
|
|
private Map<String, Integer> machineCount = new HashMap<>();
|
|
|
|
private Map<String, Long> machineTimings = new HashMap<>();
|
|
|
|
private Map<String, Long> chunkTimings = new HashMap<>();
|
|
|
|
private Set<String> chunksSkipped = new HashSet<>();
|
|
|
|
private Map<Location, Integer> buggedBlocks = new HashMap<>();
|
2016-04-24 12:23:05 +00:00
|
|
|
|
2016-04-14 16:24:03 +00:00
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
long timestamp = System.currentTimeMillis();
|
|
|
|
|
|
|
|
skipped = 0;
|
|
|
|
chunks = 0;
|
|
|
|
machines = 0;
|
2019-08-30 07:21:49 +00:00
|
|
|
chunkItemCount.clear();
|
|
|
|
machineCount.clear();
|
2016-04-14 16:24:03 +00:00
|
|
|
time = 0;
|
2019-08-30 07:21:49 +00:00
|
|
|
chunkTimings.clear();
|
|
|
|
chunksSkipped.clear();
|
|
|
|
machineTimings.clear();
|
|
|
|
blockTimings.clear();
|
2016-04-14 16:24:03 +00:00
|
|
|
|
2019-08-30 07:21:49 +00:00
|
|
|
final Map<Location, Integer> bugged = new HashMap<>(buggedBlocks);
|
|
|
|
buggedBlocks.clear();
|
2016-04-14 16:24:03 +00:00
|
|
|
|
2019-06-20 08:12:34 +00:00
|
|
|
Map<Location, Boolean> remove = new HashMap<>(delete);
|
2016-04-14 16:24:03 +00:00
|
|
|
|
|
|
|
for (Map.Entry<Location, Boolean> entry: remove.entrySet()) {
|
|
|
|
BlockStorage._integrated_removeBlockInfo(entry.getKey(), entry.getValue());
|
|
|
|
delete.remove(entry.getKey());
|
|
|
|
}
|
|
|
|
|
2019-08-30 07:21:49 +00:00
|
|
|
if (!halted) {
|
2017-03-31 12:47:43 +00:00
|
|
|
for (final String c: BlockStorage.getTickingChunks()) {
|
|
|
|
long timestamp2 = System.currentTimeMillis();
|
|
|
|
chunks++;
|
|
|
|
|
2018-03-10 19:22:12 +00:00
|
|
|
for (final Location l: BlockStorage.getTickingLocations(c)) {
|
|
|
|
if (l.getWorld().isChunkLoaded(l.getBlockX() >> 4, l.getBlockZ() >> 4)) {
|
|
|
|
final Block b = l.getBlock();
|
2017-03-31 12:47:43 +00:00
|
|
|
final SlimefunItem item = BlockStorage.check(l);
|
2019-08-25 16:06:36 +00:00
|
|
|
|
|
|
|
if (item != null && item.getBlockTicker() != null) {
|
2017-03-31 12:47:43 +00:00
|
|
|
machines++;
|
2019-08-25 16:06:36 +00:00
|
|
|
|
2017-03-31 12:47:43 +00:00
|
|
|
try {
|
2018-06-06 09:41:56 +00:00
|
|
|
item.getBlockTicker().update();
|
2019-08-25 16:06:36 +00:00
|
|
|
|
2018-06-06 09:41:56 +00:00
|
|
|
if (item.getBlockTicker().isSynchronized()) {
|
2019-08-31 09:36:45 +00:00
|
|
|
Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunPlugin.instance, () -> {
|
2019-03-30 12:32:13 +00:00
|
|
|
try {
|
|
|
|
long timestamp3 = System.currentTimeMillis();
|
|
|
|
item.getBlockTicker().tick(b, item, BlockStorage.getLocationInfo(l));
|
|
|
|
|
2019-08-30 07:21:49 +00:00
|
|
|
Long machinetime = machineTimings.get(item.getID());
|
|
|
|
Integer chunk = chunkItemCount.get(c);
|
|
|
|
Integer machine = machineCount.get(item.getID());
|
2019-08-25 16:06:36 +00:00
|
|
|
|
2019-08-30 07:21:49 +00:00
|
|
|
machineTimings.put(item.getID(), (machinetime != null ? machinetime: 0) + (System.currentTimeMillis() - timestamp3));
|
|
|
|
chunkItemCount.put(c, (chunk != null ? chunk: 0) + 1);
|
|
|
|
machineCount.put(item.getID(), (machine != null ? machine: 0) + 1);
|
|
|
|
blockTimings.put(l, System.currentTimeMillis() - timestamp3);
|
2019-03-30 12:32:13 +00:00
|
|
|
} catch (Exception x) {
|
|
|
|
int errors = 0;
|
|
|
|
if (bugged.containsKey(l)) errors = bugged.get(l);
|
|
|
|
errors++;
|
|
|
|
|
|
|
|
if (errors == 1) {
|
2019-08-25 16:06:36 +00:00
|
|
|
// Generate a new Error-Report
|
2019-08-27 13:27:38 +00:00
|
|
|
new ErrorReport(x, this, l, item);
|
2019-03-30 12:32:13 +00:00
|
|
|
|
2019-08-30 07:21:49 +00:00
|
|
|
buggedBlocks.put(l, errors);
|
2019-03-30 12:32:13 +00:00
|
|
|
}
|
|
|
|
else if (errors == 4) {
|
2019-08-31 15:52:20 +00:00
|
|
|
Slimefun.getLogger().log(Level.SEVERE, "X: " + l.getBlockX() + " Y: " + l.getBlockY() + " Z: " + l.getBlockZ() + "(" + item.getID() + ")");
|
|
|
|
Slimefun.getLogger().log(Level.SEVERE, "has thrown 4 Exceptions in the last 4 Ticks, the Block has been terminated.");
|
|
|
|
Slimefun.getLogger().log(Level.SEVERE, "Check your /plugins/Slimefun/error-reports/ folder for details.");
|
|
|
|
Slimefun.getLogger().log(Level.SEVERE, " ");
|
2019-03-30 12:32:13 +00:00
|
|
|
|
|
|
|
BlockStorage._integrated_removeBlockInfo(l, true);
|
|
|
|
|
2019-08-31 09:36:45 +00:00
|
|
|
Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunPlugin.instance, () -> {
|
2019-03-30 12:32:13 +00:00
|
|
|
l.getBlock().setType(Material.AIR);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
else {
|
2019-08-30 07:21:49 +00:00
|
|
|
buggedBlocks.put(l, errors);
|
2016-05-14 11:29:40 +00:00
|
|
|
}
|
|
|
|
}
|
2017-03-31 12:47:43 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
long timestamp3 = System.currentTimeMillis();
|
2018-06-06 09:41:56 +00:00
|
|
|
item.getBlockTicker().tick(b, item, BlockStorage.getLocationInfo(l));
|
2017-03-31 12:47:43 +00:00
|
|
|
|
2019-08-30 07:21:49 +00:00
|
|
|
machineTimings.put(item.getID(), (machineTimings.containsKey(item.getID()) ? machineTimings.get(item.getID()): 0) + (System.currentTimeMillis() - timestamp3));
|
|
|
|
chunkItemCount.put(c, (chunkItemCount.containsKey(c) ? chunkItemCount.get(c): 0) + 1);
|
|
|
|
machineCount.put(item.getID(), (machineCount.containsKey(item.getID()) ? machineCount.get(item.getID()): 0) + 1);
|
|
|
|
blockTimings.put(l, System.currentTimeMillis() - timestamp3);
|
2017-03-31 12:47:43 +00:00
|
|
|
}
|
2018-06-06 09:41:56 +00:00
|
|
|
tickers.add(item.getBlockTicker());
|
|
|
|
} catch (Exception x) {
|
2017-03-31 12:47:43 +00:00
|
|
|
int errors = 0;
|
|
|
|
if (bugged.containsKey(l)) errors = bugged.get(l);
|
|
|
|
errors++;
|
|
|
|
|
|
|
|
if (errors == 1) {
|
2019-08-25 16:06:36 +00:00
|
|
|
// Generate a new Error-Report
|
2019-08-27 13:27:38 +00:00
|
|
|
new ErrorReport(x, this, l, item);
|
2019-08-30 07:21:49 +00:00
|
|
|
buggedBlocks.put(l, errors);
|
2016-04-25 16:51:19 +00:00
|
|
|
}
|
2017-03-31 12:47:43 +00:00
|
|
|
else if (errors == 4) {
|
2019-08-31 15:52:20 +00:00
|
|
|
Slimefun.getLogger().log(Level.SEVERE, "X: " + l.getBlockX() + " Y: " + l.getBlockY() + " Z: " + l.getBlockZ() + "(" + item.getID() + ")");
|
|
|
|
Slimefun.getLogger().log(Level.SEVERE, "has thrown 4 Exceptions in the last 4 Ticks, the Block has been terminated.");
|
|
|
|
Slimefun.getLogger().log(Level.SEVERE, "Check your /plugins/Slimefun/error-reports/ folder for details.");
|
|
|
|
Slimefun.getLogger().log(Level.SEVERE, " ");
|
2016-04-24 12:26:52 +00:00
|
|
|
|
2017-03-31 12:47:43 +00:00
|
|
|
BlockStorage._integrated_removeBlockInfo(l, true);
|
|
|
|
|
2019-08-31 09:36:45 +00:00
|
|
|
Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunPlugin.instance, () -> {
|
2019-03-30 12:32:13 +00:00
|
|
|
l.getBlock().setType(Material.AIR);
|
2017-03-31 12:47:43 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
else {
|
2019-08-30 07:21:49 +00:00
|
|
|
buggedBlocks.put(l, errors);
|
2017-03-31 12:47:43 +00:00
|
|
|
}
|
2016-04-25 17:21:41 +00:00
|
|
|
}
|
2016-04-14 16:24:03 +00:00
|
|
|
}
|
2017-03-31 12:47:43 +00:00
|
|
|
else skipped++;
|
|
|
|
}
|
|
|
|
else {
|
2018-03-10 19:22:12 +00:00
|
|
|
skipped += BlockStorage.getTickingLocations(c).size();
|
2019-08-30 07:21:49 +00:00
|
|
|
chunksSkipped.add(c);
|
2017-03-31 12:47:43 +00:00
|
|
|
chunks--;
|
2019-08-30 11:47:58 +00:00
|
|
|
break;
|
2016-04-14 16:24:03 +00:00
|
|
|
}
|
|
|
|
}
|
2017-03-31 12:47:43 +00:00
|
|
|
|
2019-08-30 07:21:49 +00:00
|
|
|
chunkTimings.put(c, System.currentTimeMillis() - timestamp2);
|
2016-04-14 16:24:03 +00:00
|
|
|
}
|
|
|
|
}
|
2019-03-30 12:32:13 +00:00
|
|
|
|
2018-03-10 19:22:12 +00:00
|
|
|
for (Map.Entry<Location, Location> entry: move.entrySet()) {
|
|
|
|
BlockStorage._integrated_moveLocationInfo(entry.getKey(), entry.getValue());
|
2016-04-14 16:24:03 +00:00
|
|
|
}
|
|
|
|
move.clear();
|
|
|
|
|
2019-08-25 16:06:36 +00:00
|
|
|
Iterator<BlockTicker> iterator = tickers.iterator();
|
|
|
|
while (iterator.hasNext()) {
|
2019-08-29 13:13:40 +00:00
|
|
|
iterator.next().startNewTick();
|
2019-08-25 16:06:36 +00:00
|
|
|
iterator.remove();
|
2016-04-14 16:24:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
time = System.currentTimeMillis() - timestamp;
|
|
|
|
}
|
2019-08-25 20:57:41 +00:00
|
|
|
|
|
|
|
public long getTime() {
|
|
|
|
return time;
|
|
|
|
}
|
2016-04-14 16:24:03 +00:00
|
|
|
|
|
|
|
public void info(CommandSender sender) {
|
2016-11-27 18:34:45 +00:00
|
|
|
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&2== &aSlimefun Diagnostic Tool &2=="));
|
2019-08-30 07:21:49 +00:00
|
|
|
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6Halted: &e&l" + String.valueOf(halted).toUpperCase()));
|
2017-03-31 12:47:43 +00:00
|
|
|
sender.sendMessage("");
|
2016-11-27 18:34:45 +00:00
|
|
|
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6Impact: &e" + time + "ms / 50-750ms"));
|
|
|
|
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6Ticked Chunks: &e" + chunks));
|
|
|
|
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6Ticked Machines: &e" + machines));
|
|
|
|
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6Skipped Machines: &e" + skipped));
|
2016-04-14 16:24:03 +00:00
|
|
|
sender.sendMessage("");
|
2016-11-27 18:34:45 +00:00
|
|
|
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6Ticking Machines:"));
|
2019-08-25 16:06:36 +00:00
|
|
|
|
2016-04-14 16:24:03 +00:00
|
|
|
if (sender instanceof Player) {
|
|
|
|
TellRawMessage tellraw = new TellRawMessage();
|
2016-11-23 15:51:57 +00:00
|
|
|
tellraw.addText(" &7&oHover for more Info");
|
2016-04-14 16:24:03 +00:00
|
|
|
StringBuilder hover = new StringBuilder();
|
|
|
|
int hidden = 0;
|
2019-08-29 13:13:40 +00:00
|
|
|
|
2019-08-30 07:21:49 +00:00
|
|
|
for (Map.Entry<String, Integer> entry: machineCount.entrySet()) {
|
|
|
|
long timings = machineTimings.get(entry.getKey());
|
2019-08-29 13:13:40 +00:00
|
|
|
if (timings > 0) hover.append("\n&c" + entry.getKey() + " - " + entry.getValue()+ "x &7(" + timings + "ms)");
|
2016-04-14 16:24:03 +00:00
|
|
|
else hidden++;
|
|
|
|
}
|
2019-08-29 13:13:40 +00:00
|
|
|
|
2016-11-23 15:51:57 +00:00
|
|
|
hover.append("\n\n&c+ &4" + hidden + " Hidden");
|
2016-04-14 16:24:03 +00:00
|
|
|
tellraw.addHoverEvent(HoverAction.SHOW_TEXT, hover.toString());
|
2019-08-29 13:13:40 +00:00
|
|
|
|
2016-04-14 16:24:03 +00:00
|
|
|
try {
|
|
|
|
tellraw.send((Player) sender);
|
2019-08-31 13:07:27 +00:00
|
|
|
} catch (Exception x) {
|
|
|
|
Slimefun.getLogger().log(Level.SEVERE, "An Error occured while sending a Timings Summary for Slimefun " + Slimefun.getVersion(), x);
|
2016-04-14 16:24:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
int hidden = 0;
|
2019-08-29 13:13:40 +00:00
|
|
|
|
2019-08-30 07:21:49 +00:00
|
|
|
for (Map.Entry<String, Integer> entry: machineCount.entrySet()) {
|
|
|
|
long timings = machineTimings.get(entry.getKey());
|
2019-08-29 13:13:40 +00:00
|
|
|
if (timings > 0) sender.sendMessage(ChatColor.translateAlternateColorCodes('&', " &e" + entry.getKey() + " - " + entry.getValue()+ "x &7(" + timings + "ms)"));
|
2016-04-14 16:24:03 +00:00
|
|
|
else hidden++;
|
|
|
|
}
|
2019-08-29 13:13:40 +00:00
|
|
|
|
2016-11-27 18:34:45 +00:00
|
|
|
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c+ &4" + hidden + " Hidden"));
|
2016-04-14 16:24:03 +00:00
|
|
|
}
|
2019-08-25 16:06:36 +00:00
|
|
|
|
2016-04-14 16:24:03 +00:00
|
|
|
sender.sendMessage("");
|
2016-11-27 18:34:45 +00:00
|
|
|
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6Ticking Chunks:"));
|
2019-08-25 16:06:36 +00:00
|
|
|
|
2016-04-14 16:24:03 +00:00
|
|
|
if (sender instanceof Player) {
|
|
|
|
TellRawMessage tellraw = new TellRawMessage();
|
2016-11-23 15:51:57 +00:00
|
|
|
tellraw.addText(" &7&oHover for more Info");
|
2016-04-14 16:24:03 +00:00
|
|
|
StringBuilder hover = new StringBuilder();
|
|
|
|
int hidden = 0;
|
2019-08-29 13:13:40 +00:00
|
|
|
|
2019-08-30 07:21:49 +00:00
|
|
|
for (Map.Entry<String, Long> entry: chunkTimings.entrySet()) {
|
|
|
|
if (!chunksSkipped.contains(entry.getKey())) {
|
|
|
|
if (entry.getValue() > 0) hover.append("\n&c" + entry.getKey().replace("CraftChunk", "") + " - " + (chunkItemCount.containsKey(entry.getKey()) ? chunkItemCount.get(entry.getKey()): 0) + "x &7(" + entry.getValue() + "ms)");
|
2016-04-14 16:24:03 +00:00
|
|
|
else hidden++;
|
|
|
|
}
|
|
|
|
}
|
2019-08-29 13:13:40 +00:00
|
|
|
|
2016-11-23 15:51:57 +00:00
|
|
|
hover.append("\n\n&c+ &4" + hidden + " Hidden");
|
2016-04-14 16:24:03 +00:00
|
|
|
tellraw.addHoverEvent(HoverAction.SHOW_TEXT, hover.toString());
|
2019-06-20 08:12:34 +00:00
|
|
|
|
2016-04-14 16:24:03 +00:00
|
|
|
try {
|
|
|
|
tellraw.send((Player) sender);
|
2019-08-31 13:07:27 +00:00
|
|
|
} catch (Exception x) {
|
|
|
|
Slimefun.getLogger().log(Level.SEVERE, "An Error occured while sending a Timings Summary for Slimefun " + Slimefun.getVersion(), x);
|
2016-04-14 16:24:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
int hidden = 0;
|
2019-08-30 07:21:49 +00:00
|
|
|
for (Map.Entry<String, Long> entry: chunkTimings.entrySet()) {
|
|
|
|
if (!chunksSkipped.contains(entry.getKey())) {
|
|
|
|
if (entry.getValue() > 0) sender.sendMessage(" &c" + entry.getKey().replace("CraftChunk", "") + " - " + (chunkItemCount.containsKey(entry.getKey()) ? chunkItemCount.get(entry.getKey()): 0) + "x &7(" + entry.getValue() + "ms)");
|
2016-04-14 16:24:03 +00:00
|
|
|
else hidden++;
|
|
|
|
}
|
|
|
|
}
|
2016-11-27 18:34:45 +00:00
|
|
|
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c+ &4" + hidden + " Hidden"));
|
2016-04-14 16:24:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public long getTimings(Block b) {
|
2019-08-30 07:21:49 +00:00
|
|
|
return blockTimings.containsKey(b.getLocation()) ? blockTimings.get(b.getLocation()): 0L;
|
2016-04-14 16:24:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public long getTimings(String item) {
|
2019-08-30 07:21:49 +00:00
|
|
|
return machineTimings.containsKey(item) ? machineTimings.get(item): 0L;
|
2016-04-14 16:24:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public long getTimings(Chunk c) {
|
2019-08-30 07:21:49 +00:00
|
|
|
return chunkTimings.containsKey(c.toString()) ? chunkTimings.get(c.toString()): 0L;
|
2016-04-14 16:24:03 +00:00
|
|
|
}
|
2019-08-25 16:06:36 +00:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
return "TickerTask {\n"
|
2019-08-30 07:21:49 +00:00
|
|
|
+ " HALTED = " + halted + "\n"
|
2019-08-25 16:06:36 +00:00
|
|
|
+ " tickers = " + tickers + "\n"
|
|
|
|
+ " move = " + move + "\n"
|
|
|
|
+ " delete = " + delete + "\n"
|
2019-08-30 07:21:49 +00:00
|
|
|
+ " chunks = " + chunkItemCount + "\n"
|
|
|
|
+ " machines = " + machineCount + "\n"
|
|
|
|
+ " machinetime = " + machineTimings + "\n"
|
|
|
|
+ " chunktime = " + chunkTimings + "\n"
|
|
|
|
+ " skipped = " + chunksSkipped + "\n"
|
2019-08-25 16:06:36 +00:00
|
|
|
+ "}";
|
|
|
|
}
|
2016-04-14 16:24:03 +00:00
|
|
|
|
|
|
|
}
|