static void test_lock(void) { int i = 0; int n = 100; //int counter = 0; Lock* lock = lock_create(); for(i = 0; i < n; i++) { assert(lock_read(lock) == RET_OK); //assert(lock_get_rcounter(lock, &counter) == RET_OK); //assert(counter == 1); assert(data == 0); assert(lock_unread(lock) == RET_OK); //assert(lock_get_rcounter(lock, &counter) == RET_OK); //assert(counter == 0); assert(lock_write(lock) == RET_OK); data = 1; assert(lock_unwrite(lock) == RET_OK); assert(lock_read(lock) == RET_OK); assert(data == 1); assert(lock_unread(lock) == RET_OK); assert(lock_write(lock) == RET_OK); data = 0; assert(lock_unwrite(lock) == RET_OK); } lock_destroy(lock); return; }
STDMETHODIMP LightOPCGroup::RemoveItems(DWORD dwCount, OPCHANDLE *phServer, HRESULT **ppErrors) { HRESULT hr = S_OK; HRESULT *err = 0; LO_CHECK_STATEz1("RemoveItems", ppErrors); if (!dwCount || !phServer) { hr = E_INVALIDARG; goto Return; } err = (HRESULT*)loComAlloc(dwCount * sizeof(HRESULT)); if (!err) { hr = E_OUTOFMEMORY; goto Return; } lock_write(); { DWORD ii; LightOPCItem *item; for(ii = 0; ii < dwCount;) { unsigned tt; loTagId ti[32]; for(tt = 0; tt < SIZEOF_ARRAY(ti) && ii < dwCount; ii++) if (item = by_index((unsigned)phServer[ii])) { if (item->bActive) { active_count--; ti[tt++] = item->tid; } del((unsigned)phServer[ii]); err[ii] = S_OK; } else { err[ii] = OPC_E_INVALIDHANDLE; hr = S_FALSE; } if (tt && Active) loChangeActivity(&owner->ctxt.cactx, 0, tt, ti); } } unlock(); Return: if (FAILED(hr)) { UL_INFO((LOG_GRH("RemoveItems(%lu) = %s"), dwCount, loStrError(hr))); } else { if (ppErrors) *ppErrors = err, err = 0; UL_NOTICE((LOG_GRH("RemoveItems(%lu) = %s"), dwCount, loStrError(hr))); } if (err) loComFree(err); LO_FINISH(); return hr; }
MatchErrorCode MatchTable::delete_entry(entry_handle_t handle) { WriteLock lock = lock_write(); return match_unit->delete_entry(handle); }
HRESULT LightOPCServer::internalRemoveGroup(unsigned groupHandleID, int bForce) { #if 1 HRESULT hr = loOPC_E_INVALIDHANDLE; #else HRESULT hr = loOPC_E_NOTFOUND; #endif unsigned ii; UL_DEBUG((LOG_SR("internalRemoveGroup(%u %s)"), groupHandleID, bForce? "FORCE": "")); WR_lock(&lk_remove); lock_write(); if (ii = by_handle(groupHandleID)) { hr = del(ii, bForce && !(/*se->driver.*/ldFlags & loDf_NOFORCE)) ? OPC_S_INUSE: S_OK; ostatus.dwGroupCount--; } unlock(); lw_rw_unlock(&lk_remove); UL_DEBUG((LOGID, "%!l internalRemoveGroup(%u %s) =", hr, groupHandleID, bForce? "FORCE": "")); return hr; }
MatchErrorCode MatchTableAbstract::set_entry_ttl( entry_handle_t handle, unsigned int ttl_ms ) { if(!with_ageing) return MatchErrorCode::AGEING_DISABLED; WriteLock lock = lock_write(); return match_unit_->set_entry_ttl(handle, ttl_ms); }
MatchErrorCode MatchTableIndirect::set_default_member(mbr_hdl_t mbr) { WriteLock lock = lock_write(); if(!is_valid_mbr(mbr)) return MatchErrorCode::INVALID_MBR_HANDLE; default_index = IndirectIndex::make_mbr_index(mbr); return MatchErrorCode::SUCCESS; }
MatchErrorCode MatchTableIndirectWS::set_default_group(grp_hdl_t grp) { WriteLock lock = lock_write(); if(!is_valid_grp(grp)) return MatchErrorCode::INVALID_GRP_HANDLE; default_index = IndirectIndex::make_grp_index(grp); return MatchErrorCode::SUCCESS; }
static void test_invalid_params(void) { printf("==========Warning is normal begin==========\n"); assert(lock_read(NULL) == RET_INVALID_PARAMS); assert(lock_unread(NULL) == RET_INVALID_PARAMS); assert(lock_write(NULL) == RET_INVALID_PARAMS); assert(lock_unwrite(NULL) == RET_INVALID_PARAMS); printf("==========Warning is normal end============\n"); return; }
MatchErrorCode MatchTableIndirect::delete_entry(entry_handle_t handle) { WriteLock lock = lock_write(); const IndirectIndex *index; MatchErrorCode rc = match_unit->get_value(handle, &index); if(rc != MatchErrorCode::SUCCESS) return rc; index_ref_count.decrease(*index); return match_unit->delete_entry(handle); }
MatchErrorCode MatchTableIndirectWS::create_group(grp_hdl_t *grp) { WriteLock lock = lock_write(); if(grp_handles.get_handle(grp)) return MatchErrorCode::ERROR; groups_insert(*grp); num_groups++; return MatchErrorCode::SUCCESS; }
MatchErrorCode MatchTableAbstract::write_counters(entry_handle_t handle, counter_value_t bytes, counter_value_t packets) { ReadLock lock = lock_write(); if(!with_counters) return MatchErrorCode::COUNTERS_DISABLED; if(!is_valid_handle(handle)) return MatchErrorCode::INVALID_HANDLE; MatchUnit::EntryMeta &meta = match_unit_->get_entry_meta(handle); // should I hide counter implementation more? meta.counter.write_counter(bytes, packets); return MatchErrorCode::SUCCESS; }
MatchErrorCode MatchTableIndirect::add_entry( const std::vector<MatchKeyParam> &match_key, mbr_hdl_t mbr, entry_handle_t *handle, int priority ) { WriteLock lock = lock_write(); if(!is_valid_mbr(mbr)) return MatchErrorCode::INVALID_MBR_HANDLE; IndirectIndex index = IndirectIndex::make_mbr_index(mbr); index_ref_count.increase(index); return match_unit->add_entry(match_key, std::move(index), handle, priority); }
MatchErrorCode MatchTable::modify_entry( entry_handle_t handle, const ActionFn *action_fn, ActionData action_data ) { WriteLock lock = lock_write(); ActionFnEntry action_fn_entry(action_fn, std::move(action_data)); const ControlFlowNode *next_node = get_next_node(action_fn->get_id()); return match_unit->modify_entry( handle, ActionEntry(std::move(action_fn_entry), next_node) ); }
STDMETHODIMP LightOPCGroup::SetClientHandles(DWORD dwCount, OPCHANDLE *phServer, OPCHANDLE *phClient, HRESULT **ppErrors) { HRESULT hr = S_OK; HRESULT *err = 0; LO_CHECK_STATEz1("SetClientHandles", ppErrors); if (!dwCount || !phServer || !phClient) { hr = E_INVALIDARG; goto Return; } err = (HRESULT*)loComAlloc(dwCount * sizeof(HRESULT)); if (!err) { hr = E_OUTOFMEMORY; goto Return; } lock_write(); { DWORD ii; LightOPCItem *item; for(ii = 0; ii < dwCount; ii++) if (item = by_index((unsigned)phServer[ii])) { item->hClient = phClient[ii]; err[ii] = S_OK; } else { err[ii] = OPC_E_INVALIDHANDLE; hr = S_FALSE; } } unlock(); Return: if (FAILED(hr)) { UL_INFO((LOG_GRH("SetClientHandles(%lu) = %s"), dwCount, loStrError(hr))); } else { if (ppErrors) *ppErrors = err, err = 0; UL_NOTICE((LOG_GRH("SetClientHandles(%lu) = %s"), dwCount, loStrError(hr))); } if (err) loComFree(err); LO_FINISH(); return hr; }
MatchErrorCode MatchTable::set_default_action( const ActionFn *action_fn, ActionData action_data ) { ActionFnEntry action_fn_entry(action_fn, std::move(action_data)); const ControlFlowNode *next_node = get_next_node(action_fn->get_id()); WriteLock lock = lock_write(); default_entry = ActionEntry(std::move(action_fn_entry), next_node); return MatchErrorCode::SUCCESS; }
MatchErrorCode MatchTableIndirectWS::add_entry_ws( const std::vector<MatchKeyParam> &match_key, grp_hdl_t grp, entry_handle_t *handle, int priority ) { WriteLock lock = lock_write(); if(!is_valid_grp(grp)) return MatchErrorCode::INVALID_GRP_HANDLE; if(get_grp_size(grp) == 0) return MatchErrorCode::EMPTY_GRP; IndirectIndex index = IndirectIndex::make_grp_index(grp); index_ref_count.increase(index); return match_unit->add_entry(match_key, std::move(index), handle, priority); }
MatchErrorCode MatchTableIndirectWS::remove_member_from_group(mbr_hdl_t mbr, grp_hdl_t grp) { WriteLock lock = lock_write(); if(!is_valid_mbr(mbr)) return MatchErrorCode::INVALID_MBR_HANDLE; if(!is_valid_grp(grp)) return MatchErrorCode::INVALID_GRP_HANDLE; GroupInfo &group_info = group_entries[grp]; MatchErrorCode rc = group_info.delete_member(mbr); if(rc != MatchErrorCode::SUCCESS) return rc; index_ref_count.decrease(IndirectIndex::make_mbr_index(mbr)); return MatchErrorCode::SUCCESS; }
MatchErrorCode MatchTableIndirect::modify_member( mbr_hdl_t mbr, const ActionFn *action_fn, ActionData action_data ) { ActionFnEntry action_fn_entry(action_fn, std::move(action_data)); const ControlFlowNode *next_node = get_next_node(action_fn->get_id()); WriteLock lock = lock_write(); if(!is_valid_mbr(mbr)) return MatchErrorCode::INVALID_MBR_HANDLE; action_entries[mbr] = ActionEntry(std::move(action_fn_entry), next_node); return MatchErrorCode::SUCCESS; }
MatchErrorCode MatchTableIndirect::delete_member(mbr_hdl_t mbr) { WriteLock lock = lock_write(); if(!is_valid_mbr(mbr)) return MatchErrorCode::INVALID_MBR_HANDLE; if(index_ref_count.get(IndirectIndex::make_mbr_index(mbr)) > 0) return MatchErrorCode::MBR_STILL_USED; assert(!mbr_handles.release_handle(mbr)); num_members--; return MatchErrorCode::SUCCESS; }
MatchErrorCode MatchTable::add_entry( const std::vector<MatchKeyParam> &match_key, const ActionFn *action_fn, ActionData action_data, // move it entry_handle_t *handle, int priority ) { ActionFnEntry action_fn_entry(action_fn, std::move(action_data)); const ControlFlowNode *next_node = get_next_node(action_fn->get_id()); WriteLock lock = lock_write(); return match_unit->add_entry( match_key, ActionEntry(std::move(action_fn_entry), next_node), handle, priority ); }
STDMETHODIMP LightOPCGroup::SetState(DWORD *pRequestedUpdateRate, DWORD *pRevisedUpdateRate, BOOL *pActive, LONG *pTimeBias, FLOAT *pPercentDeadband, DWORD *pLCID, OPCHANDLE *phClientGroup) { HRESULT hr = S_OK; LO_CHECK_STATEz0("SetState"); UL_TRACE((LOG_GRH("LightOPCGroup::SetState()"))); if (pLCID && owner->se->driver.ldCheckLocale && owner->se->driver.ldCheckLocale(&owner->ctxt.cactx, *pLCID)) pLCID = 0; /* ignore on errors */ lock_write(); if (pRequestedUpdateRate) { // if (!pRevisedUpdateRate) hr = E_INVALIDARG; DWORD revised_rate = loReviseUpdateRate(owner->se, *pRequestedUpdateRate); if (UpdateRate > revised_rate && (!pActive || *pActive) /* && Active && 0 != (advise_present & advise_enabled)*/) UpdateRate = revised_rate, actuate_async(0); else UpdateRate = revised_rate; if (UpdateRate != *pRequestedUpdateRate) hr = OPC_S_UNSUPPORTEDRATE; } if (pRevisedUpdateRate) *pRevisedUpdateRate = UpdateRate; if (pActive) set_active(*pActive); if (pTimeBias) TimeBias = *pTimeBias; if (pPercentDeadband) if (lo_IsNANf(*pPercentDeadband) || *pPercentDeadband < 0. || *pPercentDeadband > 100.) hr = E_INVALIDARG; else Deadband = *pPercentDeadband; if (pLCID) grLCID = *pLCID; if (phClientGroup) ClientHandle = *phClientGroup; unlock(); if (!FAILED(hr)) UL_NOTICE((LOG_GR("SetGroupState(%u) =(%umS (%umS) %g%%)Ok"), ServerHandle, (unsigned)UpdateRate, (unsigned)(pRequestedUpdateRate? *pRequestedUpdateRate: 0), Deadband)); else UL_INFO((LOG_GR("SetGroupState(%u) =%s"), ServerHandle, loStrError(hr))); LO_FINISH(); return hr; }
MatchErrorCode MatchTableIndirect::modify_entry( entry_handle_t handle, mbr_hdl_t mbr ) { WriteLock lock = lock_write(); const IndirectIndex *index; MatchErrorCode rc = match_unit->get_value(handle, &index); if(rc != MatchErrorCode::SUCCESS) return rc; index_ref_count.decrease(*index); if(!is_valid_mbr(mbr)) return MatchErrorCode::INVALID_MBR_HANDLE; IndirectIndex new_index = IndirectIndex::make_mbr_index(mbr); index_ref_count.increase(new_index); return match_unit->modify_entry(handle, std::move(new_index)); }
MatchErrorCode MatchTableIndirect::add_member( const ActionFn *action_fn, ActionData action_data, mbr_hdl_t *mbr ) { ActionFnEntry action_fn_entry(action_fn, std::move(action_data)); const ControlFlowNode *next_node = get_next_node(action_fn->get_id()); WriteLock lock = lock_write(); if(mbr_handles.get_handle(mbr)) return MatchErrorCode::ERROR; entries_insert(*mbr, ActionEntry(std::move(action_fn_entry), next_node)); num_members++; return MatchErrorCode::SUCCESS; }
MatchErrorCode MatchTableIndirectWS::modify_entry_ws( entry_handle_t handle, grp_hdl_t grp ) { WriteLock lock = lock_write(); const IndirectIndex *index; MatchErrorCode rc = match_unit->get_value(handle, &index); if(rc != MatchErrorCode::SUCCESS) return rc; index_ref_count.decrease(*index); if(!is_valid_grp(grp)) return MatchErrorCode::INVALID_GRP_HANDLE; if(get_grp_size(grp) == 0) return MatchErrorCode::EMPTY_GRP; IndirectIndex new_index = IndirectIndex::make_grp_index(grp); index_ref_count.increase(new_index); return match_unit->modify_entry(handle, std::move(new_index)); }
MatchErrorCode MatchTableIndirectWS::delete_group(grp_hdl_t grp) { WriteLock lock = lock_write(); if(!is_valid_grp(grp)) return MatchErrorCode::INVALID_GRP_HANDLE; if(index_ref_count.get(IndirectIndex::make_grp_index(grp)) > 0) return MatchErrorCode::GRP_STILL_USED; /* we allow deletion of non-empty groups, but we must remember to decrease the ref count for the members. Note that we do not allow deletion of a member which is in a group */ GroupInfo &group_info = group_entries[grp]; for(auto mbr : group_info) index_ref_count.decrease(IndirectIndex::make_mbr_index(mbr)); assert(!grp_handles.release_handle(grp)); num_groups--; return MatchErrorCode::SUCCESS; }
STDMETHODIMP LightOPCGroup::SetName(LPCWSTR szName) { HRESULT hr = S_OK; LO_CHECK_STATEz0("SetName"); UL_TRACE((LOG_GRH("LightOPCGroup::SetName()"))); if (!szName) hr = E_INVALIDARG; else { LightOPCGroup *grp; lock_write(); grp = owner->by_name(szName); if (!grp) hr = set_name(szName); else if (grp != this) hr = OPC_E_DUPLICATENAME; unlock(); } if (S_OK != hr) UL_INFO((LOG_GRH("SetGroupName(%ls) =%s"), loWnul(szName), loStrError(hr))); else UL_NOTICE((LOG_GRH("SetGroupName(%ls)"), szName)); LO_FINISH(); return hr; }
STDMETHODIMP LightOPCGroup::SetDatatypes(DWORD dwCount, OPCHANDLE *phServer, VARTYPE *pRequestedDatatypes, HRESULT **ppErrors) { HRESULT hr = S_OK; HRESULT *err = 0; loTagEntry *te; loCallerx cctx; LO_CHECK_STATEz1("SetDatatypes", ppErrors); if (!dwCount || !phServer || !pRequestedDatatypes) { hr = E_INVALIDARG; goto Return; } err = (HRESULT*)loComAlloc(dwCount * sizeof(HRESULT)); if (!err) { hr = E_OUTOFMEMORY; goto Return; } te = owner->se->tags; cctx = owner->ctxt; lock_write(); { DWORD ii; LightOPCItem *item; cctx.cta.vc_lcid = grLCID; for(ii = 0; ii < dwCount; ii++) if (item = by_index((unsigned)phServer[ii])) { VARTYPE vt; loTagAttrib *ta; /* if (VT_EMPTY == (vt = pRequestedDatatypes[ii])) item->vtRequestedDataType = vt, err[ii] = S_OK; else */ if (S_OK == (err[ii] = lo_checktype(&cctx, ta = &te[item->tid].attr, vt = pRequestedDatatypes[ii]))) { item->vtRequestedDataType = vt; item->convtype = lo_check_conversion(ta, vt); } else hr = S_FALSE; } else { err[ii] = OPC_E_INVALIDHANDLE; hr = S_FALSE; } } unlock(); Return: if (FAILED(hr)) { UL_INFO((LOG_GRH("SetDatatypes(%lu) = %s"), dwCount, loStrError(hr))); } else { if (ppErrors) *ppErrors = err, err = 0; UL_NOTICE((LOG_GRH("SetDatatypes(%lu) = %s"), dwCount, loStrError(hr))); } if (err) loComFree(err); LO_FINISH(); return hr; }
void MatchTableAbstract::reset_state() { WriteLock lock = lock_write(); reset_state_(); }
STDMETHODIMP LightOPCGroup::SetActiveState(DWORD dwCount, OPCHANDLE *phServer, BOOL bActive, HRESULT **ppErrors) { HRESULT hr = S_OK; HRESULT *err = 0; int aqual = OPC_QUALITY_OUT_OF_SERVICE; unsigned aact = 0; LO_CHECK_STATEz1("SetActiveState", ppErrors); if (!dwCount || !phServer /*|| !ppErrors*/) { hr = E_INVALIDARG; goto Return; } err = (HRESULT*)loComAlloc(dwCount * sizeof(HRESULT)); if (!err) { hr = E_OUTOFMEMORY; goto Return; } if (bActive = 0 != bActive) aqual = -1; lock_write(); { DWORD ii; LightOPCItem *item; for(ii = 0; ii < dwCount;) { unsigned tt; loTagId ti[32]; for(tt = 0; tt < SIZEOF_ARRAY(ti) && ii < dwCount; ii++) if (item = by_index((unsigned)phServer[ii])) { if (item->bActive != bActive /*&& (OPC_READABLE & tags[item->tid].attr.flag)*/) { aact++; item->bActive = bActive; ti[tt++] = item->tid; item->Quality = aqual; item->TouchChanged(); } err[ii] = S_OK; } else { err[ii] = OPC_E_INVALIDHANDLE; hr = S_FALSE; } if (tt && Active) loChangeActivity(&owner->ctxt.cactx, bActive, tt, ti); } if (bActive) active_count += aact, last_trid = 0; else active_count -= aact; } unlock(); Return: if (FAILED(hr)) { UL_INFO((LOG_GRH("SetActiveState(%lu, %u) = %s"), dwCount, bActive, loStrError(hr))); } else { if (ppErrors) *ppErrors = err, err = 0; UL_NOTICE((LOG_GRH("SetActiveState(%lu, %u) = %s"), dwCount, bActive, loStrError(hr))); } if (err) loComFree(err); LO_FINISH(); return hr; }
STDMETHODIMP LightOPCGroup::AddItems(DWORD dwCount, OPCITEMDEF *pItemArray, OPCITEMRESULT **ppAddResults, HRESULT **ppErrors) { HRESULT hr; HRESULT *err = 0; OPCITEMRESULT *ir = 0; loTagId *tid = 0; void **acpath; LightOPCItem **oi = 0; DWORD ii; loTagEntry *tags; unsigned act_count; loAA_DECLARE(sizeof(LightOPCItem*) + sizeof(loTagId) + sizeof(void*)); LO_CHECK_STATEz2("AddItems", ppAddResults, ppErrors); if (!ppAddResults) { hr = E_INVALIDARG; goto Return; } ii = dwCount * (sizeof(*oi) + sizeof(*tid) + sizeof(*acpath)); if (0 == ii) { hr = E_INVALIDARG; goto Return; } if (!(oi = (LightOPCItem**)loAA_ALLOC(ii))) { hr = E_OUTOFMEMORY; goto Return; } memset(oi, 0, ii); tid = (loTagId*)&oi[dwCount]; acpath = (void**)&tid[dwCount]; hr = internalValidateItems(dwCount, pItemArray, tid, acpath, &ir, &err); if (FAILED(hr)) goto Return; tags = owner->se->tags; for(ii = 0; ii < dwCount; ii++) if (S_OK == err[ii]) { LightOPCItem *newby; hr = E_OUTOFMEMORY; if (oi[ii] = newby = new LightOPCItem) { OPCITEMDEF *idef = &pItemArray[ii]; loTagAttrib *ta = &tags[tid[ii]].attr; newby->tid = tid[ii]; newby->AcPath = acpath[ii]; newby->hClient = idef->hClient; newby->vtRequestedDataType = idef->vtRequestedDataType; newby->convtype = lo_check_conversion(ta, newby->vtRequestedDataType); hr = S_OK; if ((NULL == newby->AcPath || S_OK == (hr = newby->set_accpath(idef->szAccessPath))) && (!ta->taName || !(ta->taFlags & loTF_CANONAME) && #if 0 wcscmp #else owner->se->wstrcmp #endif (ta->taName, idef->szItemID))) hr = newby->set_itemid(idef->szItemID); newby->Quality = -1; if (0 == (newby->bActive = 0 != idef->bActive)) tid[ii] = 0, newby->Quality = OPC_QUALITY_OUT_OF_SERVICE; // else if (!(OPC_READABLE & tags[tid[ii]].attr.flag)) // newby->bActive = 0; } err[ii] = hr; if (hr != S_OK) UL_NOTICE((LOG_GR("AddItem(%ls)(%ls)%x/%x = %s"), loWnul(pItemArray[ii].szItemID), loWnul(pItemArray[ii].szAccessPath), pItemArray[ii].vtRequestedDataType, ir[ii].vtCanonicalDataType, loStrError(err[ii]))); } act_count = 0; lock_write(); for(ii = 0; ii < dwCount; ii++) if (S_OK == err[ii]) { unsigned idx; if (idx = add(oi[ii])) { act_count += oi[ii]->bActive /* != 0*/; oi[ii] = 0; ir[ii].hServer = (OPCHANDLE)idx; } else { err[ii] = E_OUTOFMEMORY; tid[ii] = 0; hr = S_FALSE; UL_NOTICE((LOG_GR("AddItem:add(%ls)(%ls)%x/%x = %s"), loWnul(pItemArray[ii].szItemID), loWnul(pItemArray[ii].szAccessPath), pItemArray[ii].vtRequestedDataType, ir[ii].vtCanonicalDataType, loStrError(err[ii]))); } } else { tid[ii] = 0; hr = S_FALSE; } /* end of for(;;) */ if (act_count) { active_count += act_count; if (Active) { loChangeActivity(&owner->ctxt.cactx, 1, (unsigned)dwCount, tid); last_trid = 0; /* force callback */ } } unlock(); Return: if (oi) { for(ii = 0; ii < dwCount; ii++) if (oi[ii]) delete oi[ii]; loAA_FREE(oi); } if (FAILED(hr)) { UL_INFO((LOG_GRH("AddItems(%lu) = %s"), dwCount, loStrError(hr))); } else { *ppAddResults = ir, ir = 0; if (ppErrors) *ppErrors = err, err = 0; UL_NOTICE((LOG_GRH("AddItems(%lu) = %s"), dwCount, loStrError(hr))); } if (ir) loComFree(ir); if (err) loComFree(err); LO_FINISH(); return hr; }