mCardType = $card_type; $this->mSpecs = []; $this->mOpened = false; } public function card_type() { return $this->mCardType; } public function add_amount($amount) { $this->mSpecs[] = $amount; } public function set_opened($opened) { $this->mOpened = $opened; } public function opened() : bool { return $this->mOpened; } public function total() { $amounts = 0; foreach ($this->mSpecs as $spec) { $amount = rlock::hget_sys_storage($this->mCardType,$spec); $amount = intval($amount); $amount = $amount > 0 ? $amount : 0; $amounts += $amount; } return $amounts; } public function spec_total($spec) { $amount = rlock::hget_sys_storage($this->mCardType,$spec); $amount = intval($amount); return $amount > 0 ? $amount : 0; } } class merchant { private $mMchid; private $mTotalLocks; private $mSpecLocks; public function __construct($mchid) { $this->mMchid = $mchid; $this->mTotalLocks = []; $this->mSpecLocks = []; } public function mchid() { return $this->mMchid; } public function set_total_lock($card_type, $lock_type) { if ($lock_type != rlock::CLOSE) { $this->mTotalLocks[$card_type] = $lock_type; } } public function total($card_type) { if(array_key_exists($card_type,$this->mTotalLocks)) { $amount = rlock::hget_mch_total_storage($this->mMchid,$card_type); $amount = intval($amount); return $amount > 0 ? $amount : 0; } elseif(array_key_exists($card_type, $this->mSpecLocks)) { $specs = $this->mSpecLocks[$card_type]; $amounts = 0; foreach ($specs as $spec) { $amounts += $this->spec_total($card_type,$spec); } return $amounts; } else { return 0; } } public function spec_total($card_type,$spec) { if (array_key_exists($card_type, $this->mSpecLocks) && array_key_exists($spec, $this->mSpecLocks[$card_type])) { $amount = rlock::hget_mch_storage($this->mMchid, $card_type, $spec); $amount = intval($amount); return $amount > 0 ? $amount : 0; } else { return 0; } } public function set_spec_lock($card_type,$spec,$lock_type) { if ($lock_type != rlock::CLOSE) { $this->mSpecLocks[$card_type][$spec] = $lock_type; } } public function has_lock() { return !empty($this->mTotalLocks) || !empty($this->mSpecLocks); } public function lock_type($card_type,$spec) { $total_lock = rlock::CLOSE; if(array_key_exists($card_type,$this->mTotalLocks)) { $total_lock = $this->mTotalLocks[$card_type]; } $spec_lock = rlock::CLOSE; if(array_key_exists($card_type,$this->mSpecLocks) && array_key_exists($spec,$this->mSpecLocks[$card_type])) { $spec_lock = $this->mSpecLocks[$card_type][$spec]; } return [$total_lock,$spec_lock]; } } class rstorage { private $mSystems; private $mMerchants; public function __construct() { $this->mSystems = []; $this->mMerchants = []; } public function load() { $this->mSystems = []; $this->read_sys(); $this->mMerchants = []; $this->read_merchant(); } private function locked($card_type) { if(array_key_exists($card_type,$this->mSystems)) { return true; } else { return false; } } public function allow($mchid,$card_type,$spec) : bool { Log::record("rstorage::allow mchid={$mchid} card_type={$card_type} spec={$spec}",Log::DEBUG); if(!$this->locked($card_type)) { Log::record("rstorage::allow {$card_type} locked",Log::DEBUG); return true; } [$total_lock_type,$spec_lock_type] = $this->merchant_lock_type($mchid,$card_type,$spec); $merchant = $this->mMerchants[$mchid]; Log::record("{$mchid} total_lock:{$total_lock_type} spec_lock:{$spec_lock_type}",Log::DEBUG); if($spec_lock_type == rlock::ASSIGN) { $mch_spec_total = $merchant->spec_total($spec); Log::record("ASSIGN {$mchid} spec_total:{$mch_spec_total}",Log::DEBUG); return $mch_spec_total >= $spec; } elseif($spec_lock_type == rlock::RETAIN) { //是否已经满足 Spec $mch_spec_total = $merchant->spec_total($card_type); Log::record("ASSIGN {$mchid} spec_total:{$mch_spec_total}",Log::DEBUG); if($mch_spec_total >= $spec) return true; } else { //CLOSE情况,其它两种情况优先。 } if ($total_lock_type == rlock::ASSIGN) { $mch_total = $merchant->total($card_type); if($mch_total < $spec) return false; } $system = $this->mSystems[$card_type]; $total = $system->total(); $spec_total = $system->spec_total($spec); $diff_total = $total - $this->lowest_total($mchid,$card_type); $diff_spec_total = $spec_total - $this->lowest_spec_total($mchid,$card_type,$spec); Log::record("mchid:{$mchid} total:{$total} spec_total:{$spec_total} diff_total:{$diff_total} diff_spec_total={$diff_spec_total}",Log::DEBUG); return $diff_spec_total >= $spec && $diff_total >= $spec; } //return [$toal_lock,$spec_lock] private function merchant_lock_type($mchid, $card_type, $spec) { if(!array_key_exists($mchid,$this->mMerchants)) { return [rlock::CLOSE,rlock::CLOSE]; } $merchant = $this->mMerchants[$mchid]; return $merchant->lock_type($card_type, $spec); } //需要为锁定的机构保留的最低总量 private function lowest_total($mchid,$card_type) { $total = 0; foreach ($this->mMerchants as $merchant) { if($mchid != $merchant->mchid()){ $total += $merchant->total($card_type); } } return $total; } //需要为锁定的机构保留的最低总量 private function lowest_spec_total($mchid,$card_type,$spec) { $total = 0; foreach ($this->mMerchants as $merchant) { if($mchid != $merchant->mchid()){ $total += $merchant->spec_total($card_type,$spec); } } return $total; } private function read_sys() { $items = rlock::get_sys(); $parser = function ($key,$val) { $datas = explode('-',$key); $len = count($datas); if($len != 2) return [false,'','','']; $card_type = intval($datas[0]); if($datas[1] == 'open') { return [true,'open',$card_type,boolval($val)]; } elseif(is_numeric($datas[1])) { return [true,'card',$card_type,intval($datas[1])]; } else { return [false,'','','']; } }; $systems = []; foreach ($items as $key => $val) { [$succ,$name,$card_type,$value] = $parser($key,$val); if($succ) { if(array_key_exists($card_type,$systems)) { $system = $systems[$card_type]; } else { $system = new system($card_type); $systems[$card_type] = $system; } if($name == 'open') { $system->set_opened($value); } elseif($name == 'card') { $system->add_amount($value); } } } foreach ($systems as $system) { if($system->opened()) { $card_type = $system->card_type(); $this->mSystems[$card_type] = $system; } } } private function read_merchant() { $parser = function ($key,$val,&$merchants) { $items = explode('-',$key); $len = count($items); if($len < 3) return; $mchid = intval($items[0]); if(array_key_exists($mchid,$merchants)) { $merchant = $merchants[$mchid]; } else { $merchant = new merchant($mchid); $merchants[$mchid] = $merchant; } $card_type = intval($items[1]); if($len == 3) { if($items[2] == 'turn') { $lock_type = intval($val); $merchant->set_total_lock($card_type,$lock_type); } } elseif($len == 4) { $amount = intval($items[2]); if($items[3] == 'turn') { $lock_type = intval($val); $merchant->set_spec_lock($card_type,$amount,$lock_type); } } }; $merchants = []; $items = rlock::get_merchant(); foreach ($items as $key => $val) { $parser($key, $val, $merchants); } foreach ($merchants as $merchant) { if($merchant->has_lock()) { $mchid = $merchant->mchid(); $this->mMerchants[$mchid] = $merchant; } } } }