ctf: replace HashMaps with ArrayLists for EventDeclaration storage
authorMatthew Khouzam <matthew.khouzam@ericsson.com>
Wed, 9 Jul 2014 19:29:04 +0000 (15:29 -0400)
committerMatthew Khouzam <matthew.khouzam@ericsson.com>
Thu, 21 Aug 2014 14:08:54 +0000 (10:08 -0400)
Parser no longer supports events with IDs larger than Integer.MAX_VALUE

Change-Id: I088943c5a041f16638cb89b832ab79f8ef9c1d76
Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Signed-off-by: Alexandre Montplaisir <alexmonthy@voxpopuli.im>
Reviewed-on: https://git.eclipse.org/r/25924
Tested-by: Hudson CI
Reviewed-by: Patrick Tasse <patrick.tasse@gmail.com>
org.eclipse.linuxtools.ctf.core.tests/src/org/eclipse/linuxtools/ctf/core/tests/trace/CTFStreamTest.java
org.eclipse.linuxtools.ctf.core.tests/src/org/eclipse/linuxtools/ctf/core/tests/trace/IOstructgenTest.java
org.eclipse.linuxtools.ctf.core.tests/src/org/eclipse/linuxtools/ctf/core/tests/trace/MetadataTest.java
org.eclipse.linuxtools.ctf.core.tests/src/org/eclipse/linuxtools/ctf/core/tests/types/EventDeclarationTest.java
org.eclipse.linuxtools.ctf.core/src/org/eclipse/linuxtools/ctf/core/trace/CTFStream.java
org.eclipse.linuxtools.ctf.core/src/org/eclipse/linuxtools/ctf/core/trace/CTFStreamInputPacketReader.java
org.eclipse.linuxtools.ctf.core/src/org/eclipse/linuxtools/ctf/core/trace/CTFStreamInputReader.java
org.eclipse.linuxtools.ctf.core/src/org/eclipse/linuxtools/ctf/core/trace/CTFTrace.java
org.eclipse.linuxtools.ctf.core/src/org/eclipse/linuxtools/internal/ctf/core/event/EventDeclaration.java
org.eclipse.linuxtools.tmf.ctf.core/src/org/eclipse/linuxtools/tmf/ctf/core/CtfTmfEvent.java

index ac08fc671d3c5dc1a9ded9caa3f2a17552a8e278..3be9703cd82ab4ffd0de8614aaf77df58f3eec66 100644 (file)
@@ -18,10 +18,8 @@ import static org.junit.Assume.assumeTrue;
 import java.io.File;
 import java.io.FilenameFilter;
 import java.io.IOException;
-import java.util.Map;
 import java.util.Set;
 
-import org.eclipse.linuxtools.ctf.core.event.IEventDeclaration;
 import org.eclipse.linuxtools.ctf.core.event.types.IDeclaration;
 import org.eclipse.linuxtools.ctf.core.event.types.StructDeclaration;
 import org.eclipse.linuxtools.ctf.core.tests.shared.CtfTestTrace;
@@ -156,8 +154,7 @@ public class CTFStreamTest {
      */
     @Test
     public void testGetEvents() {
-        Map<Long, IEventDeclaration> result = fixture.getEvents();
-        assertNotNull(result);
+        assertNotNull(fixture.getEventDeclarations());
     }
 
     /**
index 9424f184caa4d5359dce80da98948b83c2f74513..9b2f7a17037ec3cfaf50d4c9c5b02f4db3f217e2 100644 (file)
@@ -21,7 +21,8 @@ import java.io.FileWriter;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
-import java.util.Map;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.eclipse.linuxtools.ctf.core.event.IEventDeclaration;
 import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException;
@@ -509,8 +510,8 @@ public class IOstructgenTest {
         trace = new CTFTrace(tempTraceDir);
         assertNotNull(trace);
 
-        Map<Long, IEventDeclaration> events = trace.getEvents(0L);
-        final EventDeclaration eventDeclaration = (EventDeclaration) events.get(2L);
+        final List<IEventDeclaration> eventDeclarations = new ArrayList<>(trace.getEventDeclarations(0L));
+        final EventDeclaration eventDeclaration = (EventDeclaration) eventDeclarations.get(2);
         assertEquals("http://example.com/path_to_model?q=ust_tests_demo:done",
                 eventDeclaration.getCustomAttribute("model.emf.uri"));
     }
index cf140481c1afd44aa9d499b6a8fa4f528bf459b3..ab835bfb67c2df7fd956d52e00e072f9784a2c67 100644 (file)
@@ -18,13 +18,16 @@ import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
 
 import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.UUID;
 
+import org.eclipse.linuxtools.ctf.core.event.IEventDeclaration;
 import org.eclipse.linuxtools.ctf.core.tests.shared.CtfTestTrace;
 import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException;
+import org.eclipse.linuxtools.ctf.core.trace.CTFStream;
 import org.eclipse.linuxtools.ctf.core.trace.CTFTrace;
 import org.eclipse.linuxtools.ctf.core.trace.Metadata;
-import org.eclipse.linuxtools.ctf.core.trace.CTFStream;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -198,7 +201,7 @@ public class MetadataTest {
             assertNotNull(s);
         }
         assertEquals(1, count);
-        assertEquals(1, trace.getEvents(0L).size());
+        assertEquals(1, trace.getEventDeclarations(0L).size());
         return trace;
     }
 
@@ -206,8 +209,9 @@ public class MetadataTest {
     public void testStreamTextMD() throws CTFReaderException {
         try (CTFTrace trace = testSingleFragment();) {
             fixture.parseTextFragment(mdSecond);
-            assertEquals(2, trace.getEvents(0L).size());
-            assertEquals("bozo_the_clown", trace.getEvents(0L).get(1L).getName());
+            final List<IEventDeclaration> eventDeclarations = new ArrayList<>(trace.getEventDeclarations(0L));
+            assertEquals(2, eventDeclarations.size());
+            assertEquals("bozo_the_clown", eventDeclarations.get(1).getName());
         }
     }
 
index a3703b302d85bf5f8c96166cd2b5ecb657980e2b..ddb000ded041ef9ebb9cc208cc89eff044a10194 100644 (file)
@@ -217,8 +217,7 @@ public class EventDeclarationTest {
      */
     @Test
     public void testGetId() {
-        Long result = fixture.getId();
-        assertNotNull(result);
+        assertEquals(1,fixture.id());
     }
 
     /**
index 15545c5e2811ff1b170b9be2a451e2ad7d9a1158..57f24453616fb937b7322a1a6ae9b777805dbe32 100644 (file)
 
 package org.eclipse.linuxtools.ctf.core.trace;
 
-import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.linuxtools.ctf.core.event.IEventDeclaration;
 import org.eclipse.linuxtools.ctf.core.event.types.IDeclaration;
 import org.eclipse.linuxtools.ctf.core.event.types.IEventHeaderDeclaration;
@@ -57,7 +62,9 @@ public class CTFStream {
     /**
      * Maps event ids to events
      */
-    private Map<Long, IEventDeclaration> fEvents = new HashMap<>();
+    private final ArrayList<IEventDeclaration> fEvents = new ArrayList<>();
+
+    private boolean fEventUnsetId = false;
 
     /**
      * The inputs associated to this stream
@@ -229,9 +236,48 @@ public class CTFStream {
      *
      * @return all the event declarations for this stream, using the id as a key
      *         for the hashmap.
+     * @deprecated use {@link CTFStream#getEventDeclarations()}
      */
+    @Deprecated
     public Map<Long, IEventDeclaration> getEvents() {
-        return fEvents;
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Get all the event declarations in this stream.
+     *
+     * @return The event declarations for this stream
+     * @since 3.1
+     */
+    public @NonNull Collection<IEventDeclaration> getEventDeclarations() {
+        List<IEventDeclaration> retVal = new ArrayList<>(fEvents);
+        retVal.removeAll(Collections.<IEventDeclaration> singletonList(null));
+        return retVal;
+    }
+
+    /**
+     * Get the event declaration for a given ID.
+     *
+     * @param eventId
+     *            The ID, can be {@link EventDeclaration#UNSET_EVENT_ID}, or any
+     *            positive value
+     * @return The event declaration with the given ID for this stream, or
+     *         'null' if there are no declaration with this ID
+     * @throws IllegalArgumentException
+     *             If the passed ID is invalid
+     * @since 3.1
+     */
+    public @Nullable IEventDeclaration getEventDeclaration(int eventId) {
+        int eventIndex = (eventId == EventDeclaration.UNSET_EVENT_ID) ? 0 : eventId;
+        if (eventIndex < 0) {
+            /* Any negative value other than UNSET_EVENT_ID is invalid */
+            throw new IllegalArgumentException("Event ID cannot be negative."); //$NON-NLS-1$
+        }
+        if (eventIndex >= fEvents.size()) {
+            /* This ID could be valid, but there are no declarations with it */
+            return null;
+        }
+        return fEvents.get(eventIndex);
     }
 
     // ------------------------------------------------------------------------
@@ -239,7 +285,7 @@ public class CTFStream {
     // ------------------------------------------------------------------------
 
     /**
-     * Adds an event to the event map.
+     * Adds an event to the event list.
      *
      * An event in a stream can omit its id if it is the only event in this
      * stream. An event for which no id has been specified has a null id. It is
@@ -254,31 +300,67 @@ public class CTFStream {
      *             stream
      */
     public void addEvent(IEventDeclaration event) throws ParseException {
-        /*
-         * If there is an event without id (the null key), it must be the only
-         * one
-         */
-        if (fEvents.get(null) != null) {
+        if (fEventUnsetId) {
             throw new ParseException("Event without id with multiple events in a stream"); //$NON-NLS-1$
         }
+        int id = ((EventDeclaration) event).id();
 
         /*
          * If there is an event without id (the null key), it must be the only
          * one
          */
-        if ((event.getId() == null) && (fEvents.size() != 0)) {
-            throw new ParseException("Event without id with multiple events in a stream"); //$NON-NLS-1$
+        if (id == EventDeclaration.UNSET_EVENT_ID) {
+            if (!fEvents.isEmpty()) {
+                throw new ParseException("Event without id with multiple events in a stream"); //$NON-NLS-1$
+            }
+            fEventUnsetId = true;
+            fEvents.add(event);
+        } else {
+            /* Check if an event with the same ID already exists */
+            if (fEvents.size() > id && fEvents.get(id) != null) {
+                throw new ParseException("Event id already exists"); //$NON-NLS-1$
+            }
+            ensureSize(fEvents, id);
+            /* Put the event in the list */
+            fEvents.set(id, event);
         }
+    }
 
-        /* Check if an event with the same ID already exists */
-        if (fEvents.get(event.getId()) != null) {
-            throw new ParseException("Event id already exists"); //$NON-NLS-1$
+    /**
+     * Add a list of event declarations to this stream. There must be no overlap
+     * between the two lists of event declarations. This will merge the two
+     * lists and preserve the indexes of both lists.
+     *
+     * @param events
+     *            list of the events to add
+     * @throws CTFReaderException
+     *             if the list already contains data
+     * @since 3.1
+     */
+    public void addEvents(Collection<IEventDeclaration> events) throws CTFReaderException {
+        if (fEventUnsetId) {
+            throw new CTFReaderException("Cannot add to a stream with an unidentified event"); //$NON-NLS-1$
         }
-        if (event.getId() == null) {
-            fEvents.put(EventDeclaration.UNSET_EVENT_ID, event);
-        } else {
-            /* Put the event in the map */
-            fEvents.put(event.getId(), event);
+        if (fEvents.isEmpty()) {
+            fEvents.addAll(events);
+            return;
+        }
+        for (IEventDeclaration event : events) {
+            if (event != null) {
+                int index = event.getId().intValue();
+                ensureSize(fEvents, index);
+                if (fEvents.get(index) != null) {
+                    throw new CTFReaderException("Both lists have an event defined at position " + index); //$NON-NLS-1$
+                }
+                fEvents.set(index, event);
+            }
+        }
+    }
+
+    private static void ensureSize(ArrayList<? extends Object> list, int index) {
+        list.ensureCapacity(index);
+        while (list.size() <= index) {
+            list.add(null);
         }
     }
 
index 07fa8d804dbadd4fb65eb29764487d99d96aa38e..3004025ffd58aafe66cef429a4e5545da521626f 100644 (file)
@@ -318,7 +318,8 @@ public class CTFStreamInputPacketReader implements IDefinitionScope, AutoCloseab
      */
     public EventDefinition readNextEvent() throws CTFReaderException {
         /* Default values for those fields */
-        long eventID = EventDeclaration.UNSET_EVENT_ID;
+        // compromise since we cannot have 64 bit addressing of arrays yet.
+        int eventID = (int) EventDeclaration.UNSET_EVENT_ID;
         long timestamp = 0;
         if (fHasLost) {
             fHasLost = false;
@@ -409,7 +410,7 @@ public class CTFStreamInputPacketReader implements IDefinitionScope, AutoCloseab
                     timestampDef = variantCurrentField.lookupInteger("timestamp"); //$NON-NLS-1$
                 }
                 if (simpleIdDef != null) {
-                    eventID = simpleIdDef.getIntegerValue();
+                    eventID = simpleIdDef.getIntegerValue().intValue();
                 }
                 if (timestampDef != null) {
                     timestamp = calculateTimestamp(timestampDef);
@@ -417,7 +418,7 @@ public class CTFStreamInputPacketReader implements IDefinitionScope, AutoCloseab
             }
         }
         /* Get the right event definition using the event id. */
-        IEventDeclaration eventDeclaration = fStreamInputReader.getStreamInput().getStream().getEvents().get(eventID);
+        IEventDeclaration eventDeclaration = fStreamInputReader.getStreamInput().getStream().getEventDeclaration(eventID);
         if (eventDeclaration == null) {
             throw new CTFReaderException("Incorrect event id : " + eventID); //$NON-NLS-1$
         }
index 1a91b1bcb90b431c85617ad648199bec37bb8f44..ebbe1d78038c5bb9090db75c8c25cd87ae220cba 100644 (file)
@@ -20,7 +20,7 @@ import org.eclipse.linuxtools.ctf.core.event.IEventDeclaration;
 import org.eclipse.linuxtools.ctf.core.event.types.StructDeclaration;
 import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndexEntry;
 
-import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableList;
 
 /**
  * A CTF trace event reader. Reads the events of a trace file.
@@ -175,7 +175,7 @@ public class CTFStreamInputReader implements AutoCloseable {
      * @return Unmodifiable set with the event definitions
      */
     public Iterable<IEventDeclaration> getEventDeclarations() {
-        return ImmutableSet.copyOf(fStreamInput.getStream().getEvents().values());
+        return ImmutableList.copyOf(fStreamInput.getStream().getEventDeclarations());
     }
 
     /**
index 4bb35847b7eb804f33a9a698b2460dc1b7ed7f38..c21fd709e8dfbe791f4adbff074b983b41444d0c 100644 (file)
@@ -24,12 +24,11 @@ import java.nio.MappedByteBuffer;
 import java.nio.channels.FileChannel;
 import java.nio.channels.FileChannel.MapMode;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.UUID;
@@ -236,11 +235,25 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
      *            The ID of the stream from which to read
      * @return The Hash map with the event declarations
      * @since 2.0
+     * @deprecated use {@link CTFTrace#getEventDeclarations(Long)}
      */
+    @Deprecated
     public Map<Long, IEventDeclaration> getEvents(Long streamId) {
         return fStreams.get(streamId).getEvents();
     }
 
+    /**
+     * Gets an event declaration list for a given streamID
+     *
+     * @param streamId
+     *            The ID of the stream from which to read
+     * @return The list of event declarations
+     * @since 3.1
+     */
+    public Collection<IEventDeclaration> getEventDeclarations(Long streamId) {
+        return fStreams.get(streamId).getEventDeclarations();
+    }
+
     /**
      * Get an event by it's ID
      *
@@ -250,8 +263,25 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
      *            the ID of the event
      * @return the event declaration
      * @since 2.0
+     * @deprecated use {@link CTFTrace#getEventType(long, int)} instead
      */
+    @Deprecated
     public IEventDeclaration getEventType(long streamId, long id) {
+        return getStream(streamId).getEventDeclaration((int) id);
+    }
+
+
+    /**
+     * Get an event by it's ID
+     *
+     * @param streamId
+     *            The ID of the stream from which to read
+     * @param id
+     *            the ID of the event
+     * @return the event declaration
+     * @since 3.1
+     */
+    public IEventDeclaration getEventType(long streamId, int id) {
         return getEvents(streamId).get(id);
     }
 
@@ -455,16 +485,10 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
     private void addStream(CTFStreamInput s) {
 
         /*
-         * Copy the events
+         * add the stream
          */
-        Iterator<Entry<Long, IEventDeclaration>> it = s.getStream()
-                .getEvents().entrySet().iterator();
-        while (it.hasNext()) {
-            Entry<Long, IEventDeclaration> pairs = it.next();
-            Long eventNum = pairs.getKey();
-            IEventDeclaration eventDec = pairs.getValue();
-            getEvents(s.getStream().getId()).put(eventNum, eventDec);
-        }
+        CTFStream stream = s.getStream();
+        fStreams.put(stream.getId(), stream);
 
         /*
          * index the trace
index 5e40f57458d8d55798806fe58d5d12de4732d8dd..7aa0976e7d05e8fd50381f18bf06a20693761c69 100644 (file)
@@ -61,11 +61,6 @@ public class EventDeclaration implements IEventDeclaration {
      */
     private StructDeclaration fFields = null;
 
-    /**
-     * Event id (can be null if only event in the stream).
-     */
-    private Long fId = UNSET_EVENT_ID;
-
     /**
      * Stream to which belongs this event.
      */
@@ -79,6 +74,8 @@ public class EventDeclaration implements IEventDeclaration {
     /** Map of this event type's custom CTF attributes */
     private final Map<String, String> fCustomAttributes = new HashMap<>();
 
+    private int fId = (int) UNSET_EVENT_ID;
+
     // ------------------------------------------------------------------------
     // Constructors
     // ------------------------------------------------------------------------
@@ -122,7 +119,7 @@ public class EventDeclaration implements IEventDeclaration {
         String[] fieldNames = new String[] { CTFStrings.LOST_EVENTS_FIELD, CTFStrings.LOST_EVENTS_DURATION };
         Declaration[] fieldDeclarations = new Declaration[] { IntegerDeclaration.UINT_32B_DECL, IntegerDeclaration.UINT_64B_DECL };
         lostEvent.fFields = new StructDeclaration(fieldNames, fieldDeclarations);
-        lostEvent.fId = LOST_EVENT_ID;
+        lostEvent.fId = (int) LOST_EVENT_ID;
         lostEvent.fName = CTFStrings.LOST_EVENT_NAME;
         return lostEvent;
     }
@@ -183,11 +180,23 @@ public class EventDeclaration implements IEventDeclaration {
      *            the id
      */
     public void setId(long id) {
-        fId = id;
+        if (id < 0 || id > Integer.MAX_VALUE) {
+            throw new IllegalArgumentException("id out of range"); //$NON-NLS-1$
+        }
+        fId = (int) id;
     }
 
     @Override
     public Long getId() {
+        return Long.valueOf(fId);
+    }
+
+    /**
+     * Faster get id assuming you have less than a billion event types
+     *
+     * @return the event id
+     */
+    public int id() {
         return fId;
     }
 
@@ -240,7 +249,7 @@ public class EventDeclaration implements IEventDeclaration {
      * @return is the id set?
      */
     public boolean idIsSet() {
-        return (fId != null && fId != UNSET_EVENT_ID);
+        return (fId  != UNSET_EVENT_ID);
     }
 
     /**
@@ -320,11 +329,7 @@ public class EventDeclaration implements IEventDeclaration {
         } else if (!fFields.equals(other.fFields)) {
             return false;
         }
-        if (fId == null) {
-            if (other.fId != null) {
-                return false;
-            }
-        } else if (!fId.equals(other.fId)) {
+        if (fId != (other.fId)) {
             return false;
         }
         if (fName == null) {
@@ -354,7 +359,7 @@ public class EventDeclaration implements IEventDeclaration {
         result = (prime * result)
                 + ((fContext == null) ? 0 : fContext.hashCode());
         result = (prime * result) + ((fFields == null) ? 0 : fFields.hashCode());
-        result = (prime * result) + ((fId == null) ? 0 : fId.hashCode());
+        result = (prime * result) + fId;
         result = (prime * result) + ((fName == null) ? 0 : fName.hashCode());
         result = (prime * result) + ((fStream == null) ? 0 : fStream.hashCode());
         result = (prime * result) + fCustomAttributes.hashCode();
index 733bca86ab48ab629fbe2b30e8a2dc1459d201e3..7ab14408b5daab84575557908c4e9fafa24d473f 100644 (file)
@@ -85,7 +85,7 @@ public class CtfTmfEvent extends TmfEvent
 
         fEventDeclaration = declaration;
         fSourceCPU = cpu;
-        fTypeId = declaration.getId();
+        fTypeId = declaration.getId().longValue();
         fEventName = declaration.getName();
         fEvent = eventDefinition;
 
@@ -242,7 +242,7 @@ public class CtfTmfEvent extends TmfEvent
         if (structFields != null) {
             if (structFields.getFieldNames() != null) {
                 for (String curFieldName : structFields.getFieldNames()) {
-                    fields.add(CtfTmfEventField.parseField((IDefinition)structFields.getDefinition(curFieldName), curFieldName));
+                    fields.add(CtfTmfEventField.parseField((IDefinition) structFields.getDefinition(curFieldName), curFieldName));
                 }
             }
         }
@@ -252,7 +252,7 @@ public class CtfTmfEvent extends TmfEvent
             for (String contextName : structContext.getFieldNames()) {
                 /* Prefix field name */
                 String curContextName = CtfConstants.CONTEXT_FIELD_PREFIX + contextName;
-                fields.add(CtfTmfEventField.parseField((IDefinition)structContext.getDefinition(contextName), curContextName));
+                fields.add(CtfTmfEventField.parseField((IDefinition) structContext.getDefinition(contextName), curContextName));
             }
         }
 
This page took 0.034418 seconds and 5 git commands to generate.