/** * \brief Get a new flow * * Get a new flow. We're checking memcap first and will try to make room * if the memcap is reached. * * \param tv thread vars * \param dtv decode thread vars (for flow log api thread data) * * \retval f *LOCKED* flow on succes, NULL on error. */ static Flow *FlowGetNew(ThreadVars *tv, DecodeThreadVars *dtv, const Packet *p) { Flow *f = NULL; if (FlowCreateCheck(p) == 0) { return NULL; } /* get a flow from the spare queue */ f = FlowDequeue(&flow_spare_q); if (f == NULL) { /* If we reached the max memcap, we get a used flow */ if (!(FLOW_CHECK_MEMCAP(sizeof(Flow) + FlowStorageSize()))) { /* declare state of emergency */ if (!(SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY)) { SC_ATOMIC_OR(flow_flags, FLOW_EMERGENCY); FlowTimeoutsEmergency(); /* under high load, waking up the flow mgr each time leads * to high cpu usage. Flows are not timed out much faster if * we check a 1000 times a second. */ FlowWakeupFlowManagerThread(); } f = FlowGetUsedFlow(tv, dtv); if (f == NULL) { /* max memcap reached, so increments the counter */ if (tv != NULL && dtv != NULL) { StatsIncr(tv, dtv->counter_flow_memcap); } /* very rare, but we can fail. Just giving up */ return NULL; } /* freed a flow, but it's unlocked */ } else { /* now see if we can alloc a new flow */ f = FlowAlloc(); if (f == NULL) { if (tv != NULL && dtv != NULL) { StatsIncr(tv, dtv->counter_flow_memcap); } return NULL; } /* flow is initialized but *unlocked* */ } } else { /* flow has been recycled before it went into the spare queue */ /* flow is initialized (recylced) but *unlocked* */ } FLOWLOCK_WRLOCK(f); FlowUpdateCounter(tv, dtv, p->proto); return f; }
static int FlowStorageTest02(void) { Flow *f = NULL; StorageInit(); int id1 = FlowStorageRegister("test", sizeof(void *), NULL, StorageTestFree); if (id1 < 0) goto error; if (StorageFinalize() < 0) goto error; FlowInitConfig(FLOW_QUIET); f = FlowAlloc(); if (f == NULL) { goto error; } void *ptr = FlowGetStorageById(f, id1); if (ptr != NULL) { goto error; } void *ptr1a = SCMalloc(128); if (ptr1a == NULL) { goto error; } FlowSetStorageById(f, id1, ptr1a); void *ptr1b = FlowGetStorageById(f, id1); if (ptr1a != ptr1b) { goto error; } FlowClearMemory(f, 0); FlowFree(f); FlowShutdown(); StorageCleanup(); return 1; error: if (f != NULL) { FlowClearMemory(f, 0); FlowFree(f); } FlowShutdown(); StorageCleanup(); return 0; }
static int FlowStorageTest01(void) { Flow *f = NULL; StorageInit(); int id1 = FlowStorageRegister("test", 8, StorageTestAlloc, StorageTestFree); if (id1 < 0) goto error; int id2 = FlowStorageRegister("variable", 24, StorageTestAlloc, StorageTestFree); if (id2 < 0) goto error; int id3 = FlowStorageRegister("store", sizeof(void *), StorageTestAlloc, StorageTestFree); if (id3 < 0) goto error; if (StorageFinalize() < 0) goto error; FlowInitConfig(FLOW_QUIET); f = FlowAlloc(); if (f == NULL) { goto error; } void *ptr = FlowGetStorageById(f, id1); if (ptr != NULL) { goto error; } ptr = FlowGetStorageById(f, id2); if (ptr != NULL) { goto error; } ptr = FlowGetStorageById(f, id3); if (ptr != NULL) { goto error; } void *ptr1a = FlowAllocStorageById(f, id1); if (ptr1a == NULL) { goto error; } void *ptr2a = FlowAllocStorageById(f, id2); if (ptr2a == NULL) { goto error; } void *ptr3a = FlowAllocStorageById(f, id3); if (ptr3a == NULL) { goto error; } void *ptr1b = FlowGetStorageById(f, id1); if (ptr1a != ptr1b) { goto error; } void *ptr2b = FlowGetStorageById(f, id2); if (ptr2a != ptr2b) { goto error; } void *ptr3b = FlowGetStorageById(f, id3); if (ptr3a != ptr3b) { goto error; } FlowClearMemory(f, 0); FlowFree(f); FlowShutdown(); StorageCleanup(); return 1; error: if (f != NULL) { FlowClearMemory(f, 0); FlowFree(f); } FlowShutdown(); StorageCleanup(); return 0; }