]> git.ipfire.org Git - thirdparty/vectorscan.git/commitdiff
Rose: pack global state bits into one u8
authorJustin Viiret <justin.viiret@intel.com>
Mon, 1 Feb 2016 22:42:00 +0000 (09:42 +1100)
committerMatthew Barr <matthew.barr@intel.com>
Tue, 1 Mar 2016 00:32:01 +0000 (11:32 +1100)
Eliminate the RoseRuntimeState structure in favour of a single status
byte that is stored in scratch and copied to/from stream state.

14 files changed:
src/report.h
src/rose/block.c
src/rose/eod.c
src/rose/init.c
src/rose/match.h
src/rose/program_runtime.h
src/rose/rose_build_bytecode.cpp
src/rose/rose_dump.cpp
src/rose/rose_internal.h
src/rose/runtime.h
src/rose/stream.c
src/runtime.c
src/scratch.h
src/som/som_runtime.c

index 2fff3b9a409216eff78baece5b4df1b2d160d861..b5d9af036d68262542deb618b63345d368c9dd87 100644 (file)
@@ -290,7 +290,7 @@ int roseAdaptor_i(u64a offset, ReportID id, struct hs_scratch *scratch,
 exit:
     if (halt) {
         DEBUG_PRINTF("callback requested to terminate matches\n");
-        ci->broken = BROKEN_FROM_USER;
+        ci->status |= STATUS_TERMINATED;
         return MO_HALT_MATCHING;
     }
 
@@ -354,7 +354,7 @@ int roseDeliverReport(u64a offset, ReportID id, struct hs_scratch *scratch,
                                 to_offset, flags, ci->userContext);
     if (halt) {
         DEBUG_PRINTF("callback requested to terminate matches\n");
-        ci->broken = BROKEN_FROM_USER;
+        ci->status |= STATUS_TERMINATED;
         return MO_HALT_MATCHING;
     }
 
@@ -455,7 +455,7 @@ int roseSomAdaptor_i(u64a from_offset, u64a to_offset, ReportID id,
 exit:
     if (halt) {
         DEBUG_PRINTF("callback requested to terminate matches\n");
-        ci->broken = BROKEN_FROM_USER;
+        ci->status |= STATUS_TERMINATED;
         return MO_HALT_MATCHING;
     }
 
@@ -515,7 +515,7 @@ int roseDeliverSomReport(u64a from_offset, u64a to_offset, ReportID id,
 
     if (halt) {
         DEBUG_PRINTF("callback requested to terminate matches\n");
-        ci->broken = BROKEN_FROM_USER;
+        ci->status |= STATUS_TERMINATED;
         return MO_HALT_MATCHING;
     }
 
index 3d4a008db18de32aef80d7c471486845be14737b..98dee627c806f3f2d61891522c33fd6d4ecb8eac 100644 (file)
@@ -258,9 +258,7 @@ void roseBlockExec_i(const struct RoseEngine *t, struct hs_scratch *scratch,
     }
 
 exit:;
-    u8 dummy_delay_mask = 0;
-    if (cleanUpDelayed(length, 0, tctxt, &dummy_delay_mask)
-        == HWLM_TERMINATE_MATCHING) {
+    if (cleanUpDelayed(length, 0, scratch) == HWLM_TERMINATE_MATCHING) {
         return;
     }
 
index ade45727b14ec642a608364305a246e8e9111730..91e59521fb05b3f55f305d4f2030ece74ee00fa7 100644 (file)
@@ -98,8 +98,7 @@ hwlmcb_rv_t roseEodRunMatcher(const struct RoseEngine *t, u64a offset,
     hwlmExec(etable, eod_data, eod_len, adj, roseCallback, tctxt, tctxt->groups);
 
     // We may need to fire delayed matches
-    u8 dummy_delay_mask = 0;
-    return cleanUpDelayed(0, offset, tctxt, &dummy_delay_mask);
+    return cleanUpDelayed(0, offset, scratch);
 }
 
 static rose_inline
index 1ec520c33bdfa60fa31b3a82393b498e61fab8a1..511eafe4dfdbae47675cdccc0ec22c7c92726167 100644 (file)
@@ -45,10 +45,7 @@ static really_inline
 void init_rstate(const struct RoseEngine *t, char *state) {
     // Set runtime state: we take our initial groups from the RoseEngine.
     DEBUG_PRINTF("setting initial groups to 0x%016llx\n", t->initialGroups);
-    struct RoseRuntimeState *rstate = getRuntimeState(state);
     storeGroups(t, state, t->initialGroups);
-    rstate->flags = 0;
-    rstate->broken = NOT_BROKEN;
 }
 
 static really_inline
index 2b6dfb5d17d164d0c26166ef8adac0b5f6647d8d..7d00e2acca57716f5cbc3f3ff99220f7bf0104dd 100644 (file)
@@ -237,12 +237,13 @@ hwlmcb_rv_t flushQueuedLiterals(struct RoseContext *tctxt, u64a end) {
 }
 
 static really_inline
-hwlmcb_rv_t cleanUpDelayed(size_t length, u64a offset, struct RoseContext *tctxt,
-                           u8 *status) {
-    if (can_stop_matching(tctxtToScratch(tctxt))) {
+hwlmcb_rv_t cleanUpDelayed(size_t length, u64a offset,
+                           struct hs_scratch *scratch) {
+    if (can_stop_matching(scratch)) {
         return HWLM_TERMINATE_MATCHING;
     }
 
+    struct RoseContext *tctxt = &scratch->tctxt;
     if (flushQueuedLiterals(tctxt, length + offset)
         == HWLM_TERMINATE_MATCHING) {
         return HWLM_TERMINATE_MATCHING;
@@ -250,9 +251,9 @@ hwlmcb_rv_t cleanUpDelayed(size_t length, u64a offset, struct RoseContext *tctxt
 
     if (tctxt->filledDelayedSlots) {
         DEBUG_PRINTF("dirty\n");
-        *status |= DELAY_FLOAT_DIRTY;
+        scratch->core_info.status |= STATUS_DELAY_DIRTY;
     } else {
-        *status &= ~DELAY_FLOAT_DIRTY;
+        scratch->core_info.status &= ~STATUS_DELAY_DIRTY;
     }
 
     tctxt->filledDelayedSlots = 0;
index 1e1356e146c9edc4d4624c4b488eaee47b7adb76..766b18a8f48a3e0d13d00af925daf2d0663f3efb 100644 (file)
@@ -211,9 +211,7 @@ hwlmcb_rv_t roseHaltIfExhausted(const struct RoseEngine *t,
                                 struct hs_scratch *scratch) {
     struct core_info *ci = &scratch->core_info;
     if (isAllExhausted(t, ci->exhaustionVector)) {
-        if (!ci->broken) {
-            ci->broken = BROKEN_EXHAUSTED;
-        }
+        ci->status |= STATUS_EXHAUSTED;
         scratch->tctxt.groups = 0;
         DEBUG_PRINTF("all exhausted, termination requested\n");
         return HWLM_TERMINATE_MATCHING;
index 275f61d0f278afcf8a9f56663f993d7b2c8272c5..c067b6a39e4c6790a8a3918c4f477d01888ebfe3 100644 (file)
@@ -561,9 +561,9 @@ void fillStateOffsets(const RoseBuildImpl &tbi, u32 rolesWithStateCount,
                       RoseStateOffsets *so) {
     u32 curr_offset = 0;
 
-    // First, runtime state (stores per-stream state, like whether we need a
+    // First, runtime status (stores per-stream state, like whether we need a
     // delay rebuild or have been told to halt matching.)
-    curr_offset += sizeof(RoseRuntimeState);
+    curr_offset += sizeof(u8);
 
     // Role state storage.
     curr_offset += mmbit_size(rolesWithStateCount);
@@ -4433,7 +4433,7 @@ aligned_unique_ptr<RoseEngine> RoseBuildImpl::buildFinalEngine(u32 minWidth) {
                      &stateOffsets);
 
     scatter_plan_raw state_scatter;
-    buildStateScatterPlan(sizeof(RoseRuntimeState), bc.numStates,
+    buildStateScatterPlan(sizeof(u8), bc.numStates,
                           activeLeftCount, rosePrefixCount, stateOffsets,
                           cc.streaming, activeArrayCount, outfixBeginQueue,
                           outfixEndQueue, &state_scatter);
index adf737264d896c87f7bb87293dc2908c91f4b1b9..e803b8c45851d923d0d542b5554100d601ab4ac4 100644 (file)
@@ -865,7 +865,6 @@ void roseDumpText(const RoseEngine *t, FILE *f) {
             t->historyRequired);
     fprintf(f, " - exhaustion vector : %u bytes\n", (t->ekeyCount + 7) / 8);
     fprintf(f, " - role state mmbit  : %u bytes\n", t->stateSize);
-    fprintf(f, " - runtime state     : %zu bytes\n", sizeof(RoseRuntimeState));
     fprintf(f, " - floating matcher  : %u bytes\n", t->floatingStreamState);
     fprintf(f, " - active array      : %u bytes\n",
             mmbit_size(t->activeArrayCount));
index 326887da8dec18f8b08df04ca5853e126c6250fe..0d6c96e9b07cd25092f01fb08969065021634dea 100644 (file)
@@ -48,8 +48,6 @@ typedef u64a rose_group;
 #define MAX_DELAY                   (DELAY_SLOT_COUNT - 1)
 #define DELAY_MASK                  (DELAY_SLOT_COUNT - 1)
 
-#define DELAY_FLOAT_DIRTY      (1U << 7) /* delay literal matched in history */
-
 // Direct report stuff
 #define LITERAL_DR_FLAG   (1U << 31)
 #define LITERAL_MDR_FLAG  ((1U << 30) | (1U << 31))
@@ -214,7 +212,7 @@ struct NfaInfo {
  *
  * State not covered by this structure includes:
  *
- * -# the RoseRuntimeState structure
+ * -# the first byte, containing the status bitmask
  * -# the role state multibit
  */
 struct RoseStateOffsets {
@@ -476,12 +474,6 @@ struct RoseEngine {
     struct scatter_full_plan state_init;
 };
 
-// Rose runtime state
-struct RoseRuntimeState {
-    u8 flags; /* high bit true if delay rebuild needed */
-    u8 broken; /* user has requested that we stop matching */
-};
-
 struct ALIGN_CL_DIRECTIVE anchored_matcher_info {
     u32 next_offset; /* relative to this, 0 for end */
     u32 state_offset; /* relative to anchorState */
index a8587538d644e6eacde77393e959650187d83ed4..414ad78fd4f0b267019feb304abad012bcdc7787 100644 (file)
 
 #define rose_inline really_inline
 
-/** \brief Fetch runtime state ptr. */
-static really_inline
-struct RoseRuntimeState *getRuntimeState(char *state) {
-    struct RoseRuntimeState *rs = (struct RoseRuntimeState *)(state);
-    assert(ISALIGNED_N(rs, 8));
-    return rs;
-}
-
 static really_inline
 const void *getByOffset(const struct RoseEngine *t, u32 offset) {
     assert(offset < t->size);
@@ -71,7 +63,7 @@ const void *getByOffset(const struct RoseEngine *t, u32 offset) {
 
 static really_inline
 void *getRoleState(char *state) {
-    return state + sizeof(struct RoseRuntimeState);
+    return state + sizeof(u8); // status flags
 }
 
 /** \brief Fetch the active array for suffix nfas. */
index 476c4f7ce1acf97e691b259c7e959dcc34c227c8..9b73948961ec3d37c8519c35bf8a490e87a68bc7 100644 (file)
@@ -393,7 +393,7 @@ void roseSaveNfaStreamState(const struct RoseEngine *t, char *state,
 static rose_inline
 void ensureStreamNeatAndTidy(const struct RoseEngine *t, char *state,
                              struct hs_scratch *scratch, size_t length,
-                             u64a offset, u8 delay_rb_status) {
+                             u64a offset) {
     struct RoseContext *tctxt = &scratch->tctxt;
 
     if (roseCatchUpTo(t, state, length + scratch->core_info.buf_offset, scratch,
@@ -406,8 +406,6 @@ void ensureStreamNeatAndTidy(const struct RoseEngine *t, char *state,
     roseFlushLastByteHistory(t, state, offset + length, tctxt);
     tctxt->lastEndOffset = offset + length;
     storeGroups(t, state, tctxt->groups);
-    struct RoseRuntimeState *rstate = getRuntimeState(state);
-    rstate->flags = delay_rb_status;
 }
 
 static really_inline
@@ -418,6 +416,8 @@ void do_rebuild(const struct RoseEngine *t, const struct HWLM *ftable,
     const u8 *buf = scratch->core_info.hbuf + scratch->core_info.hlen - len;
     DEBUG_PRINTF("BEGIN FLOATING REBUILD over %zu bytes\n", len);
 
+    scratch->core_info.status &= ~STATUS_DELAY_DIRTY;
+
     hwlmExec(ftable, buf, len, 0, roseDelayRebuildCallback, scratch,
              scratch->tctxt.groups);
     assert(!can_stop_matching(scratch));
@@ -446,7 +446,6 @@ void roseStreamExec(const struct RoseEngine *t, struct hs_scratch *scratch,
     }
 
     char *state = scratch->core_info.state;
-    struct RoseRuntimeState *rstate = getRuntimeState(state);
 
     struct RoseContext *tctxt = &scratch->tctxt;
     tctxt->mpv_inactive = 0;
@@ -475,8 +474,6 @@ void roseStreamExec(const struct RoseEngine *t, struct hs_scratch *scratch,
         streamInitSufPQ(t, state, scratch);
     }
 
-    u8 delay_rb_status = rstate->flags;
-
     u32 alen = t->anchoredDistance > offset ?
         MIN(length + offset, t->anchoredDistance) - offset : 0;
 
@@ -507,12 +504,13 @@ void roseStreamExec(const struct RoseEngine *t, struct hs_scratch *scratch,
 
         size_t hlength = scratch->core_info.hlen;
 
-        char rebuild = hlength && (delay_rb_status & DELAY_FLOAT_DIRTY)
-            && (t->maxFloatingDelayedMatch == ROSE_BOUND_INF
-                || offset < t->maxFloatingDelayedMatch);
+        char rebuild = hlength &&
+                       (scratch->core_info.status & STATUS_DELAY_DIRTY) &&
+                       (t->maxFloatingDelayedMatch == ROSE_BOUND_INF ||
+                        offset < t->maxFloatingDelayedMatch);
         DEBUG_PRINTF("**rebuild %hhd status %hhu mfdm %u, offset %llu\n",
-                     rebuild, delay_rb_status, t->maxFloatingDelayedMatch,
-                     offset);
+                     rebuild, scratch->core_info.status,
+                     t->maxFloatingDelayedMatch, offset);
 
         if (!flen) {
             if (rebuild) { /* rebuild floating delayed match stuff */
@@ -552,17 +550,16 @@ void roseStreamExec(const struct RoseEngine *t, struct hs_scratch *scratch,
 
 flush_delay_and_exit:
     DEBUG_PRINTF("flushing floating\n");
-    if (cleanUpDelayed(length, offset, tctxt, &delay_rb_status)
-        == HWLM_TERMINATE_MATCHING) {
+    if (cleanUpDelayed(length, offset, scratch) == HWLM_TERMINATE_MATCHING) {
         return;
     }
 
 exit:
     DEBUG_PRINTF("CLEAN UP TIME\n");
     if (!can_stop_matching(scratch)) {
-        ensureStreamNeatAndTidy(t, state, scratch, length, offset,
-                                delay_rb_status);
+        ensureStreamNeatAndTidy(t, state, scratch, length, offset);
     }
-    DEBUG_PRINTF("DONE STREAMING SCAN, dirty = %hhu\n", delay_rb_status);
+    DEBUG_PRINTF("DONE STREAMING SCAN, status = %u\n",
+                 scratch->core_info.status);
     return;
 }
index e38434fdcbbbbe33fc199a09d5ba071879a91695..24ee90f08c36b8d318c1cfb4bbeff5eb7e71ac1c 100644 (file)
@@ -119,7 +119,8 @@ static really_inline
 void populateCoreInfo(struct hs_scratch *s, const struct RoseEngine *rose,
                       char *state, match_event_handler onEvent, void *userCtx,
                       const char *data, size_t length, const u8 *history,
-                      size_t hlen, u64a offset, UNUSED unsigned int flags) {
+                      size_t hlen, u64a offset, u8 status,
+                      UNUSED unsigned int flags) {
     assert(rose);
     s->core_info.userContext = userCtx;
     s->core_info.userCallback = onEvent ? onEvent : null_onEvent;
@@ -127,7 +128,7 @@ void populateCoreInfo(struct hs_scratch *s, const struct RoseEngine *rose,
     s->core_info.state = state; /* required for chained queues + evec */
 
     s->core_info.exhaustionVector = state + rose->stateOffsets.exhausted;
-    s->core_info.broken = NOT_BROKEN;
+    s->core_info.status = status;
     s->core_info.buf = (const u8 *)data;
     s->core_info.len = length;
     s->core_info.hbuf = history;
@@ -140,33 +141,22 @@ void populateCoreInfo(struct hs_scratch *s, const struct RoseEngine *rose,
     s->deduper.som_log_dirty = 1; /* som logs have not been cleared */
 }
 
-/** \brief Query whether this stream is broken.
- *
- * A broken stream is one on which scanning has stopped, either because the
- * user has told us to (via the return value from a match callback) or because
- * we have exhausted all reports.
- *
- * \return NOT_BROKEN, BROKEN_FROM_USER or BROKEN_EXHAUSTED.
- */
+#define STATUS_VALID_BITS                                                      \
+    (STATUS_TERMINATED | STATUS_EXHAUSTED | STATUS_DELAY_DIRTY)
+
+/** \brief Retrieve status bitmask from stream state. */
 static really_inline
-u8 getBroken(const char *state) {
-    const struct RoseRuntimeState *ts = (const void *)state;
-    assert(ts->broken == NOT_BROKEN || ts->broken == BROKEN_FROM_USER
-           || ts->broken == BROKEN_EXHAUSTED);
-    return ts->broken;
+u8 getStreamStatus(const char *state) {
+    u8 status = *(const u8 *)state;
+    assert((status & ~STATUS_VALID_BITS) == 0);
+    return status;
 }
 
-/** \brief Mark this stream with the given broken flag.
- *
- * Possible values: NOT_BROKEN, BROKEN_FROM_USER, BROKEN_EXHAUSTED.
- */
+/** \brief Store status bitmask to stream state. */
 static really_inline
-void setBroken(char *state, u8 broken) {
-    DEBUG_PRINTF("set broken=%d\n", broken);
-    assert(broken == NOT_BROKEN || broken == BROKEN_FROM_USER
-           || broken == BROKEN_EXHAUSTED);
-    struct RoseRuntimeState *ts = (void *)state;
-    ts->broken = broken;
+void setStreamStatus(char *state, u8 status) {
+    assert((status & ~STATUS_VALID_BITS) == 0);
+    *(u8 *)state = status;
 }
 
 static really_inline
@@ -585,7 +575,7 @@ hs_error_t hs_scan(const hs_database_t *db, const char *data, unsigned length,
 
     /* populate core info in scratch */
     populateCoreInfo(scratch, rose, scratch->bstate, onEvent, userCtx, data,
-                     length, NULL, 0, 0, flags);
+                     length, NULL, 0, 0, 0, flags);
 
     clearEvec(scratch->core_info.exhaustionVector, rose);
 
@@ -707,6 +697,7 @@ void init_stream(struct hs_stream *s, const struct RoseEngine *rose) {
 
     char *state = getMultiState(s);
 
+    setStreamStatus(state, 0);
     roseInitState(rose, state);
 
     clearEvec((char *)state + rose->stateOffsets.exhausted, rose);
@@ -754,11 +745,9 @@ hs_error_t hs_open_stream(const hs_database_t *db, UNUSED unsigned flags,
 static really_inline
 void rawEodExec(hs_stream_t *id, hs_scratch_t *scratch) {
     const struct RoseEngine *rose = id->rose;
-    u8 broken = scratch->core_info.broken;
 
-    if (broken) {
+    if (can_stop_matching(scratch)) {
         DEBUG_PRINTF("stream already broken\n");
-        assert(broken == BROKEN_FROM_USER || broken == BROKEN_EXHAUSTED);
         return;
     }
 
@@ -774,11 +763,9 @@ void rawEodExec(hs_stream_t *id, hs_scratch_t *scratch) {
 static never_inline
 void soleOutfixEodExec(hs_stream_t *id, hs_scratch_t *scratch) {
     const struct RoseEngine *t = id->rose;
-    u8 broken = scratch->core_info.broken;
 
-    if (broken) {
+    if (can_stop_matching(scratch)) {
         DEBUG_PRINTF("stream already broken\n");
-        assert(broken == BROKEN_FROM_USER || broken == BROKEN_EXHAUSTED);
         return;
     }
 
@@ -817,15 +804,16 @@ void report_eod_matches(hs_stream_t *id, hs_scratch_t *scratch,
 
     const struct RoseEngine *rose = id->rose;
     char *state = getMultiState(id);
+    u8 status = getStreamStatus(state);
 
-    if (getBroken(state)) {
+    if (status == STATUS_TERMINATED || status == STATUS_EXHAUSTED) {
         DEBUG_PRINTF("stream is broken, just freeing storage\n");
         return;
     }
 
     populateCoreInfo(scratch, rose, state, onEvent, context, NULL, 0,
                      getHistory(state, rose, id->offset),
-                     getHistoryAmount(rose, id->offset), id->offset, 0);
+                     getHistoryAmount(rose, id->offset), id->offset, status, 0);
 
     if (rose->somLocationCount) {
         loadSomFromStream(scratch, id->offset);
@@ -861,8 +849,7 @@ void report_eod_matches(hs_stream_t *id, hs_scratch_t *scratch,
         int halt = flushStoredSomMatches(scratch, ~0ULL);
         if (halt) {
             DEBUG_PRINTF("told to stop matching\n");
-            scratch->core_info.broken = BROKEN_FROM_USER;
-            DEBUG_PRINTF("broken = %hhd\n", scratch->core_info.broken);
+            scratch->core_info.status |= STATUS_TERMINATED;
         }
     }
 }
@@ -931,8 +918,7 @@ static really_inline
 void rawStreamExec(struct hs_stream *stream_state, struct hs_scratch *scratch) {
     assert(stream_state);
     assert(scratch);
-
-    assert(!getBroken(getMultiState(stream_state)));
+    assert(!can_stop_matching(scratch));
 
     DEBUG_PRINTF("::: streaming rose ::: offset = %llu len = %zu\n",
                  stream_state->offset, scratch->core_info.len);
@@ -944,7 +930,7 @@ void rawStreamExec(struct hs_stream *stream_state, struct hs_scratch *scratch) {
     if (!told_to_stop_matching(scratch) &&
         isAllExhausted(rose, scratch->core_info.exhaustionVector)) {
         DEBUG_PRINTF("stream exhausted\n");
-        scratch->core_info.broken = BROKEN_EXHAUSTED;
+        scratch->core_info.status = STATUS_EXHAUSTED;
     }
 }
 
@@ -953,9 +939,9 @@ void pureLiteralStreamExec(struct hs_stream *stream_state,
                            struct hs_scratch *scratch) {
     assert(stream_state);
     assert(scratch);
+    assert(!can_stop_matching(scratch));
 
     char *state = getMultiState(stream_state);
-    assert(!getBroken(state));
 
     const struct RoseEngine *rose = stream_state->rose;
     const struct HWLM *ftable = getFLiteralMatcher(rose);
@@ -982,7 +968,7 @@ void pureLiteralStreamExec(struct hs_stream *stream_state,
     if (!told_to_stop_matching(scratch) &&
         isAllExhausted(rose, scratch->core_info.exhaustionVector)) {
         DEBUG_PRINTF("stream exhausted\n");
-        scratch->core_info.broken = BROKEN_EXHAUSTED;
+        scratch->core_info.status |= STATUS_EXHAUSTED;
     }
 }
 
@@ -991,6 +977,7 @@ void soleOutfixStreamExec(struct hs_stream *stream_state,
                           struct hs_scratch *scratch) {
     assert(stream_state);
     assert(scratch);
+    assert(!can_stop_matching(scratch));
 
     const struct RoseEngine *t = stream_state->rose;
     assert(t->outfixEndQueue == 1);
@@ -1017,7 +1004,7 @@ void soleOutfixStreamExec(struct hs_stream *stream_state,
     if (nfaQueueExec(q->nfa, q, scratch->core_info.len)) {
         nfaQueueCompressState(nfa, q, scratch->core_info.len);
     } else if (!told_to_stop_matching(scratch)) {
-        scratch->core_info.broken = BROKEN_EXHAUSTED;
+        scratch->core_info.status |= STATUS_EXHAUSTED;
     }
 }
 
@@ -1033,13 +1020,12 @@ hs_error_t hs_scan_stream_internal(hs_stream_t *id, const char *data,
     const struct RoseEngine *rose = id->rose;
     char *state = getMultiState(id);
 
-    u8 broken = getBroken(state);
-    if (broken) {
+    u8 status = getStreamStatus(state);
+    if (status & (STATUS_TERMINATED | STATUS_EXHAUSTED)) {
         DEBUG_PRINTF("stream is broken, halting scan\n");
-        if (broken == BROKEN_FROM_USER) {
+        if (status & STATUS_TERMINATED) {
             return HS_SCAN_TERMINATED;
         } else {
-            assert(broken == BROKEN_EXHAUSTED);
             return HS_SUCCESS;
         }
     }
@@ -1049,14 +1035,13 @@ hs_error_t hs_scan_stream_internal(hs_stream_t *id, const char *data,
     // cases here.
     if (unlikely(length == 0)) {
         DEBUG_PRINTF("zero length block\n");
-        assert(getBroken(state) != BROKEN_FROM_USER);
         return HS_SUCCESS;
     }
 
     u32 historyAmount = getHistoryAmount(rose, id->offset);
     populateCoreInfo(scratch, rose, state, onEvent, context, data, length,
                      getHistory(state, rose, id->offset), historyAmount,
-                     id->offset, flags);
+                     id->offset, status, flags);
     assert(scratch->core_info.hlen <= id->offset
            && scratch->core_info.hlen <= rose->historyRequired);
 
@@ -1069,14 +1054,13 @@ hs_error_t hs_scan_stream_internal(hs_stream_t *id, const char *data,
     if (!id->offset && rose->boundary.reportZeroOffset) {
         DEBUG_PRINTF("zero reports\n");
         processReportList(rose, rose->boundary.reportZeroOffset, 0, scratch);
-        broken = scratch->core_info.broken;
-        if (unlikely(broken)) {
+        if (unlikely(can_stop_matching(scratch))) {
             DEBUG_PRINTF("stream is broken, halting scan\n");
-            setBroken(state, broken);
-            if (broken == BROKEN_FROM_USER) {
+            setStreamStatus(state, scratch->core_info.status);
+            if (told_to_stop_matching(scratch)) {
                 return HS_SCAN_TERMINATED;
             } else {
-                assert(broken == BROKEN_EXHAUSTED);
+                assert(scratch->core_info.status & STATUS_EXHAUSTED);
                 return HS_SUCCESS;
             }
         }
@@ -1098,22 +1082,21 @@ hs_error_t hs_scan_stream_internal(hs_stream_t *id, const char *data,
     if (rose->hasSom && !told_to_stop_matching(scratch)) {
         int halt = flushStoredSomMatches(scratch, ~0ULL);
         if (halt) {
-            scratch->core_info.broken = BROKEN_FROM_USER;
+            scratch->core_info.status |= STATUS_TERMINATED;
         }
     }
 
+    setStreamStatus(state, scratch->core_info.status);
+
     if (likely(!can_stop_matching(scratch))) {
-        maintainHistoryBuffer(id->rose, getMultiState(id), data, length);
+        maintainHistoryBuffer(rose, state, data, length);
         id->offset += length; /* maintain offset */
 
         if (rose->somLocationCount) {
             storeSomToStream(scratch, id->offset);
         }
     } else if (told_to_stop_matching(scratch)) {
-        setBroken(state, BROKEN_FROM_USER);
         return HS_SCAN_TERMINATED;
-    } else { /* exhausted */
-        setBroken(state, BROKEN_EXHAUSTED);
     }
 
     return HS_SUCCESS;
index 150db3f241341e1c0d92f7a925a684c648f8384a..e082d2f893ab6176adf4966e800002d010a6fcb3 100644 (file)
@@ -70,17 +70,16 @@ struct catchup_pq {
     u32 qm_size; /**< current size of the priority queue */
 };
 
+/** \brief Status flag: user requested termination. */
+#define STATUS_TERMINATED   (1U << 0)
 
-/** \brief Value indicating a stream is active (not broken). */
-#define NOT_BROKEN       0
+/** \brief Status flag: all possible matches on this stream have
+ * been raised (i.e. all its exhaustion keys are on.) */
+#define STATUS_EXHAUSTED    (1U << 1)
 
-/** \brief Value indicating that the user has requested that matching be
- * terminated. */
-#define BROKEN_FROM_USER 1
-
-/** \brief Value indicating that all possible matches on this stream have been
- * raised (i.e. all its exhaustion keys are on.) */
-#define BROKEN_EXHAUSTED 2
+/** \brief Status flag: Rose requires rebuild as delay literal matched in
+ * history. */
+#define STATUS_DELAY_DIRTY  (1U << 2)
 
 /** \brief Core information about the current scan, used everywhere. */
 struct core_info {
@@ -93,12 +92,12 @@ struct core_info {
     const struct RoseEngine *rose;
     char *state; /**< full stream state */
     char *exhaustionVector; /**< pointer to evec for this stream */
-    char broken;  /**< user told us to stop, or exhausted */
     const u8 *buf; /**< main scan buffer */
     size_t len; /**< length of main scan buffer in bytes */
     const u8 *hbuf; /**< history buffer */
     size_t hlen; /**< length of history buffer in bytes. */
     u64a buf_offset; /**< stream offset, for the base of the buffer */
+    u8 status; /**< stream status bitmask, using STATUS_ flags above */
 };
 
 /** \brief Rose state information. */
@@ -213,12 +212,12 @@ struct fatbit **getDelaySlots(struct hs_scratch *scratch) {
 
 static really_inline
 char told_to_stop_matching(const struct hs_scratch *scratch) {
-    return scratch->core_info.broken == BROKEN_FROM_USER;
+    return scratch->core_info.status & STATUS_TERMINATED;
 }
 
 static really_inline
 char can_stop_matching(const struct hs_scratch *scratch) {
-    return scratch->core_info.broken != NOT_BROKEN;
+    return scratch->core_info.status & (STATUS_TERMINATED | STATUS_EXHAUSTED);
 }
 
 #ifdef __cplusplus
index 418fcbab096b37ac9762fdc9cb332b2f824abdf4..84eeb6013c994b577b175ffeede725762c0bead7 100644 (file)
@@ -487,7 +487,7 @@ int clearSomLog(struct hs_scratch *scratch, u64a offset, struct fatbit *log,
         int halt = ci->userCallback(onmatch, from_offset, offset, flags,
                                     ci->userContext);
         if (halt) {
-            ci->broken = BROKEN_FROM_USER;
+            ci->status |= STATUS_TERMINATED;
             return 1;
         }
     }