# Buggy code
def StoreTagging(self, tags):
    """Store tag information into the storage file.

    Each EventObject can be tagged either manually or automatically
    to make analysis simpler, by providing more context to certain
    events or to highlight events for later viewing.

    The object passed in needs to be a list (or otherwise an iterator)
    that contains EventTag objects (event.EventTag).

    Args:
      A list or an object providing an iterator that contains
      EventTag objects.

    Raises:
      IOError: if the stream cannot be opened.
    """
    if not self._pre_obj:
        self._pre_obj = event.PreprocessObject()

    if not hasattr(self._pre_obj, "collection_information"):
        self._pre_obj.collection_information = {}

    self._pre_obj.collection_information["Action"] = "Adding tags to storage."
    self._pre_obj.collection_information["time_of_run"] = timelib.Timestamp.GetNow()
    if not hasattr(self._pre_obj, "counter"):
        self._pre_obj.counter = collections.Counter()

    tag_number = 1
    for name in self._GetStreamNames():
        if not name.startswith("plaso_tagging."):
            continue

        _, _, number_string = name.partition(".")
        try:
            number = int(number_string, 10)
        except ValueError:
            continue

        if number >= tag_number:
            tag_number = number + 1
        if self._event_tag_index is None:
            self._BuildTagIndex()

    serialized_event_tags = []
    for tag in tags:
        self._pre_obj.counter["Total Tags"] += 1
        if hasattr(tag, "tags"):
            for tag_entry in tag.tags:
                self._pre_obj.counter[tag_entry] += 1

        if self._event_tag_index is not None:
            tag_index_value = self._event_tag_index.get(tag.string_key, None)
        else:
            tag_index_value = None

        # This particular event has already been tagged on a previous occasion,
        # we need to make sure we are appending to that particular tag.
        if tag_index_value is not None:
            stream_name = "plaso_tagging.{0:06d}".format(tag_index_value.store_number)

            if not self._HasStream(stream_name):
                raise IOError("No such stream: {0:s}".format(stream_name))

            data_stream = _SerializedDataStream(self._zipfile, stream_name)
            # TODO: replace 0 by the actual event tag entry index.
            # This is for code consistency rather then a functional purpose.
            data_stream.SeekEntryAtOffset(0, tag_index_value.offset)

            # TODO: if old_tag is cached make sure to update cache after write.
            old_tag = self._ReadEventTag(data_stream)
            if not old_tag:
                continue

            # TODO: move the append functionality into EventTag.
            # Maybe name the function extend or update?
            if hasattr(old_tag, "tags"):
                tag.tags.extend(old_tag.tags)

            if hasattr(old_tag, "comment"):
                if hasattr(tag, "comment"):
                    tag.comment += old_tag.comment
                else:
                    tag.comment = old_tag.comment

            if hasattr(old_tag, "color") and not hasattr(tag, "color"):
                tag.color = old_tag.color

        if self._serializers_profiler:
            self._serializers_profiler.StartTiming("event_tag")

        serialized_event_tag = self._event_tag_serializer.WriteSerialized(tag)

        if self._serializers_profiler:
            self._serializers_profiler.StopTiming("event_tag")

        serialized_event_tags.append(serialized_event_tag)

    if self._serializers_profiler:
        self._serializers_profiler.StartTiming("write")

    stream_name = "plaso_tag_index.{0:06d}".format(tag_number)
    event_tag_index_table = _SerializedEventTagIndexTable(self._zipfile, stream_name)

    stream_name = "plaso_tagging.{0:06d}".format(tag_number)
    data_stream = _SerializedDataStream(self._zipfile, stream_name)
    entry_data_offset = data_stream.WriteInitialize()

    try:
        for tag_index, tag in enumerate(tags):
            entry_data_offset = data_stream.WriteEntry(serialized_event_tags[tag_index])

            event_uuid = getattr(tag, "event_uuid", None)
            store_number = getattr(tag, "store_number", None)
            store_offset = getattr(tag, "store_index", None)

            if event_uuid:
                tag_type = _EventTagIndexValue.TAG_TYPE_UUID
            else:
                tag_type = _EventTagIndexValue.TAG_TYPE_NUMERIC

            event_tag_index_table.AddEventTagIndex(
                tag_type,
                entry_data_offset,
                event_uuid=event_uuid,
                store_number=store_number,
                store_offset=store_offset,
            )

    except:
        data_stream.WriteAbort()

        if self._serializers_profiler:
            self._serializers_profiler.StopTiming("write")

        raise

    event_tag_index_table.Write()
    data_stream.WriteFinalize()

    if self._serializers_profiler:
        self._serializers_profiler.StopTiming("write")

    # TODO: Update the tags that have changed in the index instead
    # of flushing the index.

    # If we already built a list of tag in memory we need to clear that
    # since the tags have changed.
    if self._event_tag_index is not None:
        del self._event_tag_index


# Traceback (MemoryError)
2015-10-14 12:58:53,921 [WARNING] (StorageWriter) PID:2384 <multi_process> Unhandled exception in storage writer (PID: 2384).
2015-10-14 12:58:53,926 [ERROR] (StorageWriter) PID:2384 <multi_process>
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/plaso/multi_processing/multi_process.py", line 1184, in _Main
self._storage_writer.WriteEventObjects()
File "/usr/lib/python2.7/dist-packages/plaso/lib/storage.py", line 1645, in WriteEventObjects
self._Close()
File "/usr/lib/python2.7/dist-packages/plaso/lib/storage.py", line 1675, in _Close
self._storage_file.Close()
File "/usr/lib/python2.7/dist-packages/plaso/lib/storage.py", line 874, in Close
self._FlushBuffer()
File "/usr/lib/python2.7/dist-packages/plaso/lib/storage.py", line 431, in _FlushBuffer
self._WriteStream(stream_name, b''.join(proto_str))
MemoryError
2015-10-14 12:59:17,026 [WARNING] (MainProcess) PID:2379 <multi_process> Killing process: Worker_00 (PID: 2385).
2015-10-14 12:59:17,026 [WARNING] (MainProcess) PID:2379 <multi_process> Killing process: Worker_04 (PID: 2392).
Processing completed with errors.

# Fixed code
def StoreTagging(self, tags):
    """Store tag information into the storage file.

    Each EventObject can be tagged either manually or automatically
    to make analysis simpler, by providing more context to certain
    events or to highlight events for later viewing.

    The object passed in needs to be a list (or otherwise an iterator)
    that contains EventTag objects (event.EventTag).

    Args:
      A list or an object providing an iterator that contains
      EventTag objects.

    Raises:
      IOError: if the stream cannot be opened.
    """
    if not self._pre_obj:
        self._pre_obj = event.PreprocessObject()

    if not hasattr(self._pre_obj, "collection_information"):
        self._pre_obj.collection_information = {}

    self._pre_obj.collection_information["Action"] = "Adding tags to storage."
    self._pre_obj.collection_information["time_of_run"] = timelib.Timestamp.GetNow()
    if not hasattr(self._pre_obj, "counter"):
        self._pre_obj.counter = collections.Counter()

    tag_number = 1
    for name in self._GetStreamNames():
        if not name.startswith("plaso_tagging."):
            continue

        _, _, number_string = name.partition(".")
        try:
            number = int(number_string, 10)
        except ValueError:
            continue

        if number >= tag_number:
            tag_number = number + 1
        if self._event_tag_index is None:
            self._BuildTagIndex()

    serialized_event_tags = []
    for tag in tags:
        self._pre_obj.counter["Total Tags"] += 1
        if hasattr(tag, "tags"):
            for tag_entry in tag.tags:
                self._pre_obj.counter[tag_entry] += 1

        if self._event_tag_index is not None:
            tag_index_value = self._event_tag_index.get(tag.string_key, None)
        else:
            tag_index_value = None

        # This particular event has already been tagged on a previous occasion,
        # we need to make sure we are appending to that particular tag.
        if tag_index_value is not None:
            stream_name = "plaso_tagging.{0:06d}".format(tag_index_value.store_number)

            if not self._HasStream(stream_name):
                raise IOError("No such stream: {0:s}".format(stream_name))

            data_stream = _SerializedDataStream(self._zipfile, self._path, stream_name)
            # TODO: replace 0 by the actual event tag entry index.
            # This is for code consistency rather then a functional purpose.
            data_stream.SeekEntryAtOffset(0, tag_index_value.offset)

            # TODO: if old_tag is cached make sure to update cache after write.
            old_tag = self._ReadEventTag(data_stream)
            if not old_tag:
                continue

            # TODO: move the append functionality into EventTag.
            # Maybe name the function extend or update?
            if hasattr(old_tag, "tags"):
                tag.tags.extend(old_tag.tags)

            if hasattr(old_tag, "comment"):
                if hasattr(tag, "comment"):
                    tag.comment += old_tag.comment
                else:
                    tag.comment = old_tag.comment

            if hasattr(old_tag, "color") and not hasattr(tag, "color"):
                tag.color = old_tag.color

        if self._serializers_profiler:
            self._serializers_profiler.StartTiming("event_tag")

        serialized_event_tag = self._event_tag_serializer.WriteSerialized(tag)

        if self._serializers_profiler:
            self._serializers_profiler.StopTiming("event_tag")

        serialized_event_tags.append(serialized_event_tag)

    if self._serializers_profiler:
        self._serializers_profiler.StartTiming("write")

    stream_name = "plaso_tag_index.{0:06d}".format(tag_number)
    event_tag_index_table = _SerializedEventTagIndexTable(self._zipfile, stream_name)

    stream_name = "plaso_tagging.{0:06d}".format(tag_number)
    data_stream = _SerializedDataStream(self._zipfile, self._path, stream_name)
    entry_data_offset = data_stream.WriteInitialize()

    try:
        for tag_index, tag in enumerate(tags):
            entry_data_offset = data_stream.WriteEntry(serialized_event_tags[tag_index])

            event_uuid = getattr(tag, "event_uuid", None)
            store_number = getattr(tag, "store_number", None)
            store_offset = getattr(tag, "store_index", None)

            if event_uuid:
                tag_type = _EventTagIndexValue.TAG_TYPE_UUID
            else:
                tag_type = _EventTagIndexValue.TAG_TYPE_NUMERIC

            event_tag_index_table.AddEventTagIndex(
                tag_type,
                entry_data_offset,
                event_uuid=event_uuid,
                store_number=store_number,
                store_offset=store_offset,
            )

    except:
        data_stream.WriteAbort()

        if self._serializers_profiler:
            self._serializers_profiler.StopTiming("write")

        raise

    event_tag_index_table.Write()
    data_stream.WriteFinalize()

    if self._serializers_profiler:
        self._serializers_profiler.StopTiming("write")

    # TODO: Update the tags that have changed in the index instead
    # of flushing the index.

    # If we already built a list of tag in memory we need to clear that
    # since the tags have changed.
    if self._event_tag_index is not None:
        del self._event_tag_index