I made a color palette with a jPanel and a JLabel array in it. At first it worked well, but then i put some other jLabels out of the JPanel and added them some events. Now I keep getting this error:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeLo(TimSort.java:747)
at java.util.TimSort.mergeAt(TimSort.java:483)
at java.util.TimSort.mergeCollapse(TimSort.java:410)
at java.util.TimSort.sort(TimSort.java:214)
at java.util.TimSort.sort(TimSort.java:173)
at java.util.Arrays.sort(Arrays.java:659)
at java.util.Collections.sort(Collections.java:217)
at javax.swing.SortingFocusTraversalPolicy.enumerateAndSortCycle(SortingFocusTraversalPolicy.java:136)
at javax.swing.SortingFocusTraversalPolicy.getFocusTraversalCycle(SortingFocusTraversalPolicy.java:110)
at javax.swing.SortingFocusTraversalPolicy.getFirstComponent(SortingFocusTraversalPolicy.java:435)
at javax.swing.LayoutFocusTraversalPolicy.getFirstComponent(LayoutFocusTraversalPolicy.java:166)
at javax.swing.SortingFocusTraversalPolicy.getDefaultComponent(SortingFocusTraversalPolicy.java:515)
at java.awt.FocusTraversalPolicy.getInitialComponent(FocusTraversalPolicy.java:169)
at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:380)
at java.awt.Component.dispatchEventImpl(Component.java:4731)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Window.dispatchEventImpl(Window.java:2719)
at java.awt.Component.dispatchEvent(Component.java:4687)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:723)
at java.awt.EventQueue.access$200(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:682)
at java.awt.EventQueue$3.run(EventQueue.java:680)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:696)
at java.awt.EventQueue$4.run(EventQueue.java:694)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:693)
at java.awt.SequencedEvent.dispatch(SequencedEvent.java:116)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:721)
at java.awt.EventQueue.access$200(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:682)
at java.awt.EventQueue$3.run(EventQueue.java:680)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:696)
at java.awt.EventQueue$4.run(EventQueue.java:694)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:693)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:244)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:163)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:139)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:97)
I tried to remove everything i've done after first time i got this error, but still keep getting it. When i change the layout from GridLayout to anything else, then the error disappears, but the code becomes useless. So i need GridLayout. When i move everything in that JPanel to another JPanel, the error also goes away. But when i remove the first JPanel, error comes back.
By the way, the program works, but it's not pleasent to keep getting errors...
Edit: When i use less than 225 color, there's no error. I'm really curious about what's happening. Any explanation would be appreciated...
It seems to me like you've hit a bug in the JDK since the error seems to come from Swing classes.
Options:
Define the property java.util.Arrays.useLegacyMergeSort as true. Either using in your code the line
System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
before any Swing code. As the first line in the main method should work.
Or adding
-Djava.util.Arrays.useLegacyMergeSort=true
to your starting options (in the console, or in the project properties in an IDE, Ant script, etc.)
Upgrade your JDK and see if the problem goes away
Downgrade to Java 6
Report my findings:
-Djava.util.Arrays.useLegacyMergeSort=true
works
but
System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
does not work.
It is due to the fact that in JDK Arrays.class
static final class LegacyMergeSort {
private static final boolean userRequested = ...
It is a static variable which is defined when jvm starts. Setting System property in the program will have no effect if the class has been loaded into jvm.
I have beeing monitoring the LegacyMergeSort.userRequested variable, and the findings confirmed with above statement.
Update:
The program must set system properties before java.util.Arrays is loaded to classloader.
Otherwise, once it is loaded, setting the properties is not going to be useful due to the reason mentioned above.
Make sure nothing else loaded Arrays.class:
By putting following code to your program to test:
java.lang.reflect.Method m = ClassLoader.class.getDeclaredMethod("findLoadedClass", new Class[] { String.class });
m.setAccessible(true);
ClassLoader cl = ClassLoader.getSystemClassLoader();
Object test1 = m.invoke(cl, "java.util.Arrays");
System.out.println("test1 loaded? ->" + (test1 != null));
[Update]
This solution unfortunately is not guaranteed to solve the problem in all cases. It is not enough to patch the default SortingFocusTraversalPolicy
of the KeyboardFocusManager.
I recommend to read the answer by Robin Loxley below, including his Update.
[/Update]
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeHi(TimSort.java:868)
This problem is caused by a bug in javax.swing.LayoutComparator.
The following class installs a fixed version of javax.swing.LayoutComparator, which does not violate the contract of Comparator<Component>. This (or any other) fixed version of javax.swing.LayoutComparator should be submitted to Oracle by some Oracle contributor.
package ...;
import java.awt.Component;
import java.awt.ComponentOrientation;
import java.awt.FocusTraversalPolicy;
import java.awt.KeyboardFocusManager;
import java.awt.Window;
import java.lang.reflect.Field;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.ListIterator;
import javax.swing.JRootPane;
import javax.swing.SortingFocusTraversalPolicy;
import javax.swing.UIManager;
/**
* Uses reflection to install a fixed version of {#link javax.swing.LayoutComparator} to solve the
* LayoutFocusTraversalPolicy/TimSort problem.
*
* <p>
* <code>java.lang.IllegalArgumentException: Comparison method violates its general contract!</code>
* <br/>
* {#code at java.util.TimSort.mergeHi(TimSort.java:868)}
* </p>
* <p>
* Usage: call {#code Class.forName(LayoutFocusTraversalPolicyTimSortBugFixer.class.getName())}
* before creating Swing components.
* </p>
*
* #author Burkhard Strauss
* #since Feb 2015
*/
public class LayoutFocusTraversalPolicyTimSortBugFixer
{
static
{
UIManager.getUI(new JRootPane()); // make Swing install the SortingFocusTraversalPolicy
final KeyboardFocusManager keyboardFocusManager = KeyboardFocusManager
.getCurrentKeyboardFocusManager();
final FocusTraversalPolicy focusTraversalPolicy = keyboardFocusManager
.getDefaultFocusTraversalPolicy();
boolean fixed = false;
if (focusTraversalPolicy instanceof SortingFocusTraversalPolicy)
{
try
{
final Field field = SortingFocusTraversalPolicy.class.getDeclaredField("comparator");
final boolean accessible = field.isAccessible();
try
{
field.setAccessible(true);
field.set(focusTraversalPolicy, new LayoutComparator());
fixed = true;
}
finally
{
field.setAccessible(accessible);
}
}
catch (final Exception e)
{
}
}
if (!fixed)
{
Loggers.getLoggerFor(LayoutFocusTraversalPolicyTimSortBugFixer.class).warn("could not fix the bug");
}
}
/**
* Fixed version of {#link javax.swing.LayoutComparator}.
* <p>
* Search for 'bugfix' in the code.
* </p>
*
* #author Burkhard Strauss
* #since Feb 2015
*/
#SuppressWarnings("serial")
private static class LayoutComparator implements Comparator<Component>, java.io.Serializable
{
private static final int ROW_TOLERANCE = 10;
private boolean horizontal = true;
private boolean leftToRight = true;
#SuppressWarnings("unused")
void setComponentOrientation(final ComponentOrientation orientation)
{
horizontal = orientation.isHorizontal();
leftToRight = orientation.isLeftToRight();
}
#Override
public int compare(Component a, Component b)
{
if (a == b)
{
return 0;
}
// Row/Column algorithm only applies to siblings. If 'a' and 'b'
// aren't siblings, then we need to find their most inferior
// ancestors which share a parent. Compute the ancestory lists for
// each Component and then search from the Window down until the
// hierarchy branches.
if (a.getParent() != b.getParent())
{
final LinkedList<Component> aAncestory = new LinkedList<Component>();
for (; a != null; a = a.getParent())
{
aAncestory.add(a);
if (a instanceof Window)
{
break;
}
}
if (a == null)
{
// 'a' is not part of a Window hierarchy. Can't cope.
throw new ClassCastException();
}
final LinkedList<Component> bAncestory = new LinkedList<Component>();
for (; b != null; b = b.getParent())
{
bAncestory.add(b);
if (b instanceof Window)
{
break;
}
}
if (b == null)
{
// 'b' is not part of a Window hierarchy. Can't cope.
throw new ClassCastException();
}
for (ListIterator<Component> aIter = aAncestory.listIterator(aAncestory.size()), bIter = bAncestory
.listIterator(bAncestory.size());;)
{
if (aIter.hasPrevious())
{
a = aIter.previous();
}
else
{
// a is an ancestor of b
return -1;
}
if (bIter.hasPrevious())
{
b = bIter.previous();
}
else
{
// b is an ancestor of a
return 1;
}
if (a != b)
{
break;
}
}
}
final int ax = a.getX(), ay = a.getY(), bx = b.getX(), by = b.getY();
int zOrder = a.getParent().getComponentZOrder(a) - b.getParent().getComponentZOrder(b);
{
//
// Here is the bugfix:
// Don't return 0 if a != b. This would violate the contract of
// Comparator<Component>.compare().
//
if (zOrder == 0)
{
zOrder = -1;
}
}
if (horizontal)
{
if (leftToRight)
{
// LT - Western Europe (optional for Japanese, Chinese, Korean)
if (Math.abs(ay - by) < ROW_TOLERANCE)
{
return (ax < bx) ? -1 : ((ax > bx) ? 1 : zOrder);
}
else
{
return (ay < by) ? -1 : 1;
}
}
else
{ // !leftToRight
// RT - Middle East (Arabic, Hebrew)
if (Math.abs(ay - by) < ROW_TOLERANCE)
{
return (ax > bx) ? -1 : ((ax < bx) ? 1 : zOrder);
}
else
{
return (ay < by) ? -1 : 1;
}
}
}
else
{ // !horizontal
if (leftToRight)
{
// TL - Mongolian
if (Math.abs(ax - bx) < ROW_TOLERANCE)
{
return (ay < by) ? -1 : ((ay > by) ? 1 : zOrder);
}
else
{
return (ax < bx) ? -1 : 1;
}
}
else
{ // !leftToRight
// TR - Japanese, Chinese, Korean
if (Math.abs(ax - bx) < ROW_TOLERANCE)
{
return (ay < by) ? -1 : ((ay > by) ? 1 : zOrder);
}
else
{
return (ax > bx) ? -1 : 1;
}
}
}
}
}
}
I just ran into the same error and spent a good amount of time tracking it down. To help others who run into this error it is important to know how to test TimSort. The checks that violate the transitivity contract and throw this error are deep in the algorithm and require a test to meet certain criteria before this problem can be reproduced.
Create a list with 32 or more objects.
Within that list, there needs to two or more runs.
Each run must contain 3 or more objects.
Once you meet those two criteria you can begin testing for this failure.
A run is defined as a sub-set of the list where each item is already in the desired ordered state.
It is not enough to patch LayoutComparator as suggerested above. This fix does not work in my case.
The issue was fixed in JDK 8 (8u45 at least).
SortingFocusTraversalPolicy to use legacy Merge Sort Method.
There is nothing wrong with the JDK.
I was facing the same issue since 2 days & finally got to know that bug was with my date-format.
In my API response few dates were in "dd-MM-yyyy HH:mm" format while few of them were in "dd/MM/yyyy HH:mm" format.
Same issue while comparing integers, May be your List is having some null values.
Here is my code, which is working like a charm
Collections.sort(root_array, new Comparator<RootResponseItem>(){
public int compare(RootResponseItem o1, RootResponseItem o2){
Date date1 = new Date();
String dtStart = o1.getSectors().get(0).getDeparture().getDate() + " " + o1.getSectors().get(0).getDeparture().getTime();
dtStart = dtStart.replaceAll("-","/");
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm");
try {
date1 = format.parse(dtStart);
} catch (ParseException e) {
e.printStackTrace();
}
Date date2 = new Date();
String dtStart2 = o2.getSectors().get(0).getDeparture().getDate() + " " + o2.getSectors().get(0).getDeparture().getTime();
dtStart2 = dtStart2.replaceAll("-","/");
SimpleDateFormat format2 = new SimpleDateFormat("dd/MM/yyyy HH:mm");
try {
date2 = format2.parse(dtStart2);
} catch (ParseException e) {
e.printStackTrace();
}
return date1.compareTo(date2);
}
});
Related
I am writing a program that checks prices and if it increases past a set amount then lets the user know by putting into a JavaFX text area line by line with a time stamp, appendText() spits out 2 errors. The error codes don't point to anything specific which is causing me to go in circles.
Most of the code works and if I use System.out.print() instead the code runs perfectly, but if I use txtContent.appendText() then at a random time in the first five minutes I will get one of the following errors.
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException: Cannot read the array length because "this.lines" is null
at javafx.graphics#19/com.sun.javafx.text.PrismTextLayout.layout(PrismTextLayout.java:1222)
at javafx.graphics#19/com.sun.javafx.text.PrismTextLayout.ensureLayout(PrismTextLayout.java:223)
at javafx.graphics#19/com.sun.javafx.text.PrismTextLayout.getBounds(PrismTextLayout.java:246)
at javafx.graphics#19/javafx.scene.text.Text.getLogicalBounds(Text.java:432)
at javafx.graphics#19/javafx.scene.text.Text.doComputeGeomBounds(Text.java:1187)
at javafx.graphics#19/javafx.scene.text.Text$1.doComputeGeomBounds(Text.java:149)
at javafx.graphics#19/com.sun.javafx.scene.shape.TextHelper.computeGeomBoundsImpl(TextHelper.java:90)
at javafx.graphics#19/com.sun.javafx.scene.NodeHelper.computeGeomBounds(NodeHelper.java:117)
at javafx.graphics#19/javafx.scene.Node.updateGeomBounds(Node.java:3825)
at javafx.graphics#19/javafx.scene.Node.getGeomBounds(Node.java:3787)
at javafx.graphics#19/javafx.scene.Node.getLocalBounds(Node.java:3735)
at javafx.graphics#19/javafx.scene.Node$MiscProperties$3.computeBounds(Node.java:6825)
at javafx.graphics#19/javafx.scene.Node$LazyBoundsProperty.get(Node.java:9840)
at javafx.graphics#19/javafx.scene.Node$LazyBoundsProperty.get(Node.java:9810)
at javafx.graphics#19/javafx.scene.Node.getBoundsInLocal(Node.java:3415)
at javafx.controls#19/javafx.scene.control.skin.TextAreaSkin$ContentView.layoutChildren(TextAreaSkin.java:1324)
at javafx.graphics#19/javafx.scene.Parent.layout(Parent.java:1207)
at javafx.graphics#19/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics#19/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics#19/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics#19/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics#19/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics#19/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics#19/javafx.scene.Scene.doLayoutPass(Scene.java:592)
at javafx.graphics#19/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2512)
at javafx.graphics#19/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:407)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at javafx.graphics#19/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:406)
at javafx.graphics#19/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:436)
at javafx.graphics#19/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:575)
at javafx.graphics#19/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:555)
at javafx.graphics#19/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:548)
at javafx.graphics#19/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:352)
at javafx.graphics#19/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics#19/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics#19/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
at java.base/java.lang.Thread.run(Thread.java:1589)
Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: Index -1 out of bounds for length 2
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:100)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:106)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:302)
at java.base/java.util.Objects.checkIndex(Objects.java:385)
at java.base/java.util.ArrayList.get(ArrayList.java:427)
at javafx.base#19/com.sun.javafx.collections.ObservableListWrapper.get(ObservableListWrapper.java:89)
at javafx.base#19/com.sun.javafx.collections.VetoableListDecorator.get(VetoableListDecorator.java:305)
at javafx.graphics#19/javafx.scene.Parent.updateCachedBounds(Parent.java:1704)
at javafx.graphics#19/javafx.scene.Parent.recomputeBounds(Parent.java:1648)
at javafx.graphics#19/javafx.scene.Parent.doComputeGeomBounds(Parent.java:1501)
at javafx.graphics#19/javafx.scene.Parent$1.doComputeGeomBounds(Parent.java:115)
at javafx.graphics#19/com.sun.javafx.scene.ParentHelper.computeGeomBoundsImpl(ParentHelper.java:84)
at javafx.graphics#19/com.sun.javafx.scene.layout.RegionHelper.superComputeGeomBoundsImpl(RegionHelper.java:78)
at javafx.graphics#19/com.sun.javafx.scene.layout.RegionHelper.superComputeGeomBounds(RegionHelper.java:62)
at javafx.graphics#19/javafx.scene.layout.Region.doComputeGeomBounds(Region.java:3355)
at javafx.graphics#19/javafx.scene.layout.Region$1.doComputeGeomBounds(Region.java:168)
at javafx.graphics#19/com.sun.javafx.scene.layout.RegionHelper.computeGeomBoundsImpl(RegionHelper.java:89)
at javafx.graphics#19/com.sun.javafx.scene.NodeHelper.computeGeomBounds(NodeHelper.java:117)
at javafx.graphics#19/javafx.scene.Node.updateGeomBounds(Node.java:3825)
at javafx.graphics#19/javafx.scene.Node.getGeomBounds(Node.java:3787)
at javafx.graphics#19/javafx.scene.Node.getLocalBounds(Node.java:3735)
at javafx.graphics#19/javafx.scene.Node.intersectsBounds(Node.java:5270)
at javafx.graphics#19/javafx.scene.Node$1.intersectsBounds(Node.java:559)
at javafx.graphics#19/com.sun.javafx.scene.NodeHelper.intersectsBounds(NodeHelper.java:264)
at javafx.graphics#19/javafx.scene.layout.Region.doPickNodeLocal(Region.java:3224)
at javafx.graphics#19/javafx.scene.layout.Region$1.doPickNodeLocal(Region.java:184)
at javafx.graphics#19/com.sun.javafx.scene.layout.RegionHelper.pickNodeLocalImpl(RegionHelper.java:104)
at javafx.graphics#19/com.sun.javafx.scene.NodeHelper.pickNodeLocal(NodeHelper.java:130)
at javafx.graphics#19/javafx.scene.Node.pickNode(Node.java:5180)
at javafx.graphics#19/javafx.scene.Scene$MouseHandler.pickNode(Scene.java:4037)
at javafx.graphics#19/javafx.scene.Scene.pick(Scene.java:2067)
at javafx.graphics#19/javafx.scene.Scene$MouseHandler.process(Scene.java:3847)
at javafx.graphics#19/javafx.scene.Scene.processMouseEvent(Scene.java:1887)
at javafx.graphics#19/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2620)
at javafx.graphics#19/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:411)
at javafx.graphics#19/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:301)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at javafx.graphics#19/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:450)
at javafx.graphics#19/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
at javafx.graphics#19/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:449)
at javafx.graphics#19/com.sun.glass.ui.View.handleMouseEvent(View.java:551)
at javafx.graphics#19/com.sun.glass.ui.View.notifyMouse(View.java:937)
at javafx.graphics#19/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics#19/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
at java.base/java.lang.Thread.run(Thread.java:1589)
Normally when I get errors like this I will follow errors to the part that I wrote something incorrect or made some mistake with my work. But these don't point to anything in particular other than my runLoop which is pretty simple.
try
{
Database.deleteLastRow();
Database.updateRows();
JSONAccess.createNewRow();
if(increaseCounter)
{
rowCounter++;
}
if(rowCounter >= Main.calculatedRows)
{
if(testLine)
{
System.out.println("Starting");
testLine = false;
}
increaseCounter = false;
MainGUI.txtContent.appendText("\n New Section");
Database.compareValues();
}
}
catch (Exception e)
{
MainGUI.btnStart.setDisable(false);
MainGUI.btnStop.setDisable(true);
System.out.println("Test to see if something goes wrong");
}
public static void compareValues() throws Exception
{
Class.forName("org.hsqldb.jdbc.JDBCDriver");
for (String tableName : symbolsList)
{
String compareSql = "SELECT * FROM tbl_" + tableName + " ORDER BY id";
prepStatement = connection.prepareStatement(compareSql);
ResultSet rs = prepStatement.executeQuery();
int rowNum = 1;
while (rs.next())
{
if (rowNum == 1)
{
dblNew = rs.getDouble("val");
}
if (rowNum == Main.calculatedRows)
{
dblOld = rs.getDouble("val");
}
rowNum = Main.calculatedRows;
}
mathsCompare(tableName, dblNew, dblOld);
}
}
public static void mathsCompare(String tableName1, double dblNew1, double dblOld1) throws Exception
{
if(dblNew1>dblOld1)
{
double dblChange = ((dblNew1-dblOld1)/dblOld1)*100;
if(dblChange >= Main.dblPercentage)
{
MainGUI.txtContent.appendText("\n" + tableName1);
System.out.print("\n" + tableName1);
}
}
}
If I have both System.out.println and MainGUI.txtContent.appendText enabled then the console gets an extra set of values out before the error comes out but thats when I get stumped
Any help appreciated.
If you had read my other question, you'll know I've spent this weekend putting together a 6502 CPU emulator as a programming exercise.
The CPU emulator is mostly complete, and seems to be fairly accurate from my limited testing, however it is running incredibly fast, and I want to throttle it down to the actual clock speed of the machine.
My current test loop is this:
// Just loop infinitely.
while (1 == 1)
{
CPU.ClockCyclesBeforeNext--;
if (CPU.ClockCyclesBeforeNext <= 0)
{
// Find out how many clock cycles this instruction will take
CPU.ClockCyclesBeforeNext = CPU.OpcodeMapper.Map[CPU.Memory[CPU.PC]].CpuCycles;
// Run the instruction
CPU.ExecuteInstruction(CPU.Memory[CPU.PC]);
// Debugging Info
CPU.DumpDebug();
Console.WriteLine(CPU.OpcodeMapper.Map[CPU.Memory[CPU.PC]].ArgumentLength);
// Move to next instruction
CPU.PC += 1 + CPU.OpcodeMapper.Map[CPU.Memory[CPU.PC]].ArgumentLength;
}
}
As you can tell, each opcode takes a specific amount of time to complete, so I do not run the next instruction until I count down the CPU Cycle clock. This provides proper timing between opcodes, its just that the entire thing runs way to fast.
The targeted CPU speed is 1.79mhz, however I'd like whatever solution to the clock issue to keep the speed at 1.79mhz even as I add complexity, so I don't have to adjust it up.
Any ideas?
I wrote a Z80 emulator many years ago, and to do cycle accurate execution, I divided the clock rate into a number of small blocks and had the core execute that many clock cycles. In my case, I tied it to the frame rate of the game system I was emulating. Each opcode knew how many cycles it took to execute and the core would keep running opcodes until the specified number of cycles had been executed. I had an outer run loop that would run the cpu core, and run other parts of the emulated system and then sleep until the start time of the next iteration.
EDIT: Adding example of run loop.
int execute_run_loop( int cycles )
{
int n = 0;
while( n < cycles )
{
/* Returns number of cycles executed */
n += execute_next_opcode();
}
return n;
}
Hope this helps.
Take a look at the original quicktime documentation for inspiration.
It was written a long time ago, when displaying video meant just swapping still frames at high enough speed, but the Apple guys decided they needed a full time-management framework. The design at first looks overengineered, but it let them deal with widely different speed requirements and keep them tightly synchronized.
you're fortunate that 6502 has deterministic time behaviour, the exact time each instruction takes is well documented; but it's not constant. some instructions take 2 cycles, other 3. Just like frames in QuickTime, a video doesn't have a 'frames per second' parameter, each frame tells how long it wants to be in screen.
Since modern CPU's are so non-deterministic, and multitasking OS's can even freeze for a few miliseconds (virtual memory!), you should keep a tab if you're behind schedule, or if you can take a few microseconds nap.
As jfk says, the most common way to do this is tie the cpu speed to the vertical refresh of the (emulated) video output.
Pick a number of cycles to run per video frame. This will often be machine-specific but you can calculate it by something like :
cycles = clock speed in Hz / required frames-per-second
Then you also get to do a sleep until the video update is hit, at which point you start the next n cycles of CPU emulation.
If you're emulating something in particular then you just need to look up the fps rate and processor speed to get this approximately right.
EDIT: If you don't have any external timing requirements then it is normal for an emulator to just run as fast as it possibly can. Sometimes this is a desired effect and sometimes not :)
I would use the clock cycles to calculate time and them sleep the difference in time. Of course, to do this, you need a high-resolution clock. They way you are doing it is going to spike the CPU in spinning loops.
Yes, as said before most of the time you don't need a CPU emulator to emulate instructions at the same speed of the real thing. What user perceive is the output of the computation (i.e. audio and video outputs) so you only need to be in sync with such outputs which doesn't mean you must have necessarily an exact CPU emulation speed.
In other words, if the frame rate of the video input is, let's say, 50Hz, then let the CPU emulator run as fast as it can to draw the screen but be sure to output the screen frames at the correct rate (50Hz). From an external point of view your emulator is emulating at the correct speed.
Trying to be cycle exact even in the execution time is a non-sense on a multi-tasking OS like Windows or Linux because the emulator instruction time (tipically 1uS for vintage 80s CPUs) and the scheduling time slot of the modern OS are comparable.
Trying to output something at a 50Hz rate is a much simpler task you can do very good on any modern machine
Another option is available if audio emulation is implemented, and if audio output is tied to the system/CPU clock. In particular I know that this is the case with the 8-bit Apple ][ computers.
Usually sound is generated in buffers of a fixed size (which is a fixed time), so operation (generation of data etc) of these buffers can be tied to CPU throughput via synchronization primitives.
I am in the process of making something a little more general use case based, such as the ability to convert time to an estimated amount of instructions and vice versa.
The project homepage is # http://net7mma.codeplex.com
The code starts like this: (I think)
#region Copyright
/*
This file came from Managed Media Aggregation, You can always find the latest version # https://net7mma.codeplex.com/
Julius.Friedman#gmail.com / (SR. Software Engineer ASTI Transportation Inc. http://www.asti-trans.com)
Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction,
* including without limitation the rights to :
* use,
* copy,
* modify,
* merge,
* publish,
* distribute,
* sublicense,
* and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
*
* JuliusFriedman#gmail.com should be contacted for further details.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
*
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE,
* ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* v//
*/
#endregion
namespace Media.Concepts.Classes
{
//Windows.Media.Clock has a fairly complex but complete API
/// <summary>
/// Provides a clock with a given offset and calendar.
/// </summary>
public class Clock : Media.Common.BaseDisposable
{
static bool GC = false;
#region Fields
/// <summary>
/// Indicates when the clock was created
/// </summary>
public readonly System.DateTimeOffset Created;
/// <summary>
/// The calendar system of the clock
/// </summary>
public readonly System.Globalization.Calendar Calendar;
/// <summary>
/// The amount of ticks which occur per update of the <see cref="System.Environment.TickCount"/> member.
/// </summary>
public readonly long TicksPerUpdate;
/// <summary>
/// The amount of instructions which occured when synchronizing with the system clock.
/// </summary>
public readonly long InstructionsPerClockUpdate;
#endregion
#region Properties
/// <summary>
/// The TimeZone offset of the clock from UTC
/// </summary>
public System.TimeSpan Offset { get { return Created.Offset; } }
/// <summary>
/// The average amount of operations per tick.
/// </summary>
public long AverageOperationsPerTick { get { return InstructionsPerClockUpdate / TicksPerUpdate; } }
/// <summary>
/// The <see cref="System.TimeSpan"/> which represents <see cref="TicksPerUpdate"/> as an amount of time.
/// </summary>
public System.TimeSpan SystemClockResolution { get { return System.TimeSpan.FromTicks(TicksPerUpdate); } }
/// <summary>
/// Return the current system time in the TimeZone offset of this clock
/// </summary>
public System.DateTimeOffset Now { get { return System.DateTimeOffset.Now.ToOffset(Offset).Add(new System.TimeSpan((long)(AverageOperationsPerTick / System.TimeSpan.TicksPerMillisecond))); } }
/// <summary>
/// Return the current system time in the TimeZone offset of this clock converter to UniversalTime.
/// </summary>
public System.DateTimeOffset UtcNow { get { return Now.ToUniversalTime(); } }
//public bool IsUtc { get { return Offset == System.TimeSpan.Zero; } }
//public bool IsDaylightSavingTime { get { return Created.LocalDateTime.IsDaylightSavingTime(); } }
#endregion
#region Constructor
/// <summary>
/// Creates a clock using the system's current timezone and calendar.
/// The system clock is profiled to determine it's accuracy
/// <see cref="System.DateTimeOffset.Now.Offset"/>
/// <see cref="System.Globalization.CultureInfo.CurrentCulture.Calendar"/>
/// </summary>
public Clock(bool shouldDispose = true)
: this(System.DateTimeOffset.Now.Offset, System.Globalization.CultureInfo.CurrentCulture.Calendar, shouldDispose)
{
try { if (false == GC && System.Runtime.GCSettings.LatencyMode != System.Runtime.GCLatencyMode.NoGCRegion) GC = System.GC.TryStartNoGCRegion(0); }
catch { }
finally
{
System.Threading.Thread.BeginCriticalRegion();
//Sample the TickCount
long ticksStart = System.Environment.TickCount,
ticksEnd;
//Continually sample the TickCount. while the value has not changed increment InstructionsPerClockUpdate
while ((ticksEnd = System.Environment.TickCount) == ticksStart) ++InstructionsPerClockUpdate; //+= 4; Read,Assign,Compare,Increment
//How many ticks occur per update of TickCount
TicksPerUpdate = ticksEnd - ticksStart;
System.Threading.Thread.EndCriticalRegion();
}
}
/// <summary>
/// Constructs a new clock using the given TimeZone offset and Calendar system
/// </summary>
/// <param name="timeZoneOffset"></param>
/// <param name="calendar"></param>
/// <param name="shouldDispose">Indicates if the instace should be diposed when Dispose is called.</param>
public Clock(System.TimeSpan timeZoneOffset, System.Globalization.Calendar calendar, bool shouldDispose = true)
{
//Allow disposal
ShouldDispose = shouldDispose;
Calendar = System.Globalization.CultureInfo.CurrentCulture.Calendar;
Created = new System.DateTimeOffset(System.DateTime.Now, timeZoneOffset);
}
#endregion
#region Overrides
public override void Dispose()
{
if (false == ShouldDispose) return;
base.Dispose();
try
{
if (System.Runtime.GCSettings.LatencyMode == System.Runtime.GCLatencyMode.NoGCRegion)
{
System.GC.EndNoGCRegion();
GC = false;
}
}
catch { }
}
#endregion
//Methods or statics for OperationCountToTimeSpan? (Estimate)
public void NanoSleep(int nanos)
{
Clock.NanoSleep((long)nanos);
}
public static void NanoSleep(long nanos)
{
System.Threading.Thread.BeginCriticalRegion();
NanoSleep(ref nanos);
System.Threading.Thread.EndCriticalRegion();
}
static void NanoSleep(ref long nanos)
{
try
{
unchecked
{
while (Common.Binary.Clamp(--nanos, 0, 1) >= 2)
{
/* if(--nanos % 2 == 0) */
NanoSleep(long.MinValue); //nanos -= 1 + (ops / (ulong)AverageOperationsPerTick);// *10;
}
}
}
catch
{
return;
}
}
}
}
Once you have some type of layman clock implementation you advance to something like a Timer
/// <summary>
/// Provides a Timer implementation which can be used across all platforms and does not rely on the existing Timer implementation.
/// </summary>
public class Timer : Common.BaseDisposable
{
readonly System.Threading.Thread m_Counter; // m_Consumer, m_Producer
internal System.TimeSpan m_Frequency;
internal ulong m_Ops = 0, m_Ticks = 0;
bool m_Enabled;
internal System.DateTimeOffset m_Started;
public delegate void TickEvent(ref long ticks);
public event TickEvent Tick;
public bool Enabled { get { return m_Enabled; } set { m_Enabled = value; } }
public System.TimeSpan Frequency { get { return m_Frequency; } }
internal ulong m_Bias;
//
//Could just use a single int, 32 bits is more than enough.
//uint m_Flags;
//
readonly internal Clock m_Clock = new Clock();
readonly internal System.Collections.Generic.Queue<long> Producer;
void Count()
{
System.Threading.Thread Event = new System.Threading.Thread(new System.Threading.ThreadStart(() =>
{
System.Threading.Thread.BeginCriticalRegion();
long sample;
AfterSample:
try
{
Top:
System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.Highest;
while (m_Enabled && Producer.Count >= 1)
{
sample = Producer.Dequeue();
Tick(ref sample);
}
System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.Lowest;
if (false == m_Enabled) return;
while (m_Enabled && Producer.Count == 0) if(m_Counter.IsAlive) m_Counter.Join(0); //++m_Ops;
goto Top;
}
catch { if (false == m_Enabled) return; goto AfterSample; }
finally { System.Threading.Thread.EndCriticalRegion(); }
}))
{
IsBackground = false,
Priority = System.Threading.ThreadPriority.AboveNormal
};
Event.TrySetApartmentState(System.Threading.ApartmentState.MTA);
Event.Start();
Approximate:
ulong approximate = (ulong)Common.Binary.Clamp((m_Clock.AverageOperationsPerTick / (Frequency.Ticks + 1)), 1, ulong.MaxValue);
try
{
m_Started = m_Clock.Now;
System.Threading.Thread.BeginCriticalRegion();
unchecked
{
Start:
if (IsDisposed) return;
switch (++m_Ops)
{
default:
{
if (m_Bias + ++m_Ops >= approximate)
{
System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.Highest;
Producer.Enqueue((long)m_Ticks++);
ulong x = ++m_Ops / approximate;
while (1 > --x /*&& Producer.Count <= m_Frequency.Ticks*/) Producer.Enqueue((long)++m_Ticks);
m_Ops = (++m_Ops * m_Ticks) - (m_Bias = ++m_Ops / approximate);
System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.Lowest;
}
if(Event != null) Event.Join(m_Frequency);
goto Start;
}
}
}
}
catch (System.Threading.ThreadAbortException) { if (m_Enabled) goto Approximate; System.Threading.Thread.ResetAbort(); }
catch (System.OutOfMemoryException) { if ((ulong)Producer.Count > approximate) Producer.Clear(); if (m_Enabled) goto Approximate; }
catch { if (m_Enabled) goto Approximate; }
finally
{
Event = null;
System.Threading.Thread.EndCriticalRegion();
}
}
public Timer(System.TimeSpan frequency)
{
Producer = new System.Collections.Generic.Queue<long>((int)(m_Frequency = frequency).Ticks * 10);
m_Counter = new System.Threading.Thread(new System.Threading.ThreadStart(Count))
{
IsBackground = false,
Priority = System.Threading.ThreadPriority.AboveNormal
};
m_Counter.TrySetApartmentState(System.Threading.ApartmentState.MTA);
Tick = delegate { m_Ops += 1 + m_Bias; };
}
public void Start()
{
if (m_Enabled) return;
m_Enabled = true;
m_Counter.Start();
var p = System.Threading.Thread.CurrentThread.Priority;
System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.Lowest;
while (m_Ops == 0) m_Counter.Join(0); //m_Clock.NanoSleep(0);
System.Threading.Thread.CurrentThread.Priority = p;
}
public void Stop()
{
m_Enabled = false;
}
void Change(System.TimeSpan interval, System.TimeSpan dueTime)
{
m_Enabled = false;
m_Frequency = interval;
m_Enabled = true;
}
delegate void ElapsedEvent(object sender, object args);
public override void Dispose()
{
if (IsDisposed) return;
base.Dispose();
Stop();
try { m_Counter.Abort(m_Frequency); }
catch (System.Threading.ThreadAbortException) { System.Threading.Thread.ResetAbort(); }
catch { }
Tick = null;
//Producer.Clear();
}
}
Then you can really replicate some logic using something like
/// <summary>
/// Provides a completely managed implementation of <see cref="System.Diagnostics.Stopwatch"/> which expresses time in the same units as <see cref="System.TimeSpan"/>.
/// </summary>
public class Stopwatch : Common.BaseDisposable
{
internal Timer Timer;
long Units;
public bool Enabled { get { return Timer != null && Timer.Enabled; } }
public double ElapsedMicroseconds { get { return Units * Media.Common.Extensions.TimeSpan.TimeSpanExtensions.TotalMicroseconds(Timer.Frequency); } }
public double ElapsedMilliseconds { get { return Units * Timer.Frequency.TotalMilliseconds; } }
public double ElapsedSeconds { get { return Units * Timer.Frequency.TotalSeconds; } }
//public System.TimeSpan Elapsed { get { return System.TimeSpan.FromMilliseconds(ElapsedMilliseconds / System.TimeSpan.TicksPerMillisecond); } }
public System.TimeSpan Elapsed
{
get
{
switch (Units)
{
case 0: return System.TimeSpan.Zero;
default:
{
System.TimeSpan taken = System.DateTime.UtcNow - Timer.m_Started;
return taken.Add(new System.TimeSpan(Units * Timer.Frequency.Ticks));
//System.TimeSpan additional = new System.TimeSpan(Media.Common.Extensions.Math.MathExtensions.Clamp(Units, 0, Timer.Frequency.Ticks));
//return taken.Add(additional);
}
}
//////The maximum amount of times the timer can elapse in the given frequency
////double maxCount = (taken.TotalMilliseconds / Timer.Frequency.TotalMilliseconds) / ElapsedMilliseconds;
////if (Units > maxCount)
////{
//// //How many more times the event was fired than needed
//// double overage = (maxCount - Units);
//// additional = new System.TimeSpan(System.Convert.ToInt64(Media.Common.Extensions.Math.MathExtensions.Clamp(Units, overage, maxCount)));
//// //return taken.Add(new System.TimeSpan((long)Media.Common.Extensions.Math.MathExtensions.Clamp(Units, overage, maxCount)));
////}
//////return taken.Add(new System.TimeSpan(Units));
}
}
public void Start()
{
if (Enabled) return;
Units = 0;
//Create a Timer that will elapse every OneTick //`OneMicrosecond`
Timer = new Timer(Media.Common.Extensions.TimeSpan.TimeSpanExtensions.OneTick);
//Handle the event by incrementing count
Timer.Tick += Count;
Timer.Start();
}
public void Stop()
{
if (false == Enabled) return;
Timer.Stop();
Timer.Dispose();
}
void Count(ref long count) { ++Units; }
}
Finally, create something semi useful e.g. a Bus and then perhaps a virtual screen to emit data to the bus...
public abstract class Bus : Common.CommonDisposable
{
public readonly Timer Clock = new Timer(Common.Extensions.TimeSpan.TimeSpanExtensions.OneTick);
public Bus() : base(false) { Clock.Start(); }
}
public class ClockedBus : Bus
{
long FrequencyHz, Maximum, End;
readonly Queue<byte[]> Input = new Queue<byte[]>(), Output = new Queue<byte[]>();
readonly double m_Bias;
public ClockedBus(long frequencyHz, double bias = 1.5)
{
m_Bias = bias;
cache = Clock.m_Clock.InstructionsPerClockUpdate / 1000;
SetFrequency(frequencyHz);
Clock.Tick += Clock_Tick;
Clock.Start();
}
public void SetFrequency(long frequencyHz)
{
FrequencyHz = frequencyHz;
//Clock.m_Frequency = new TimeSpan(Clock.m_Clock.InstructionsPerClockUpdate / 1000);
//Maximum = System.TimeSpan.TicksPerSecond / Clock.m_Clock.InstructionsPerClockUpdate;
//Maximum = Clock.m_Clock.InstructionsPerClockUpdate / System.TimeSpan.TicksPerSecond;
Maximum = cache / (cache / FrequencyHz);
Maximum *= System.TimeSpan.TicksPerSecond;
Maximum = (cache / FrequencyHz);
End = Maximum * 2;
Clock.m_Frequency = new TimeSpan(Maximum);
if (cache < frequencyHz * m_Bias) throw new Exception("Cannot obtain stable clock");
Clock.Producer.Clear();
}
public override void Dispose()
{
ShouldDispose = true;
Clock.Tick -= Clock_Tick;
Clock.Stop();
Clock.Dispose();
base.Dispose();
}
~ClockedBus() { Dispose(); }
long sample = 0, steps = 0, count = 0, avg = 0, cache = 1;
void Clock_Tick(ref long ticks)
{
if (ShouldDispose == false && false == IsDisposed)
{
//Console.WriteLine("#ops=>" + Clock.m_Ops + " #ticks=>" + Clock.m_Ticks + " #Lticks=>" + ticks + "#=>" + Clock.m_Clock.Now.TimeOfDay + "#=>" + (Clock.m_Clock.Now - Clock.m_Clock.Created));
steps = sample;
sample = ticks;
++count;
System.ConsoleColor f = System.Console.ForegroundColor;
if (count <= Maximum)
{
System.Console.BackgroundColor = ConsoleColor.Yellow;
System.Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("count=> " + count + "#=>" + Clock.m_Clock.Now.TimeOfDay + "#=>" + (Clock.m_Clock.Now - Clock.m_Clock.Created) + " - " + DateTime.UtcNow.ToString("MM/dd/yyyy hh:mm:ss.ffffff tt"));
avg = Maximum / count;
if (Clock.m_Clock.InstructionsPerClockUpdate / count > Maximum)
{
System.Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("---- Over InstructionsPerClockUpdate ----" + FrequencyHz);
}
}
else if (count >= End)
{
System.Console.BackgroundColor = ConsoleColor.Black;
System.Console.ForegroundColor = ConsoleColor.Blue;
avg = Maximum / count;
Console.WriteLine("avg=> " + avg + "#=>" + FrequencyHz);
count = 0;
}
}
}
//Read, Write at Frequency
}
public class VirtualScreen
{
TimeSpan RefreshRate;
bool VerticalSync;
int Width, Height;
Common.MemorySegment DisplayMemory, BackBuffer, DisplayBuffer;
}
Here is how I tested the StopWatch
internal class StopWatchTests
{
public void TestForOneMicrosecond()
{
System.Collections.Generic.List<System.Tuple<bool, System.TimeSpan, System.TimeSpan>> l = new System.Collections.Generic.List<System.Tuple<bool, System.TimeSpan, System.TimeSpan>>();
//Create a Timer that will elapse every `OneMicrosecond`
for (int i = 0; i <= 250; ++i) using (Media.Concepts.Classes.Stopwatch sw = new Media.Concepts.Classes.Stopwatch())
{
var started = System.DateTime.UtcNow;
System.Console.WriteLine("Started: " + started.ToString("MM/dd/yyyy hh:mm:ss.ffffff tt"));
//Define some amount of time
System.TimeSpan sleepTime = Media.Common.Extensions.TimeSpan.TimeSpanExtensions.OneMicrosecond;
System.Diagnostics.Stopwatch testSw = new System.Diagnostics.Stopwatch();
//Start
testSw.Start();
//Start
sw.Start();
while (testSw.Elapsed.Ticks < sleepTime.Ticks - (Common.Extensions.TimeSpan.TimeSpanExtensions.OneTick + Common.Extensions.TimeSpan.TimeSpanExtensions.OneTick).Ticks)
sw.Timer.m_Clock.NanoSleep(0); //System.Threading.Thread.SpinWait(0);
//Sleep the desired amount
//System.Threading.Thread.Sleep(sleepTime);
//Stop
testSw.Stop();
//Stop
sw.Stop();
var finished = System.DateTime.UtcNow;
var taken = finished - started;
var cc = System.Console.ForegroundColor;
System.Console.WriteLine("Finished: " + finished.ToString("MM/dd/yyyy hh:mm:ss.ffffff tt"));
System.Console.WriteLine("Sleep Time: " + sleepTime.ToString());
System.Console.WriteLine("Real Taken Total: " + taken.ToString());
if (taken > sleepTime)
{
System.Console.ForegroundColor = System.ConsoleColor.Red;
System.Console.WriteLine("Missed by: " + (taken - sleepTime));
}
else
{
System.Console.ForegroundColor = System.ConsoleColor.Green;
System.Console.WriteLine("Still have: " + (sleepTime - taken));
}
System.Console.ForegroundColor = cc;
System.Console.WriteLine("Real Taken msec Total: " + taken.TotalMilliseconds.ToString());
System.Console.WriteLine("Real Taken sec Total: " + taken.TotalSeconds.ToString());
System.Console.WriteLine("Real Taken μs Total: " + Media.Common.Extensions.TimeSpan.TimeSpanExtensions.TotalMicroseconds(taken).ToString());
System.Console.WriteLine("Managed Taken Total: " + sw.Elapsed.ToString());
System.Console.WriteLine("Diagnostic Taken Total: " + testSw.Elapsed.ToString());
System.Console.WriteLine("Diagnostic Elapsed Seconds Total: " + ((testSw.ElapsedTicks / (double)System.Diagnostics.Stopwatch.Frequency)));
//Write the rough amount of time taken in micro seconds
System.Console.WriteLine("Managed Time Estimated Taken: " + sw.ElapsedMicroseconds + "μs");
//Write the rough amount of time taken in micro seconds
System.Console.WriteLine("Diagnostic Time Estimated Taken: " + Media.Common.Extensions.TimeSpan.TimeSpanExtensions.TotalMicroseconds(testSw.Elapsed) + "μs");
System.Console.WriteLine("Managed Time Estimated Taken: " + sw.ElapsedMilliseconds);
System.Console.WriteLine("Diagnostic Time Estimated Taken: " + testSw.ElapsedMilliseconds);
System.Console.WriteLine("Managed Time Estimated Taken: " + sw.ElapsedSeconds);
System.Console.WriteLine("Diagnostic Time Estimated Taken: " + testSw.Elapsed.TotalSeconds);
if (sw.Elapsed < testSw.Elapsed)
{
System.Console.WriteLine("Faster than Diagnostic StopWatch");
l.Add(new System.Tuple<bool, System.TimeSpan, System.TimeSpan>(true, sw.Elapsed, testSw.Elapsed));
}
else if (sw.Elapsed > testSw.Elapsed)
{
System.Console.WriteLine("Slower than Diagnostic StopWatch");
l.Add(new System.Tuple<bool, System.TimeSpan, System.TimeSpan>(false, sw.Elapsed, testSw.Elapsed));
}
else
{
System.Console.WriteLine("Equal to Diagnostic StopWatch");
l.Add(new System.Tuple<bool, System.TimeSpan, System.TimeSpan>(true, sw.Elapsed, testSw.Elapsed));
}
}
int w = 0, f = 0;
var cc2 = System.Console.ForegroundColor;
foreach (var t in l)
{
if (t.Item1)
{
System.Console.ForegroundColor = System.ConsoleColor.Green;
++w; System.Console.WriteLine("Faster than Diagnostic StopWatch by: " + (t.Item3 - t.Item2));
}
else
{
System.Console.ForegroundColor = System.ConsoleColor.Red;
++f; System.Console.WriteLine("Slower than Diagnostic StopWatch by: " + (t.Item2 - t.Item3));
}
}
System.Console.ForegroundColor = System.ConsoleColor.Green;
System.Console.WriteLine("Wins = " + w);
System.Console.ForegroundColor = System.ConsoleColor.Red;
System.Console.WriteLine("Loss = " + f);
System.Console.ForegroundColor = cc2;
}
}
I have three fields
hour -- minutes -- and total
If hour or minutes change i want to calculate a total.
If the total is changed i want to calculate the corresponding minutes and hours.
Example:
1h 30minutes = 1.5 Total
2.25 Total = 2h 15minutes
I am trying to achive this with watch
watch: {
hour: {
handler: (new_hour, old_hour) => {
if(isNaN(new_hour)){
manual.hour = old_hour
}else{
manual.setTotal();
}
}
},
minutes: {
handler: (new_minutes, old_minutes) => {
if(isNaN(new_minutes)){
manual.minutes = old_minutes
}else{
if(Number(new_minutes) > 60){
manual.minutes = old_minutes
}else{
manual.setTotal();
}
}
}
},
total:{
handler: (new_total, old_total) => {
if(isNaN(new_total)) {
manual.total = old_total;
}else{
const hour = new_total.split(",")[0];
const minutes = new_total.split(",")[1];
manual.hour = hour;
manual.minutes = (minutes * 60).toFixed(0);
}
}
}
}
However this is resulting in a loop because on handler allways calls the other handler. How can this be done in a smarter way?
you could use onkeyup listener (and/or change)
new Vue({
el: "#app",
data: {
input_h: 0,
input_m: 0,
input_t: 0
},
methods: {
update_h (e) {
this.input_h = Number(e.target.value)
this.update_t(null)
},
update_m (e) {
this.input_m = Number(e.target.value)
this.update_t(null)
},
update_t (e) {
if (e === null) {
this.input_t = Math.round((this.input_h + this.input_m / 60) * 100)/100
} else {
this.input_t = Number(e.target.value)
this.input_h = Math.floor(this.input_t)
this.input_m = Math.round(this.input_t%1 * 60)
}
},
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.js"></script>
<div id="app">
<input :value="input_h" #keyUp="update_h"/>Hours<br/>
<input :value="input_m" #keyUp="update_m"/>Minutes<br/>
<input :value="input_t" #keyUp="update_t"/>Total<br/>
</div>
Otherwise, if you want to prevent circular dependency, you need to set up a single source of data, and use computed getters and setters to update the other fields. You don't even have to use a visible field for that.
https://jsbin.com/tagupab/edit has a working example
I haven't checked this out, but perhaps you could exchange watchers for computed properties with setter, see ref Computed setter
Note the comment here circular dependency on observed properties #622 (yyx990803 commented on Dec 11, 2014)
The thing is even when there is a circular dependency, the eventual
value should be able to stabilize after 1 additional iteration (which
Vue will then stop because the new evaluated value is the same)
OR
I guess you could put
if (newValue === oldValue) {
return
}
at the top of each watcher. This is sort of what computed does anyway.
My problem is that my JavaFx application has gone to be very slow. Both in the start of the application and in some of the triggered events. It is a calendar application that uses a GridPane, that I am modifying. I have this method:
t.setOnMouseClicked(event->{
long starttid = System.currentTimeMillis();
System.out.println("start");
if (markedTimeEnd != null && markedTimeStart != null) {
colorMinutes(markedTimeStart, markedTimeEnd, Color.BLACK, bakrundWhite);
} else if (markedTimeStart != null) {
colorMinutes(markedTimeStart, markedTimeStart, Color.BLACK, bakrundWhite);
}
long tidNu = System.currentTimeMillis();
long tid = tidNu-starttid;
System.out.println("Print first time:\n"+tid);
int minutTid = gridPane.getRowIndex(t);
int timmeTimme = minutTid / 60;
int minutMinut = minutTid - (60 * timmeTimme);
markedTimeStart = new TidPunkt(timmeTimme, minutMinut);
markedTimeEnd = null;
tid = System.currentTimeMillis() -tidNu;
tidNu = System.currentTimeMillis();
System.out.println("Time for the middel calculations:\n"+tid);
if (markedTimeEnd != null && markedTimeStart != null) {
colorMinutes(markedTimeStart, markedTimeEnd, Color.GREEN,bakrundGren);
} else if (markedTimeStart != null) {
colorMinutes(markedTimeStart, markedTimeStart, Color.GREEN,bakrundGren);
}
event.consume();
repaintAll();
System.out.println("Time to end:\n"+(System.currentTimeMillis()-tidNu));
});
And the code for the colorMinutes:
private void colorMinutes(TidPunkt markedTimeStart, TidPunkt markedTimeEnd, Color colorText, Background colorOther) {
System.out.println("The call is comming");
int startBothTogether = markedTimeStart.getTimme() * 100 + markedTimeStart.getMinut();
int endBothTogether = markedTimeEnd.getTimme() * 100 + markedTimeEnd.getMinut();
System.out.println("Befor filter");
gridPane.getChildren().stream()//parallelStream()
.filter(x-> x.getId()!=null)
.filter(y-> y.getId().matches("\\d\\d:\\d\\d"))
.filter(pp->{
int hoursForPart = Integer.parseInt(((Node) pp).getId().split(":")[0]);
int miutesForPart = Integer.parseInt(((Node) pp).getId().split(":")[1]);
int bothTogether = hoursForPart * 100 + miutesForPart;
if (bothTogether >= startBothTogether && bothTogether <= endBothTogether)
return true;
else
return false;
})
.forEach(pp->{
Platform.runLater(() -> {
System.out.println("Changing collor ----");
if(pp instanceof Pane){
((Pane) pp).setBackground(colorOther)
}else{
((Text) pp).setFill(colorText);
}
});
});
}
But it takes very long before it is change on the screen and it freezes sometime after what I can se is the finish of these methods by the System.out.println. I have been trying to profile but can't figure it out(best I have come up with it that is seems to be a big call tree, of javaFx "stuff" when exiting the method). The System.out.println prints is:
start
Print first time:
0
Time for the middel calculations:
0
The call is comming
Befor filter
Time to end:
373
Changing collor ----
Changing collor ----
Changing collor ----
Changing collor ----
But from button press to all is being color correct it takes many seconds.
The full code can be found here
You're posting to many Runnables using Platform.runLater. There is no reason to use Platform.runLater here at all, since the onMouseClicked event handler is executed on the javafx application thread anyways.
Using
.forEach(pp->{
if(pp instanceof Pane){
((Pane) pp).setBackground(colorOther)
}else{
((Text) pp).setFill(colorText);
}
});
Should improve the performance drastically.
Furthermore you seem to add a huge amout of Nodes in your repaintAll method (more specifically the ritaGrundKalender method) without removing Nodes which increases the number of Runnables for every click. I suggest you change this behavior.
I have the following configuration:
log4j.appender.debug=org.apache.log4j.DailyRollingFileAppender
log4j.appender.debug.File=/path/to/log/log.txt
log4j.appender.debug.Append=true
log4j.appender.debug.DatePattern=.yyyy-MM-dd-HH-mm-ss
log4j.appender.debug.layout=org.apache.log4j.PatternLayout
log4j.appender.debug.layout.ConversionPattern=%n================================%n%d{yyyy-MM-dd-HH-mm-ss}%n%c%n%m %x%n--------------------------------%n
Currently, the files being rolled over is called:
log.txt.2014-10-26-14-12-33
Using the above DatePattern, however I would like the filename rolled over as:
2014-10-26-14-12-33.log.txt
However, it seems as if even when I remove the dot in the beginning and add it to the end, the filename is still appended to the beginning. So:
log4j.appender.debug.DatePattern=yyyy-MM-dd-HH-mm-ss'.ending'
Still logs as
log.txt.2014-10-26-14-12-33.ending
The reason is that I want the files to be easily sorted in the file explorer. I have several log files.
Is there a way to get log4j not to add the file name to the beginning of the rolled file?
Unfortunately no unless you customize and override the method called rollover in http://grepcode.com/file/repo1.maven.org/maven2/log4j/log4j/1.2.14/org/apache/log4j/DailyRollingFileAppender.java.
It does:
String datedFilename = fileName+sdf.format(now);
You will need to do:
String datedFilename = sdf.format(now).toString();
and use that class in your log4j xml.
Below one method has been added and called where normally schedueledTime is altered.
The method is moFilename which is called from two places, everything else is the same.
private String moFileName(File file, Date time) {
return file.getParent() + "/" + sdf.format(time) + "." + file.getName();
}
All code:
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.log4j;
import java.io.IOException;
import java.io.File;
import java.io.InterruptedIOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Calendar;
import java.util.TimeZone;
import java.util.Locale;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.spi.LoggingEvent;
/**
DailyRollingFileAppender extends {#link FileAppender} so that the
underlying file is rolled over at a user chosen frequency.
DailyRollingFileAppender has been observed to exhibit
synchronization issues and data loss. The log4j extras
companion includes alternatives which should be considered
for new deployments and which are discussed in the documentation
for org.apache.log4j.rolling.RollingFileAppender.
<p>The rolling schedule is specified by the <b>DatePattern</b>
option. This pattern should follow the {#link SimpleDateFormat}
conventions. In particular, you <em>must</em> escape literal text
within a pair of single quotes. A formatted version of the date
pattern is used as the suffix for the rolled file name.
<p>For example, if the <b>File</b> option is set to
<code>/foo/bar.log</code> and the <b>DatePattern</b> set to
<code>'.'yyyy-MM-dd</code>, on 2001-02-16 at midnight, the logging
file <code>/foo/bar.log</code> will be copied to
<code>/foo/bar.log.2001-02-16</code> and logging for 2001-02-17
will continue in <code>/foo/bar.log</code> until it rolls over
the next day.
<p>Is is possible to specify monthly, weekly, half-daily, daily,
hourly, or minutely rollover schedules.
<p><table border="1" cellpadding="2">
<tr>
<th>DatePattern</th>
<th>Rollover schedule</th>
<th>Example</th>
<tr>
<td><code>'.'yyyy-MM</code>
<td>Rollover at the beginning of each month</td>
<td>At midnight of May 31st, 2002 <code>/foo/bar.log</code> will be
copied to <code>/foo/bar.log.2002-05</code>. Logging for the month
of June will be output to <code>/foo/bar.log</code> until it is
also rolled over the next month.
<tr>
<td><code>'.'yyyy-ww</code>
<td>Rollover at the first day of each week. The first day of the
week depends on the locale.</td>
<td>Assuming the first day of the week is Sunday, on Saturday
midnight, June 9th 2002, the file <i>/foo/bar.log</i> will be
copied to <i>/foo/bar.log.2002-23</i>. Logging for the 24th week
of 2002 will be output to <code>/foo/bar.log</code> until it is
rolled over the next week.
<tr>
<td><code>'.'yyyy-MM-dd</code>
<td>Rollover at midnight each day.</td>
<td>At midnight, on March 8th, 2002, <code>/foo/bar.log</code> will
be copied to <code>/foo/bar.log.2002-03-08</code>. Logging for the
9th day of March will be output to <code>/foo/bar.log</code> until
it is rolled over the next day.
<tr>
<td><code>'.'yyyy-MM-dd-a</code>
<td>Rollover at midnight and midday of each day.</td>
<td>At noon, on March 9th, 2002, <code>/foo/bar.log</code> will be
copied to <code>/foo/bar.log.2002-03-09-AM</code>. Logging for the
afternoon of the 9th will be output to <code>/foo/bar.log</code>
until it is rolled over at midnight.
<tr>
<td><code>'.'yyyy-MM-dd-HH</code>
<td>Rollover at the top of every hour.</td>
<td>At approximately 11:00.000 o'clock on March 9th, 2002,
<code>/foo/bar.log</code> will be copied to
<code>/foo/bar.log.2002-03-09-10</code>. Logging for the 11th hour
of the 9th of March will be output to <code>/foo/bar.log</code>
until it is rolled over at the beginning of the next hour.
<tr>
<td><code>'.'yyyy-MM-dd-HH-mm</code>
<td>Rollover at the beginning of every minute.</td>
<td>At approximately 11:23,000, on March 9th, 2001,
<code>/foo/bar.log</code> will be copied to
<code>/foo/bar.log.2001-03-09-10-22</code>. Logging for the minute
of 11:23 (9th of March) will be output to
<code>/foo/bar.log</code> until it is rolled over the next minute.
</table>
<p>Do not use the colon ":" character in anywhere in the
<b>DatePattern</b> option. The text before the colon is interpeted
as the protocol specificaion of a URL which is probably not what
you want.
#author Eirik Lygre
#author Ceki Gülcü*/
public class MoDailyRollingFileAppender extends FileAppender {
// The code assumes that the following constants are in a increasing
// sequence.
static final int TOP_OF_TROUBLE=-1;
static final int TOP_OF_MINUTE = 0;
static final int TOP_OF_HOUR = 1;
static final int HALF_DAY = 2;
static final int TOP_OF_DAY = 3;
static final int TOP_OF_WEEK = 4;
static final int TOP_OF_MONTH = 5;
/**
The date pattern. By default, the pattern is set to
"'.'yyyy-MM-dd" meaning daily rollover.
*/
private String datePattern = "'.'yyyy-MM-dd";
/**
The log file will be renamed to the value of the
scheduledFilename variable when the next interval is entered. For
example, if the rollover period is one hour, the log file will be
renamed to the value of "scheduledFilename" at the beginning of
the next hour.
The precise time when a rollover occurs depends on logging
activity.
*/
private String scheduledFilename;
/**
The next time we estimate a rollover should occur. */
private long nextCheck = System.currentTimeMillis () - 1;
Date now = new Date();
SimpleDateFormat sdf;
RollingCalendar rc = new RollingCalendar();
int checkPeriod = TOP_OF_TROUBLE;
// The gmtTimeZone is used only in computeCheckPeriod() method.
static final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT");
/**
The default constructor does nothing. */
public MoDailyRollingFileAppender () {
}
/**
Instantiate a <code>DailyRollingFileAppender</code> and open the
file designated by <code>filename</code>. The opened filename will
become the ouput destination for this appender.
*/
public MoDailyRollingFileAppender (Layout layout, String filename,
String datePattern) throws IOException {
super(layout, filename, true);
this.datePattern = datePattern;
activateOptions();
}
/**
The <b>DatePattern</b> takes a string in the same format as
expected by {#link SimpleDateFormat}. This options determines the
rollover schedule.
*/
public void setDatePattern(String pattern) {
datePattern = pattern;
}
/** Returns the value of the <b>DatePattern</b> option. */
public String getDatePattern() {
return datePattern;
}
public void activateOptions() {
super.activateOptions();
if(datePattern != null && fileName != null) {
now.setTime(System.currentTimeMillis());
sdf = new SimpleDateFormat(datePattern);
int type = computeCheckPeriod();
printPeriodicity(type);
rc.setType(type);
File file = new File(fileName);
// Mo edit
scheduledFilename = moFileName(file, new Date(file.lastModified()));
} else {
LogLog.error("Either File or DatePattern options are not set for appender ["
+name+"].");
}
}
void printPeriodicity(int type) {
switch(type) {
case TOP_OF_MINUTE:
LogLog.debug("Appender ["+name+"] to be rolled every minute.");
break;
case TOP_OF_HOUR:
LogLog.debug("Appender ["+name
+"] to be rolled on top of every hour.");
break;
case HALF_DAY:
LogLog.debug("Appender ["+name
+"] to be rolled at midday and midnight.");
break;
case TOP_OF_DAY:
LogLog.debug("Appender ["+name
+"] to be rolled at midnight.");
break;
case TOP_OF_WEEK:
LogLog.debug("Appender ["+name
+"] to be rolled at start of week.");
break;
case TOP_OF_MONTH:
LogLog.debug("Appender ["+name
+"] to be rolled at start of every month.");
break;
default:
LogLog.warn("Unknown periodicity for appender ["+name+"].");
}
}
// This method computes the roll over period by looping over the
// periods, starting with the shortest, and stopping when the r0 is
// different from from r1, where r0 is the epoch formatted according
// the datePattern (supplied by the user) and r1 is the
// epoch+nextMillis(i) formatted according to datePattern. All date
// formatting is done in GMT and not local format because the test
// logic is based on comparisons relative to 1970-01-01 00:00:00
// GMT (the epoch).
int computeCheckPeriod() {
RollingCalendar rollingCalendar = new RollingCalendar(gmtTimeZone, Locale.getDefault());
// set sate to 1970-01-01 00:00:00 GMT
Date epoch = new Date(0);
if(datePattern != null) {
for(int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
simpleDateFormat.setTimeZone(gmtTimeZone); // do all date formatting in GMT
String r0 = simpleDateFormat.format(epoch);
rollingCalendar.setType(i);
Date next = new Date(rollingCalendar.getNextCheckMillis(epoch));
String r1 = simpleDateFormat.format(next);
//System.out.println("Type = "+i+", r0 = "+r0+", r1 = "+r1);
if(r0 != null && r1 != null && !r0.equals(r1)) {
return i;
}
}
}
return TOP_OF_TROUBLE; // Deliberately head for trouble...
}
/**
Rollover the current file to a new file.
*/
void rollOver() throws IOException {
/* Compute filename, but only if datePattern is specified */
if (datePattern == null) {
errorHandler.error("Missing DatePattern option in rollOver().");
return;
}
File file = new File(fileName);
String datedFilename = moFileName(file, now);
// It is too early to roll over because we are still within the
// bounds of the current interval. Rollover will occur once the
// next interval is reached.
if (scheduledFilename.equals(datedFilename)) {
return;
}
// close current file, and rename it to datedFilename
this.closeFile();
File target = new File(scheduledFilename);
if (target.exists()) {
target.delete();
}
boolean result = file.renameTo(target);
if(result) {
LogLog.debug(fileName +" -> "+ scheduledFilename);
} else {
LogLog.error("Failed to rename ["+fileName+"] to ["+scheduledFilename+"].");
}
try {
// This will also close the file. This is OK since multiple
// close operations are safe.
this.setFile(fileName, true, this.bufferedIO, this.bufferSize);
}
catch(IOException e) {
errorHandler.error("setFile("+fileName+", true) call failed.");
}
scheduledFilename = datedFilename;
}
private String moFileName(File file, Date time) {
return file.getParent() + "/" + sdf.format(time) + "." + file.getName();
}
/**
* This method differentiates DailyRollingFileAppender from its
* super class.
*
* <p>Before actually logging, this method will check whether it is
* time to do a rollover. If it is, it will schedule the next
* rollover time and then rollover.
* */
protected void subAppend(LoggingEvent event) {
long n = System.currentTimeMillis();
if (n >= nextCheck) {
now.setTime(n);
nextCheck = rc.getNextCheckMillis(now);
try {
rollOver();
}
catch(IOException ioe) {
if (ioe instanceof InterruptedIOException) {
Thread.currentThread().interrupt();
}
LogLog.error("rollOver() failed.", ioe);
}
}
super.subAppend(event);
}
}
/**
* RollingCalendar is a helper class to DailyRollingFileAppender.
* Given a periodicity type and the current time, it computes the
* start of the next interval.
* */
class RollingCalendar extends GregorianCalendar {
private static final long serialVersionUID = -3560331770601814177L;
int type = DailyRollingFileAppender.TOP_OF_TROUBLE;
RollingCalendar() {
super();
}
RollingCalendar(TimeZone tz, Locale locale) {
super(tz, locale);
}
void setType(int type) {
this.type = type;
}
public long getNextCheckMillis(Date now) {
return getNextCheckDate(now).getTime();
}
public Date getNextCheckDate(Date now) {
this.setTime(now);
switch(type) {
case DailyRollingFileAppender.TOP_OF_MINUTE:
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.MINUTE, 1);
break;
case DailyRollingFileAppender.TOP_OF_HOUR:
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.HOUR_OF_DAY, 1);
break;
case DailyRollingFileAppender.HALF_DAY:
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
int hour = get(Calendar.HOUR_OF_DAY);
if(hour < 12) {
this.set(Calendar.HOUR_OF_DAY, 12);
} else {
this.set(Calendar.HOUR_OF_DAY, 0);
this.add(Calendar.DAY_OF_MONTH, 1);
}
break;
case DailyRollingFileAppender.TOP_OF_DAY:
this.set(Calendar.HOUR_OF_DAY, 0);
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.DATE, 1);
break;
case DailyRollingFileAppender.TOP_OF_WEEK:
this.set(Calendar.DAY_OF_WEEK, getFirstDayOfWeek());
this.set(Calendar.HOUR_OF_DAY, 0);
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.WEEK_OF_YEAR, 1);
break;
case DailyRollingFileAppender.TOP_OF_MONTH:
this.set(Calendar.DATE, 1);
this.set(Calendar.HOUR_OF_DAY, 0);
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.MONTH, 1);
break;
default:
throw new IllegalStateException("Unknown periodicity type.");
}
return getTime();
}
}
Config file is:
mo.log.pattern=%n================================%n%d{yyyy-MM-dd-HH-mm-ss}%n%c%n%m %x%n--------------------------------%n
mo.log.datepattern=yyyy-MM-dd-HH-mm-ss
log4j.appender.debug=org.apache.log4j.MoDailyRollingFileAppender
log4j.appender.debug.File=/path/to/Generated/Logs/debug.log
log4j.appender.debug.Append=true
log4j.appender.debug.DatePattern=${mo.log.datepattern}
log4j.appender.debug.layout=org.apache.log4j.PatternLayout
log4j.appender.debug.layout.ConversionPattern=${mo.log.pattern}