mirror of
https://github.com/VectorCamp/vectorscan.git
synced 2025-06-28 16:41:01 +03:00
Rose: pack global state bits into one u8
Eliminate the RoseRuntimeState structure in favour of a single status byte that is stored in scratch and copied to/from stream state.
This commit is contained in:
parent
28f379d738
commit
9e9bb6a960
@ -290,7 +290,7 @@ int roseAdaptor_i(u64a offset, ReportID id, struct hs_scratch *scratch,
|
|||||||
exit:
|
exit:
|
||||||
if (halt) {
|
if (halt) {
|
||||||
DEBUG_PRINTF("callback requested to terminate matches\n");
|
DEBUG_PRINTF("callback requested to terminate matches\n");
|
||||||
ci->broken = BROKEN_FROM_USER;
|
ci->status |= STATUS_TERMINATED;
|
||||||
return MO_HALT_MATCHING;
|
return MO_HALT_MATCHING;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,7 +354,7 @@ int roseDeliverReport(u64a offset, ReportID id, struct hs_scratch *scratch,
|
|||||||
to_offset, flags, ci->userContext);
|
to_offset, flags, ci->userContext);
|
||||||
if (halt) {
|
if (halt) {
|
||||||
DEBUG_PRINTF("callback requested to terminate matches\n");
|
DEBUG_PRINTF("callback requested to terminate matches\n");
|
||||||
ci->broken = BROKEN_FROM_USER;
|
ci->status |= STATUS_TERMINATED;
|
||||||
return MO_HALT_MATCHING;
|
return MO_HALT_MATCHING;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,7 +455,7 @@ int roseSomAdaptor_i(u64a from_offset, u64a to_offset, ReportID id,
|
|||||||
exit:
|
exit:
|
||||||
if (halt) {
|
if (halt) {
|
||||||
DEBUG_PRINTF("callback requested to terminate matches\n");
|
DEBUG_PRINTF("callback requested to terminate matches\n");
|
||||||
ci->broken = BROKEN_FROM_USER;
|
ci->status |= STATUS_TERMINATED;
|
||||||
return MO_HALT_MATCHING;
|
return MO_HALT_MATCHING;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,7 +515,7 @@ int roseDeliverSomReport(u64a from_offset, u64a to_offset, ReportID id,
|
|||||||
|
|
||||||
if (halt) {
|
if (halt) {
|
||||||
DEBUG_PRINTF("callback requested to terminate matches\n");
|
DEBUG_PRINTF("callback requested to terminate matches\n");
|
||||||
ci->broken = BROKEN_FROM_USER;
|
ci->status |= STATUS_TERMINATED;
|
||||||
return MO_HALT_MATCHING;
|
return MO_HALT_MATCHING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,9 +258,7 @@ void roseBlockExec_i(const struct RoseEngine *t, struct hs_scratch *scratch,
|
|||||||
}
|
}
|
||||||
|
|
||||||
exit:;
|
exit:;
|
||||||
u8 dummy_delay_mask = 0;
|
if (cleanUpDelayed(length, 0, scratch) == HWLM_TERMINATE_MATCHING) {
|
||||||
if (cleanUpDelayed(length, 0, tctxt, &dummy_delay_mask)
|
|
||||||
== HWLM_TERMINATE_MATCHING) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
hwlmExec(etable, eod_data, eod_len, adj, roseCallback, tctxt, tctxt->groups);
|
||||||
|
|
||||||
// We may need to fire delayed matches
|
// We may need to fire delayed matches
|
||||||
u8 dummy_delay_mask = 0;
|
return cleanUpDelayed(0, offset, scratch);
|
||||||
return cleanUpDelayed(0, offset, tctxt, &dummy_delay_mask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static rose_inline
|
static rose_inline
|
||||||
|
@ -45,10 +45,7 @@ static really_inline
|
|||||||
void init_rstate(const struct RoseEngine *t, char *state) {
|
void init_rstate(const struct RoseEngine *t, char *state) {
|
||||||
// Set runtime state: we take our initial groups from the RoseEngine.
|
// Set runtime state: we take our initial groups from the RoseEngine.
|
||||||
DEBUG_PRINTF("setting initial groups to 0x%016llx\n", t->initialGroups);
|
DEBUG_PRINTF("setting initial groups to 0x%016llx\n", t->initialGroups);
|
||||||
struct RoseRuntimeState *rstate = getRuntimeState(state);
|
|
||||||
storeGroups(t, state, t->initialGroups);
|
storeGroups(t, state, t->initialGroups);
|
||||||
rstate->flags = 0;
|
|
||||||
rstate->broken = NOT_BROKEN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static really_inline
|
static really_inline
|
||||||
|
@ -237,12 +237,13 @@ hwlmcb_rv_t flushQueuedLiterals(struct RoseContext *tctxt, u64a end) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static really_inline
|
static really_inline
|
||||||
hwlmcb_rv_t cleanUpDelayed(size_t length, u64a offset, struct RoseContext *tctxt,
|
hwlmcb_rv_t cleanUpDelayed(size_t length, u64a offset,
|
||||||
u8 *status) {
|
struct hs_scratch *scratch) {
|
||||||
if (can_stop_matching(tctxtToScratch(tctxt))) {
|
if (can_stop_matching(scratch)) {
|
||||||
return HWLM_TERMINATE_MATCHING;
|
return HWLM_TERMINATE_MATCHING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct RoseContext *tctxt = &scratch->tctxt;
|
||||||
if (flushQueuedLiterals(tctxt, length + offset)
|
if (flushQueuedLiterals(tctxt, length + offset)
|
||||||
== HWLM_TERMINATE_MATCHING) {
|
== HWLM_TERMINATE_MATCHING) {
|
||||||
return 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) {
|
if (tctxt->filledDelayedSlots) {
|
||||||
DEBUG_PRINTF("dirty\n");
|
DEBUG_PRINTF("dirty\n");
|
||||||
*status |= DELAY_FLOAT_DIRTY;
|
scratch->core_info.status |= STATUS_DELAY_DIRTY;
|
||||||
} else {
|
} else {
|
||||||
*status &= ~DELAY_FLOAT_DIRTY;
|
scratch->core_info.status &= ~STATUS_DELAY_DIRTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
tctxt->filledDelayedSlots = 0;
|
tctxt->filledDelayedSlots = 0;
|
||||||
|
@ -211,9 +211,7 @@ hwlmcb_rv_t roseHaltIfExhausted(const struct RoseEngine *t,
|
|||||||
struct hs_scratch *scratch) {
|
struct hs_scratch *scratch) {
|
||||||
struct core_info *ci = &scratch->core_info;
|
struct core_info *ci = &scratch->core_info;
|
||||||
if (isAllExhausted(t, ci->exhaustionVector)) {
|
if (isAllExhausted(t, ci->exhaustionVector)) {
|
||||||
if (!ci->broken) {
|
ci->status |= STATUS_EXHAUSTED;
|
||||||
ci->broken = BROKEN_EXHAUSTED;
|
|
||||||
}
|
|
||||||
scratch->tctxt.groups = 0;
|
scratch->tctxt.groups = 0;
|
||||||
DEBUG_PRINTF("all exhausted, termination requested\n");
|
DEBUG_PRINTF("all exhausted, termination requested\n");
|
||||||
return HWLM_TERMINATE_MATCHING;
|
return HWLM_TERMINATE_MATCHING;
|
||||||
|
@ -561,9 +561,9 @@ void fillStateOffsets(const RoseBuildImpl &tbi, u32 rolesWithStateCount,
|
|||||||
RoseStateOffsets *so) {
|
RoseStateOffsets *so) {
|
||||||
u32 curr_offset = 0;
|
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.)
|
// delay rebuild or have been told to halt matching.)
|
||||||
curr_offset += sizeof(RoseRuntimeState);
|
curr_offset += sizeof(u8);
|
||||||
|
|
||||||
// Role state storage.
|
// Role state storage.
|
||||||
curr_offset += mmbit_size(rolesWithStateCount);
|
curr_offset += mmbit_size(rolesWithStateCount);
|
||||||
@ -4433,7 +4433,7 @@ aligned_unique_ptr<RoseEngine> RoseBuildImpl::buildFinalEngine(u32 minWidth) {
|
|||||||
&stateOffsets);
|
&stateOffsets);
|
||||||
|
|
||||||
scatter_plan_raw state_scatter;
|
scatter_plan_raw state_scatter;
|
||||||
buildStateScatterPlan(sizeof(RoseRuntimeState), bc.numStates,
|
buildStateScatterPlan(sizeof(u8), bc.numStates,
|
||||||
activeLeftCount, rosePrefixCount, stateOffsets,
|
activeLeftCount, rosePrefixCount, stateOffsets,
|
||||||
cc.streaming, activeArrayCount, outfixBeginQueue,
|
cc.streaming, activeArrayCount, outfixBeginQueue,
|
||||||
outfixEndQueue, &state_scatter);
|
outfixEndQueue, &state_scatter);
|
||||||
|
@ -865,7 +865,6 @@ void roseDumpText(const RoseEngine *t, FILE *f) {
|
|||||||
t->historyRequired);
|
t->historyRequired);
|
||||||
fprintf(f, " - exhaustion vector : %u bytes\n", (t->ekeyCount + 7) / 8);
|
fprintf(f, " - exhaustion vector : %u bytes\n", (t->ekeyCount + 7) / 8);
|
||||||
fprintf(f, " - role state mmbit : %u bytes\n", t->stateSize);
|
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, " - floating matcher : %u bytes\n", t->floatingStreamState);
|
||||||
fprintf(f, " - active array : %u bytes\n",
|
fprintf(f, " - active array : %u bytes\n",
|
||||||
mmbit_size(t->activeArrayCount));
|
mmbit_size(t->activeArrayCount));
|
||||||
|
@ -48,8 +48,6 @@ typedef u64a rose_group;
|
|||||||
#define MAX_DELAY (DELAY_SLOT_COUNT - 1)
|
#define MAX_DELAY (DELAY_SLOT_COUNT - 1)
|
||||||
#define DELAY_MASK (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
|
// Direct report stuff
|
||||||
#define LITERAL_DR_FLAG (1U << 31)
|
#define LITERAL_DR_FLAG (1U << 31)
|
||||||
#define LITERAL_MDR_FLAG ((1U << 30) | (1U << 31))
|
#define LITERAL_MDR_FLAG ((1U << 30) | (1U << 31))
|
||||||
@ -214,7 +212,7 @@ struct NfaInfo {
|
|||||||
*
|
*
|
||||||
* State not covered by this structure includes:
|
* State not covered by this structure includes:
|
||||||
*
|
*
|
||||||
* -# the RoseRuntimeState structure
|
* -# the first byte, containing the status bitmask
|
||||||
* -# the role state multibit
|
* -# the role state multibit
|
||||||
*/
|
*/
|
||||||
struct RoseStateOffsets {
|
struct RoseStateOffsets {
|
||||||
@ -476,12 +474,6 @@ struct RoseEngine {
|
|||||||
struct scatter_full_plan state_init;
|
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 {
|
struct ALIGN_CL_DIRECTIVE anchored_matcher_info {
|
||||||
u32 next_offset; /* relative to this, 0 for end */
|
u32 next_offset; /* relative to this, 0 for end */
|
||||||
u32 state_offset; /* relative to anchorState */
|
u32 state_offset; /* relative to anchorState */
|
||||||
|
@ -55,14 +55,6 @@
|
|||||||
|
|
||||||
#define rose_inline really_inline
|
#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
|
static really_inline
|
||||||
const void *getByOffset(const struct RoseEngine *t, u32 offset) {
|
const void *getByOffset(const struct RoseEngine *t, u32 offset) {
|
||||||
assert(offset < t->size);
|
assert(offset < t->size);
|
||||||
@ -71,7 +63,7 @@ const void *getByOffset(const struct RoseEngine *t, u32 offset) {
|
|||||||
|
|
||||||
static really_inline
|
static really_inline
|
||||||
void *getRoleState(char *state) {
|
void *getRoleState(char *state) {
|
||||||
return state + sizeof(struct RoseRuntimeState);
|
return state + sizeof(u8); // status flags
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \brief Fetch the active array for suffix nfas. */
|
/** \brief Fetch the active array for suffix nfas. */
|
||||||
|
@ -393,7 +393,7 @@ void roseSaveNfaStreamState(const struct RoseEngine *t, char *state,
|
|||||||
static rose_inline
|
static rose_inline
|
||||||
void ensureStreamNeatAndTidy(const struct RoseEngine *t, char *state,
|
void ensureStreamNeatAndTidy(const struct RoseEngine *t, char *state,
|
||||||
struct hs_scratch *scratch, size_t length,
|
struct hs_scratch *scratch, size_t length,
|
||||||
u64a offset, u8 delay_rb_status) {
|
u64a offset) {
|
||||||
struct RoseContext *tctxt = &scratch->tctxt;
|
struct RoseContext *tctxt = &scratch->tctxt;
|
||||||
|
|
||||||
if (roseCatchUpTo(t, state, length + scratch->core_info.buf_offset, scratch,
|
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);
|
roseFlushLastByteHistory(t, state, offset + length, tctxt);
|
||||||
tctxt->lastEndOffset = offset + length;
|
tctxt->lastEndOffset = offset + length;
|
||||||
storeGroups(t, state, tctxt->groups);
|
storeGroups(t, state, tctxt->groups);
|
||||||
struct RoseRuntimeState *rstate = getRuntimeState(state);
|
|
||||||
rstate->flags = delay_rb_status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static really_inline
|
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;
|
const u8 *buf = scratch->core_info.hbuf + scratch->core_info.hlen - len;
|
||||||
DEBUG_PRINTF("BEGIN FLOATING REBUILD over %zu bytes\n", 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,
|
hwlmExec(ftable, buf, len, 0, roseDelayRebuildCallback, scratch,
|
||||||
scratch->tctxt.groups);
|
scratch->tctxt.groups);
|
||||||
assert(!can_stop_matching(scratch));
|
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;
|
char *state = scratch->core_info.state;
|
||||||
struct RoseRuntimeState *rstate = getRuntimeState(state);
|
|
||||||
|
|
||||||
struct RoseContext *tctxt = &scratch->tctxt;
|
struct RoseContext *tctxt = &scratch->tctxt;
|
||||||
tctxt->mpv_inactive = 0;
|
tctxt->mpv_inactive = 0;
|
||||||
@ -475,8 +474,6 @@ void roseStreamExec(const struct RoseEngine *t, struct hs_scratch *scratch,
|
|||||||
streamInitSufPQ(t, state, scratch);
|
streamInitSufPQ(t, state, scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 delay_rb_status = rstate->flags;
|
|
||||||
|
|
||||||
u32 alen = t->anchoredDistance > offset ?
|
u32 alen = t->anchoredDistance > offset ?
|
||||||
MIN(length + offset, t->anchoredDistance) - offset : 0;
|
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;
|
size_t hlength = scratch->core_info.hlen;
|
||||||
|
|
||||||
char rebuild = hlength && (delay_rb_status & DELAY_FLOAT_DIRTY)
|
char rebuild = hlength &&
|
||||||
&& (t->maxFloatingDelayedMatch == ROSE_BOUND_INF
|
(scratch->core_info.status & STATUS_DELAY_DIRTY) &&
|
||||||
|| offset < t->maxFloatingDelayedMatch);
|
(t->maxFloatingDelayedMatch == ROSE_BOUND_INF ||
|
||||||
|
offset < t->maxFloatingDelayedMatch);
|
||||||
DEBUG_PRINTF("**rebuild %hhd status %hhu mfdm %u, offset %llu\n",
|
DEBUG_PRINTF("**rebuild %hhd status %hhu mfdm %u, offset %llu\n",
|
||||||
rebuild, delay_rb_status, t->maxFloatingDelayedMatch,
|
rebuild, scratch->core_info.status,
|
||||||
offset);
|
t->maxFloatingDelayedMatch, offset);
|
||||||
|
|
||||||
if (!flen) {
|
if (!flen) {
|
||||||
if (rebuild) { /* rebuild floating delayed match stuff */
|
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:
|
flush_delay_and_exit:
|
||||||
DEBUG_PRINTF("flushing floating\n");
|
DEBUG_PRINTF("flushing floating\n");
|
||||||
if (cleanUpDelayed(length, offset, tctxt, &delay_rb_status)
|
if (cleanUpDelayed(length, offset, scratch) == HWLM_TERMINATE_MATCHING) {
|
||||||
== HWLM_TERMINATE_MATCHING) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
DEBUG_PRINTF("CLEAN UP TIME\n");
|
DEBUG_PRINTF("CLEAN UP TIME\n");
|
||||||
if (!can_stop_matching(scratch)) {
|
if (!can_stop_matching(scratch)) {
|
||||||
ensureStreamNeatAndTidy(t, state, scratch, length, offset,
|
ensureStreamNeatAndTidy(t, state, scratch, length, offset);
|
||||||
delay_rb_status);
|
|
||||||
}
|
}
|
||||||
DEBUG_PRINTF("DONE STREAMING SCAN, dirty = %hhu\n", delay_rb_status);
|
DEBUG_PRINTF("DONE STREAMING SCAN, status = %u\n",
|
||||||
|
scratch->core_info.status);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,8 @@ static really_inline
|
|||||||
void populateCoreInfo(struct hs_scratch *s, const struct RoseEngine *rose,
|
void populateCoreInfo(struct hs_scratch *s, const struct RoseEngine *rose,
|
||||||
char *state, match_event_handler onEvent, void *userCtx,
|
char *state, match_event_handler onEvent, void *userCtx,
|
||||||
const char *data, size_t length, const u8 *history,
|
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);
|
assert(rose);
|
||||||
s->core_info.userContext = userCtx;
|
s->core_info.userContext = userCtx;
|
||||||
s->core_info.userCallback = onEvent ? onEvent : null_onEvent;
|
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.state = state; /* required for chained queues + evec */
|
||||||
|
|
||||||
s->core_info.exhaustionVector = state + rose->stateOffsets.exhausted;
|
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.buf = (const u8 *)data;
|
||||||
s->core_info.len = length;
|
s->core_info.len = length;
|
||||||
s->core_info.hbuf = history;
|
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 */
|
s->deduper.som_log_dirty = 1; /* som logs have not been cleared */
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \brief Query whether this stream is broken.
|
#define STATUS_VALID_BITS \
|
||||||
*
|
(STATUS_TERMINATED | STATUS_EXHAUSTED | STATUS_DELAY_DIRTY)
|
||||||
* 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
|
/** \brief Retrieve status bitmask from stream state. */
|
||||||
* we have exhausted all reports.
|
|
||||||
*
|
|
||||||
* \return NOT_BROKEN, BROKEN_FROM_USER or BROKEN_EXHAUSTED.
|
|
||||||
*/
|
|
||||||
static really_inline
|
static really_inline
|
||||||
u8 getBroken(const char *state) {
|
u8 getStreamStatus(const char *state) {
|
||||||
const struct RoseRuntimeState *ts = (const void *)state;
|
u8 status = *(const u8 *)state;
|
||||||
assert(ts->broken == NOT_BROKEN || ts->broken == BROKEN_FROM_USER
|
assert((status & ~STATUS_VALID_BITS) == 0);
|
||||||
|| ts->broken == BROKEN_EXHAUSTED);
|
return status;
|
||||||
return ts->broken;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \brief Mark this stream with the given broken flag.
|
/** \brief Store status bitmask to stream state. */
|
||||||
*
|
|
||||||
* Possible values: NOT_BROKEN, BROKEN_FROM_USER, BROKEN_EXHAUSTED.
|
|
||||||
*/
|
|
||||||
static really_inline
|
static really_inline
|
||||||
void setBroken(char *state, u8 broken) {
|
void setStreamStatus(char *state, u8 status) {
|
||||||
DEBUG_PRINTF("set broken=%d\n", broken);
|
assert((status & ~STATUS_VALID_BITS) == 0);
|
||||||
assert(broken == NOT_BROKEN || broken == BROKEN_FROM_USER
|
*(u8 *)state = status;
|
||||||
|| broken == BROKEN_EXHAUSTED);
|
|
||||||
struct RoseRuntimeState *ts = (void *)state;
|
|
||||||
ts->broken = broken;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static really_inline
|
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 */
|
/* populate core info in scratch */
|
||||||
populateCoreInfo(scratch, rose, scratch->bstate, onEvent, userCtx, data,
|
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);
|
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);
|
char *state = getMultiState(s);
|
||||||
|
|
||||||
|
setStreamStatus(state, 0);
|
||||||
roseInitState(rose, state);
|
roseInitState(rose, state);
|
||||||
|
|
||||||
clearEvec((char *)state + rose->stateOffsets.exhausted, rose);
|
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
|
static really_inline
|
||||||
void rawEodExec(hs_stream_t *id, hs_scratch_t *scratch) {
|
void rawEodExec(hs_stream_t *id, hs_scratch_t *scratch) {
|
||||||
const struct RoseEngine *rose = id->rose;
|
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");
|
DEBUG_PRINTF("stream already broken\n");
|
||||||
assert(broken == BROKEN_FROM_USER || broken == BROKEN_EXHAUSTED);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -774,11 +763,9 @@ void rawEodExec(hs_stream_t *id, hs_scratch_t *scratch) {
|
|||||||
static never_inline
|
static never_inline
|
||||||
void soleOutfixEodExec(hs_stream_t *id, hs_scratch_t *scratch) {
|
void soleOutfixEodExec(hs_stream_t *id, hs_scratch_t *scratch) {
|
||||||
const struct RoseEngine *t = id->rose;
|
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");
|
DEBUG_PRINTF("stream already broken\n");
|
||||||
assert(broken == BROKEN_FROM_USER || broken == BROKEN_EXHAUSTED);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -817,15 +804,16 @@ void report_eod_matches(hs_stream_t *id, hs_scratch_t *scratch,
|
|||||||
|
|
||||||
const struct RoseEngine *rose = id->rose;
|
const struct RoseEngine *rose = id->rose;
|
||||||
char *state = getMultiState(id);
|
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");
|
DEBUG_PRINTF("stream is broken, just freeing storage\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
populateCoreInfo(scratch, rose, state, onEvent, context, NULL, 0,
|
populateCoreInfo(scratch, rose, state, onEvent, context, NULL, 0,
|
||||||
getHistory(state, rose, id->offset),
|
getHistory(state, rose, id->offset),
|
||||||
getHistoryAmount(rose, id->offset), id->offset, 0);
|
getHistoryAmount(rose, id->offset), id->offset, status, 0);
|
||||||
|
|
||||||
if (rose->somLocationCount) {
|
if (rose->somLocationCount) {
|
||||||
loadSomFromStream(scratch, id->offset);
|
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);
|
int halt = flushStoredSomMatches(scratch, ~0ULL);
|
||||||
if (halt) {
|
if (halt) {
|
||||||
DEBUG_PRINTF("told to stop matching\n");
|
DEBUG_PRINTF("told to stop matching\n");
|
||||||
scratch->core_info.broken = BROKEN_FROM_USER;
|
scratch->core_info.status |= STATUS_TERMINATED;
|
||||||
DEBUG_PRINTF("broken = %hhd\n", scratch->core_info.broken);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -931,8 +918,7 @@ static really_inline
|
|||||||
void rawStreamExec(struct hs_stream *stream_state, struct hs_scratch *scratch) {
|
void rawStreamExec(struct hs_stream *stream_state, struct hs_scratch *scratch) {
|
||||||
assert(stream_state);
|
assert(stream_state);
|
||||||
assert(scratch);
|
assert(scratch);
|
||||||
|
assert(!can_stop_matching(scratch));
|
||||||
assert(!getBroken(getMultiState(stream_state)));
|
|
||||||
|
|
||||||
DEBUG_PRINTF("::: streaming rose ::: offset = %llu len = %zu\n",
|
DEBUG_PRINTF("::: streaming rose ::: offset = %llu len = %zu\n",
|
||||||
stream_state->offset, scratch->core_info.len);
|
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) &&
|
if (!told_to_stop_matching(scratch) &&
|
||||||
isAllExhausted(rose, scratch->core_info.exhaustionVector)) {
|
isAllExhausted(rose, scratch->core_info.exhaustionVector)) {
|
||||||
DEBUG_PRINTF("stream exhausted\n");
|
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) {
|
struct hs_scratch *scratch) {
|
||||||
assert(stream_state);
|
assert(stream_state);
|
||||||
assert(scratch);
|
assert(scratch);
|
||||||
|
assert(!can_stop_matching(scratch));
|
||||||
|
|
||||||
char *state = getMultiState(stream_state);
|
char *state = getMultiState(stream_state);
|
||||||
assert(!getBroken(state));
|
|
||||||
|
|
||||||
const struct RoseEngine *rose = stream_state->rose;
|
const struct RoseEngine *rose = stream_state->rose;
|
||||||
const struct HWLM *ftable = getFLiteralMatcher(rose);
|
const struct HWLM *ftable = getFLiteralMatcher(rose);
|
||||||
@ -982,7 +968,7 @@ void pureLiteralStreamExec(struct hs_stream *stream_state,
|
|||||||
if (!told_to_stop_matching(scratch) &&
|
if (!told_to_stop_matching(scratch) &&
|
||||||
isAllExhausted(rose, scratch->core_info.exhaustionVector)) {
|
isAllExhausted(rose, scratch->core_info.exhaustionVector)) {
|
||||||
DEBUG_PRINTF("stream exhausted\n");
|
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) {
|
struct hs_scratch *scratch) {
|
||||||
assert(stream_state);
|
assert(stream_state);
|
||||||
assert(scratch);
|
assert(scratch);
|
||||||
|
assert(!can_stop_matching(scratch));
|
||||||
|
|
||||||
const struct RoseEngine *t = stream_state->rose;
|
const struct RoseEngine *t = stream_state->rose;
|
||||||
assert(t->outfixEndQueue == 1);
|
assert(t->outfixEndQueue == 1);
|
||||||
@ -1017,7 +1004,7 @@ void soleOutfixStreamExec(struct hs_stream *stream_state,
|
|||||||
if (nfaQueueExec(q->nfa, q, scratch->core_info.len)) {
|
if (nfaQueueExec(q->nfa, q, scratch->core_info.len)) {
|
||||||
nfaQueueCompressState(nfa, q, scratch->core_info.len);
|
nfaQueueCompressState(nfa, q, scratch->core_info.len);
|
||||||
} else if (!told_to_stop_matching(scratch)) {
|
} 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;
|
const struct RoseEngine *rose = id->rose;
|
||||||
char *state = getMultiState(id);
|
char *state = getMultiState(id);
|
||||||
|
|
||||||
u8 broken = getBroken(state);
|
u8 status = getStreamStatus(state);
|
||||||
if (broken) {
|
if (status & (STATUS_TERMINATED | STATUS_EXHAUSTED)) {
|
||||||
DEBUG_PRINTF("stream is broken, halting scan\n");
|
DEBUG_PRINTF("stream is broken, halting scan\n");
|
||||||
if (broken == BROKEN_FROM_USER) {
|
if (status & STATUS_TERMINATED) {
|
||||||
return HS_SCAN_TERMINATED;
|
return HS_SCAN_TERMINATED;
|
||||||
} else {
|
} else {
|
||||||
assert(broken == BROKEN_EXHAUSTED);
|
|
||||||
return HS_SUCCESS;
|
return HS_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1049,14 +1035,13 @@ hs_error_t hs_scan_stream_internal(hs_stream_t *id, const char *data,
|
|||||||
// cases here.
|
// cases here.
|
||||||
if (unlikely(length == 0)) {
|
if (unlikely(length == 0)) {
|
||||||
DEBUG_PRINTF("zero length block\n");
|
DEBUG_PRINTF("zero length block\n");
|
||||||
assert(getBroken(state) != BROKEN_FROM_USER);
|
|
||||||
return HS_SUCCESS;
|
return HS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 historyAmount = getHistoryAmount(rose, id->offset);
|
u32 historyAmount = getHistoryAmount(rose, id->offset);
|
||||||
populateCoreInfo(scratch, rose, state, onEvent, context, data, length,
|
populateCoreInfo(scratch, rose, state, onEvent, context, data, length,
|
||||||
getHistory(state, rose, id->offset), historyAmount,
|
getHistory(state, rose, id->offset), historyAmount,
|
||||||
id->offset, flags);
|
id->offset, status, flags);
|
||||||
assert(scratch->core_info.hlen <= id->offset
|
assert(scratch->core_info.hlen <= id->offset
|
||||||
&& scratch->core_info.hlen <= rose->historyRequired);
|
&& 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) {
|
if (!id->offset && rose->boundary.reportZeroOffset) {
|
||||||
DEBUG_PRINTF("zero reports\n");
|
DEBUG_PRINTF("zero reports\n");
|
||||||
processReportList(rose, rose->boundary.reportZeroOffset, 0, scratch);
|
processReportList(rose, rose->boundary.reportZeroOffset, 0, scratch);
|
||||||
broken = scratch->core_info.broken;
|
if (unlikely(can_stop_matching(scratch))) {
|
||||||
if (unlikely(broken)) {
|
|
||||||
DEBUG_PRINTF("stream is broken, halting scan\n");
|
DEBUG_PRINTF("stream is broken, halting scan\n");
|
||||||
setBroken(state, broken);
|
setStreamStatus(state, scratch->core_info.status);
|
||||||
if (broken == BROKEN_FROM_USER) {
|
if (told_to_stop_matching(scratch)) {
|
||||||
return HS_SCAN_TERMINATED;
|
return HS_SCAN_TERMINATED;
|
||||||
} else {
|
} else {
|
||||||
assert(broken == BROKEN_EXHAUSTED);
|
assert(scratch->core_info.status & STATUS_EXHAUSTED);
|
||||||
return HS_SUCCESS;
|
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)) {
|
if (rose->hasSom && !told_to_stop_matching(scratch)) {
|
||||||
int halt = flushStoredSomMatches(scratch, ~0ULL);
|
int halt = flushStoredSomMatches(scratch, ~0ULL);
|
||||||
if (halt) {
|
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))) {
|
if (likely(!can_stop_matching(scratch))) {
|
||||||
maintainHistoryBuffer(id->rose, getMultiState(id), data, length);
|
maintainHistoryBuffer(rose, state, data, length);
|
||||||
id->offset += length; /* maintain offset */
|
id->offset += length; /* maintain offset */
|
||||||
|
|
||||||
if (rose->somLocationCount) {
|
if (rose->somLocationCount) {
|
||||||
storeSomToStream(scratch, id->offset);
|
storeSomToStream(scratch, id->offset);
|
||||||
}
|
}
|
||||||
} else if (told_to_stop_matching(scratch)) {
|
} else if (told_to_stop_matching(scratch)) {
|
||||||
setBroken(state, BROKEN_FROM_USER);
|
|
||||||
return HS_SCAN_TERMINATED;
|
return HS_SCAN_TERMINATED;
|
||||||
} else { /* exhausted */
|
|
||||||
setBroken(state, BROKEN_EXHAUSTED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return HS_SUCCESS;
|
return HS_SUCCESS;
|
||||||
|
@ -70,17 +70,16 @@ struct catchup_pq {
|
|||||||
u32 qm_size; /**< current size of the priority queue */
|
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). */
|
/** \brief Status flag: all possible matches on this stream have
|
||||||
#define NOT_BROKEN 0
|
* 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
|
/** \brief Status flag: Rose requires rebuild as delay literal matched in
|
||||||
* terminated. */
|
* history. */
|
||||||
#define BROKEN_FROM_USER 1
|
#define STATUS_DELAY_DIRTY (1U << 2)
|
||||||
|
|
||||||
/** \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 Core information about the current scan, used everywhere. */
|
/** \brief Core information about the current scan, used everywhere. */
|
||||||
struct core_info {
|
struct core_info {
|
||||||
@ -93,12 +92,12 @@ struct core_info {
|
|||||||
const struct RoseEngine *rose;
|
const struct RoseEngine *rose;
|
||||||
char *state; /**< full stream state */
|
char *state; /**< full stream state */
|
||||||
char *exhaustionVector; /**< pointer to evec for this stream */
|
char *exhaustionVector; /**< pointer to evec for this stream */
|
||||||
char broken; /**< user told us to stop, or exhausted */
|
|
||||||
const u8 *buf; /**< main scan buffer */
|
const u8 *buf; /**< main scan buffer */
|
||||||
size_t len; /**< length of main scan buffer in bytes */
|
size_t len; /**< length of main scan buffer in bytes */
|
||||||
const u8 *hbuf; /**< history buffer */
|
const u8 *hbuf; /**< history buffer */
|
||||||
size_t hlen; /**< length of history buffer in bytes. */
|
size_t hlen; /**< length of history buffer in bytes. */
|
||||||
u64a buf_offset; /**< stream offset, for the base of the buffer */
|
u64a buf_offset; /**< stream offset, for the base of the buffer */
|
||||||
|
u8 status; /**< stream status bitmask, using STATUS_ flags above */
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \brief Rose state information. */
|
/** \brief Rose state information. */
|
||||||
@ -213,12 +212,12 @@ struct fatbit **getDelaySlots(struct hs_scratch *scratch) {
|
|||||||
|
|
||||||
static really_inline
|
static really_inline
|
||||||
char told_to_stop_matching(const struct hs_scratch *scratch) {
|
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
|
static really_inline
|
||||||
char can_stop_matching(const struct hs_scratch *scratch) {
|
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
|
#ifdef __cplusplus
|
||||||
|
@ -487,7 +487,7 @@ int clearSomLog(struct hs_scratch *scratch, u64a offset, struct fatbit *log,
|
|||||||
int halt = ci->userCallback(onmatch, from_offset, offset, flags,
|
int halt = ci->userCallback(onmatch, from_offset, offset, flags,
|
||||||
ci->userContext);
|
ci->userContext);
|
||||||
if (halt) {
|
if (halt) {
|
||||||
ci->broken = BROKEN_FROM_USER;
|
ci->status |= STATUS_TERMINATED;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user