Exemplo n.º 1
0
 def Stop(self):
     err = None
     srcStatus = self.__status
     dstStatus = SCHED_STATUS_STOPPING
     try:
         print(
             Logger(time.strftime(
                 LOG_TIME_FOEMAT,
                 time.localtime())).Info('Stop scheduler ...'))
         print(
             Logger(time.strftime(
                 LOG_TIME_FOEMAT,
                 time.localtime())).Info('Check scheduler status...'))
         err = CheckStatus(srcStatus, dstStatus)
         if err is not None:
             return err
         self.SetStatus(dstStatus)
         self.__bankerBufferPool.Close()
         self.__signBufferPool.Close()
         self.__broadcastBufferPool.Close()
         self.__stakingBufferPool.Close()
         self.__errorBufferPool.Close()
         self.__distributionBufferPool.Close()
         print(
             Logger(time.strftime(
                 LOG_TIME_FOEMAT,
                 time.localtime())).Info('Scheduler has been stopped.'))
         return err
     finally:
         if err is not None:
             self.SetStatus(srcStatus)
         else:
             self.SetStatus(SCHED_STATUS_STOPPED)
Exemplo n.º 2
0
 def RegisterModules(self, modules):
     for banker in modules.Bankers:
         if banker is None:
             continue
         ok, err = self.__registrar.Register(banker)
         if err is not None:
             return err
         if ok is False:
             continue
     print(
         Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Info(
             'banker modules register successfully!'))
     for signer in modules.Signers:
         if signer is None:
             continue
         ok, err = self.__registrar.Register(signer)
         if err is not None:
             return err
         if ok is False:
             continue
     print(
         Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Info(
             'signer modules register successfully!'))
     for broadcaster in modules.Broadcasters:
         if broadcaster is None:
             continue
         ok, err = self.__registrar.Register(broadcaster)
         if err is not None:
             return err
         if ok is False:
             continue
     print(
         Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Info(
             'broadcaster modules register successfully!'))
     for staking in modules.Stakings:
         if staking is None:
             continue
         ok, err = self.__registrar.Register(staking)
         if err is not None:
             return err
         if ok is False:
             continue
     print(
         Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Info(
             'staking modules register successfully!'))
     for distributor in modules.Distributors:
         if distributor is None:
             continue
         ok, err = self.__registrar.Register(distributor)
         if err is not None:
             return err
         if ok is False:
             continue
     print(
         Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Info(
             'distribution modules register successfully!'))
Exemplo n.º 3
0
def checkTx(body):
    tx = json.loads(body)
    if tx is None:
        return None, ParseError('checkTx: json.loads: json parse error')
    if tx.get('txhash') is None:
        return None, CheckTxError('checkTx: txhash is not found')
    try:
        print(
            Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Info(
                'current tx hash is %s' % (tx['txhash'])))
        resp = http.request(HTTP_METHOD_GET, TX_HASH_URL % (tx['txhash']))
        if resp and resp.status == 200:
            if tx.get('logs') is not None and tx['logs'][0].get(
                    'success') is not None and (
                        tx['logs'][0])['success'] is True:
                return resp.data.decode('utf-8'), None
            else:
                return None, None
        elif resp and resp.status == 404:
            return None, CheckTxError('checkTx: txhash is invalid')
        elif resp and resp.status == 500:
            return None, CheckTxError('Internal Server Error')
        return None, CheckTxError('unknown error')
    except Exception as e:
        return None, CheckTxError(e)
Exemplo n.º 4
0
 def func(body):
     err = stakingBufferPool.Put(body)
     if err is not None:
         print(
             Logger(time.strftime(
                 LOG_TIME_FOEMAT,
                 time.localtime())).Warn('the delegate pool was closed'))
Exemplo n.º 5
0
 def func(sendSignData):
     err = signBufferPool.Put(sendSignData)
     if err is not None:
         print(
             Logger(time.strftime(
                 LOG_TIME_FOEMAT,
                 time.localtime())).Warn('the sign pool was closed'))
Exemplo n.º 6
0
 def func(body):
     err = broadcastBufferPool.Put(body)
     if err is not None:
         print(
             Logger(time.strftime(
                 LOG_TIME_FOEMAT,
                 time.localtime())).Warn('the broadcast pool was closed'))
Exemplo n.º 7
0
 def func(txerError):
     err = errBufPool.Put(txerError)
     if err is not None:
         print(
             Logger(time.strftime(
                 LOG_TIME_FOEMAT,
                 time.localtime())).Warn('the error pool was closed'))
Exemplo n.º 8
0
 def func(data):
     err = bankerBufferPool.Put(data)
     if err is not None:
         print(
             Logger(time.strftime(
                 LOG_TIME_FOEMAT,
                 time.localtime())).Warn('the bank pool was closed'))
Exemplo n.º 9
0
 def Start(self, auth):
     err = None
     srcStatus = self.__status
     dstStatus = SCHED_STATUS_STARTING
     try:
         print(
             Logger(time.strftime(
                 LOG_TIME_FOEMAT,
                 time.localtime())).Info('Start scheduler ...'))
         print(
             Logger(time.strftime(
                 LOG_TIME_FOEMAT,
                 time.localtime())).Info('Check scheduler status...'))
         err = CheckStatus(srcStatus, dstStatus)
         if err is not None:
             return err
         self.SetStatus(dstStatus)
         print(
             Logger(time.strftime(
                 LOG_TIME_FOEMAT,
                 time.localtime())).Info('Check auth module...'))
         if isinstance(auth, Auth) is False:
             return err
         print(
             Logger(time.strftime(
                 LOG_TIME_FOEMAT,
                 time.localtime())).Info('Auth module is valid...'))
         self.__auth = auth
         err = self.__checkBufferPool()
         if err is not None:
             return err
         self.randomTx(threading.currentThread())
         self.transfer(threading.currentThread())
         self.sign(threading.currentThread())
         self.broadcast(threading.currentThread())
         self.staking(threading.currentThread())
         self.distribution(threading.currentThread())
         print(
             Logger(time.strftime(
                 LOG_TIME_FOEMAT,
                 time.localtime())).Info('Scheduler has been started.'))
         return err
     finally:
         if err is not None:
             self.SetStatus(srcStatus)
         else:
             self.SetStatus(SCHED_STATUS_STARTED)
Exemplo n.º 10
0
 def Init(self, modulesArgs, poolArgs, node):
     err = None
     srcStatus = self.__status
     dstStatus = SCHED_STATUS_INITIALIZING
     try:
         print(
             Logger(time.strftime(
                 LOG_TIME_FOEMAT,
                 time.localtime())).Info('Initialized scheduler ...'))
         print(
             Logger(time.strftime(
                 LOG_TIME_FOEMAT,
                 time.localtime())).Info('check scheduler status...'))
         err = CheckStatus(srcStatus, dstStatus)
         if err is not None:
             return err
         self.SetStatus(dstStatus)
         err = modulesArgs.Check()
         if err is not None:
             return err
         print(
             Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Info(
                 'scheduler is being initialing...'))
         if self.__registrar is None:
             self.__registrar = Registrar()
         else:
             self.__registrar.Clear()
         self.__initBufferPool(poolArgs)
         err = self.RegisterModules(modulesArgs)
         if err is not None:
             return err
         if node is not None:
             self.__node = node
         print(
             Logger(time.strftime(
                 LOG_TIME_FOEMAT,
                 time.localtime())).Info('scheduler has been initialized'))
         return err
     finally:
         if err is not None:
             self.SetStatus(srcStatus)
         else:
             self.SetStatus(SCHED_STATUS_INITIALIZED)
Exemplo n.º 11
0
def main():
    scheduler = Scheduler()
    poolArgs = PoolArgs(50, 10, 50, 10, 50, 10, 50, 10, 50, 10, 50, 100)
    bankers, err = GetBankers(1)
    if err is not None:
        print(
            Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Warn(
                'An error occurs when building banker: %s' % (err)))
    signers, err = GetSigners(1)
    if err is not None:
        print(
            Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Warn(
                'An error occurs when building signer: %s' % (err)))
    broadcasters, err = GetBroadcasters(1)
    if err is not None:
        print(
            Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Warn(
                'An error occurs when building broadcaster: %s' % (err)))
    stakingers, err = GetStakingers(1)
    if err is not None:
        print(
            Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Warn(
                'An error occurs when building stakinger: %s' % (err)))
    distributors, err = GetDistributors(1)
    if err is not None:
        print(
            Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Warn(
                'An error occurs when building distributor: %s' % (err)))
    moduleArgs = ModuleArgs(bankers, signers, broadcasters, stakingers,
                            distributors)

    err = scheduler.Init(moduleArgs, poolArgs, HSN_NODE_RPC_SERVER)
    if err is not None:
        print(
            Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Warn(
                'An error occurs when initializing scheduler: %s' % (err)))

    # 收集本地账户并验证
    accountList = CollectAccount()
    print(
        Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Info(
            'have %d account located at local' % (len(accountList))))
    auth = Auth('AUTH|100', 0)
    auth.Add(accountList)
    # 获取验证者
    validators = CollectValidators()
    auth.AddValidatorSet(validators)
    err = scheduler.Start(auth)
    if err is not None:
        print(
            Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Warn(
                'An error occurs when starting scheduler: %s' % (err)))
Exemplo n.º 12
0
 def func():
     while True:
         print(
             Logger(time.strftime(LOG_TIME_FOEMAT,
                                  time.localtime())).Info(
                                      'current threading is %s' %
                                      (threading.currentThread())))
         print(
             Logger(time.strftime(LOG_TIME_FOEMAT,
                                  time.localtime())).Info(
                                      'scheduler thread %s is alive' %
                                      (schedulerThread.getName())))
         broadcastData, err = self.__broadcastBufferPool.Get()
         if err is not None:
             print(
                 Logger(time.strftime(
                     LOG_TIME_FOEMAT, time.localtime())).Warn(
                         'the broadcast pool is closed, break'))
             break
         self.broadcastOne(broadcastData)
Exemplo n.º 13
0
 def func(errorBufPool, errorQueue):
     while True:
         print(
             Logger(time.strftime(LOG_TIME_FOEMAT,
                                  time.localtime())).Info(
                                      'current threading is %s' %
                                      (threading.currentThread())))
         print(
             Logger(time.strftime(LOG_TIME_FOEMAT,
                                  time.localtime())).Info(
                                      'scheduler thread %s is alive' %
                                      (schedulerThread.getName())))
         data, err = self.__errorBufferPool.Get()
         if err is not None:
             print(
                 Logger(time.strftime(
                     LOG_TIME_FOEMAT, time.localtime())).Warn(
                         'the error pool is closed, break'))
             break
         errorQueue.put_nowait(data)
Exemplo n.º 14
0
 def func():
     while True:
         print(
             Logger(time.strftime(LOG_TIME_FOEMAT,
                                  time.localtime())).Info(
                                      'current threading is %s' %
                                      (threading.currentThread())))
         print(
             Logger(time.strftime(LOG_TIME_FOEMAT,
                                  time.localtime())).Info(
                                      'scheduler thread %s is alive' %
                                      (schedulerThread.getName())))
         stakingData, err = self.__stakingBufferPool.Get()
         if err is not None:
             print(
                 Logger(time.strftime(
                     LOG_TIME_FOEMAT, time.localtime())).Warn(
                         'the stakinger pool is closed, break'))
             break
         # include delegate, redelegate and unbondingDelegate
         if stakingData and stakingData.getType() == 'delegate':
             self.delegateOne(stakingData.getData())
Exemplo n.º 15
0
 def func():
     while True:
         print(
             Logger(time.strftime(LOG_TIME_FOEMAT,
                                  time.localtime())).Info(
                                      'current threading is %s' %
                                      (threading.currentThread())))
         print(
             Logger(time.strftime(LOG_TIME_FOEMAT,
                                  time.localtime())).Info(
                                      'scheduler thread %s is alive' %
                                      (schedulerThread.getName())))
         distributionData, err = self.__distributionBufferPool.Get()
         if err is not None:
             print(
                 Logger(time.strftime(
                     LOG_TIME_FOEMAT, time.localtime())).Warn(
                         'the distribution pool is closed, break'))
             break
         # include withdrawDelegatorOneReward, withdrawDelegatorAllReward
         if distributionData and distributionData.getType(
         ) == 'withdrawDelegatorOneReward':
             self.withdrawDelegatorOneReward(distributionData.getData())
Exemplo n.º 16
0
 def func():
     while True:
         print(
             Logger(time.strftime(LOG_TIME_FOEMAT,
                                  time.localtime())).Info(
                                      'current threading is %s' %
                                      (threading.currentThread())))
         print(
             Logger(time.strftime(LOG_TIME_FOEMAT,
                                  time.localtime())).Info(
                                      'scheduler thread %s is alive' %
                                      (schedulerThread.getName())))
         accountList = list(self.__auth.GetAccountDict().values())
         validatorList = list(self.__auth.GetValidatorDict().values())
         seed = random.randint(0, 10)
         if seed % 2 == 0:
             self.randomSendTx(accountList)
         elif seed % 3 == 0:
             self.randomWithdrawDelegatorOneRewardTx(
                 accountList, validatorList)
         else:
             self.randomDelegateTx(accountList, validatorList)
         time.sleep(random.randint(1, 10))
Exemplo n.º 17
0
def sendBank(data, bankerBufferPool):
    if data is None or bankerBufferPool is None or bankerBufferPool.Closed():
        return False
    print(
        Logger(time.strftime(LOG_TIME_FOEMAT,
                             time.localtime())).Info('enter send t banker'))

    def func(data):
        err = bankerBufferPool.Put(data)
        if err is not None:
            print(
                Logger(time.strftime(
                    LOG_TIME_FOEMAT,
                    time.localtime())).Warn('the bank pool was closed'))

    thread = threading.Thread(target=func(data))
    thread.start()
Exemplo n.º 18
0
 def func(srcAccount, body):
     delay = 1
     while True:
         time.sleep(delay)
         txResult, err = checkTx(body)
         if txResult is not None:
             with open(BROADCASTED_TX_DIR + '/' + srcAccount.getAddress() +
                       '|' + str(now_timestamp()) + '.json',
                       'w',
                       encoding='utf-8') as broadcastedTxFile:
                 if broadcastedTxFile.writable():
                     broadcastedTxFile.write(txResult)
                     return
         if err is not None:
             if delay == 6:
                 break
             else:
                 delay += 1
                 print(
                     Logger(time.strftime(
                         LOG_TIME_FOEMAT, time.localtime())).Warn(
                             'checkTx recycle : %s' % (err.msg)))
Exemplo n.º 19
0
 def withdrawDelegatorOneReward(self, withdrawRewardData):
     if withdrawRewardData is None or isinstance(
             withdrawRewardData, WithdrawDelegatorOneRewardArgs
     ) is False or withdrawRewardData.Check() is not None:
         return
     distributor, err = self.__registrar.Get(TYPE_DISTRIBUTION)
     if distributor is None or err is not None:
         errMsg = 'could not get a distributor: %s' % (err)
         sendError(TxerError(ERROR_DISTRIBUTION, errMsg), '',
                   self.__errorBufferPool)
         distributionArgs = DistributionArgs('withdrawDelegatorOneReward',
                                             withdrawRewardData)
         sendDistribution(distributionArgs)
         return
     ok = isinstance(distributor, Distributor)
     if ok is False:
         errMsg = 'incorrect distributor type: ID: %s' % (distributor.ID())
         sendError(TxerError(ERROR_DISTRIBUTION, errMsg), distributor.ID(),
                   self.__errorBufferPool)
         distributionArgs = DistributionArgs('withdrawDelegatorOneReward',
                                             withdrawRewardData)
         sendDistribution(distributionArgs)
         return
     distributionTxJsonFilePath, err = distributor.WithdrawDelegatorOneReward(
         withdrawRewardData.delegator, withdrawRewardData.validator,
         withdrawRewardData.fees, withdrawRewardData.gas,
         withdrawRewardData.gasAdjust)
     if distributionTxJsonFilePath is not None:
         sendSignData = SendSignArgs(withdrawRewardData.delegator,
                                     distributionTxJsonFilePath,
                                     self.__node)
         sendSign(sendSignData, self.__signBufferPool)
     if err is not None:
         print(
             Logger(time.strftime(LOG_TIME_FOEMAT,
                                  time.localtime())).Warn(err.msg))
         sendError(err, distributor.ID(), self.__errorBufferPool)
Exemplo n.º 20
0
 def func(body):
     err = distributionBufferPool.Put(body)
     if err is not None:
         print(
             Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Warn(
                 'the distribution pool was closed'))
Exemplo n.º 21
0
def CheckStatus(srcStatus, dstStatus):
    lock = RWLock()
    lock.acquire_write()
    try:
        # 情况一
        if srcStatus == SCHED_STATUS_INITIALIZING:
            print(
                Logger(time.strftime(
                    LOG_TIME_FOEMAT,
                    time.localtime())).Warn('scheduler is initialing...'))
            return CheckStatusError(
                Logger(time.strftime(
                    LOG_TIME_FOEMAT,
                    time.localtime())).Warn('scheduler is initialing...'))
        elif srcStatus == SCHED_STATUS_STARTING:
            print(
                Logger(time.strftime(
                    LOG_TIME_FOEMAT,
                    time.localtime())).Warn('scheduler is starting...'))
            return CheckStatusError(
                Logger(time.strftime(
                    LOG_TIME_FOEMAT,
                    time.localtime())).Warn('scheduler is starting...'))
        elif srcStatus == SCHED_STATUS_STOPPING:
            print(
                Logger(time.strftime(
                    LOG_TIME_FOEMAT,
                    time.localtime())).Warn('scheduler is stopping...'))
            return CheckStatusError(
                Logger(time.strftime(
                    LOG_TIME_FOEMAT,
                    time.localtime())).Warn('scheduler is stopping...'))
        # 情况二
        elif srcStatus == SCHED_STATUS_UNINITIALIZED and (
                dstStatus == SCHED_STATUS_STARTING
                or dstStatus == SCHED_STATUS_STOPPING):
            print(
                Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Warn(
                    'scheduler haven\'t been initialized!'))
            return CheckStatusError(
                Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Warn(
                    'scheduler haven\'t been initialized!'))
        # 情况三
        elif dstStatus == SCHED_STATUS_INITIALIZING:
            if srcStatus == SCHED_STATUS_STARTED:
                print(
                    Logger(time.strftime(
                        LOG_TIME_FOEMAT,
                        time.localtime())).Warn('scheduler has been started!'))
                return CheckStatusError(
                    Logger(time.strftime(
                        LOG_TIME_FOEMAT,
                        time.localtime())).Warn('scheduler has been started!'))
        elif dstStatus == SCHED_STATUS_STARTING:
            if srcStatus == SCHED_STATUS_UNINITIALIZED:
                print(
                    Logger(time.strftime(
                        LOG_TIME_FOEMAT, time.localtime())).Warn(
                            'scheduler is being uninitialized!'))
                return CheckStatusError(
                    Logger(time.strftime(
                        LOG_TIME_FOEMAT, time.localtime())).Warn(
                            'scheduler is being uninitialized!'))
            elif srcStatus == SCHED_STATUS_STARTED:
                print(
                    Logger(time.strftime(
                        LOG_TIME_FOEMAT,
                        time.localtime())).Warn('scheduler has been started!'))
                return CheckStatusError(
                    Logger(time.strftime(
                        LOG_TIME_FOEMAT,
                        time.localtime())).Warn('scheduler has been started!'))
        elif dstStatus == SCHED_STATUS_STOPPING:
            if srcStatus != SCHED_STATUS_STARTED:
                print(
                    Logger(time.strftime(
                        LOG_TIME_FOEMAT,
                        time.localtime())).Warn('scheduler haven\'t start!'))
                return CheckStatusError(
                    Logger(time.strftime(
                        LOG_TIME_FOEMAT,
                        time.localtime())).Warn('scheduler haven\'t start!'))
        else:
            print(
                Logger(time.strftime(LOG_TIME_FOEMAT,
                                     time.localtime())).Warn('unknown status'))
            return CheckStatusError(
                Logger(time.strftime(LOG_TIME_FOEMAT,
                                     time.localtime())).Warn('unknown status'))
        return None
    finally:
        if lock:
            lock.release()
Exemplo n.º 22
0
 def __initBufferPool(self, poolArgs):
     # init banker buffer pool
     if self.__bankerBufferPool is not None and self.__bankerBufferPool.Closed(
     ) is False:
         self.__bankerBufferPool.Close()
     self.__bankerBufferPool = Pool(poolArgs.BankerBufCap,
                                    poolArgs.BankerMaxBufNumber)
     print(
         Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Info(
             'banker buffer pool built by bufCap = %s and maxBufNumber = %s'
             % (poolArgs.BankerBufCap, poolArgs.BankerMaxBufNumber)))
     # init signer buffer pool
     if self.__signBufferPool is not None and self.__signBufferPool.Closed(
     ) is False:
         self.__signBufferPool.Close()
     self.__signBufferPool = Pool(poolArgs.SignerBufCap,
                                  poolArgs.SignerBufMaxNumber)
     print(
         Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Info(
             'signer buffer pool built by bufCap = %s and maxBufNumber = %s'
             % (poolArgs.SignerBufCap, poolArgs.SignerBufMaxNumber)))
     # init broadcaster buffer pool
     if self.__broadcastBufferPool is not None and self.__broadcastBufferPool.Closed(
     ) is False:
         self.__broadcastBufferPool.Close()
     self.__broadcastBufferPool = Pool(poolArgs.BroadcasterBufCap,
                                       poolArgs.BroadcasterMaxNumber)
     print(
         Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Info(
             'broadcaster buffer pool built by bufCap = %s and maxBufNumber = %s'
             % (poolArgs.BroadcasterBufCap, poolArgs.BroadcasterMaxNumber)))
     # init staking buffer pool
     if self.__stakingBufferPool is not None and self.__stakingBufferPool.Closed(
     ) is False:
         self.__stakingBufferPool.Close()
     self.__stakingBufferPool = Pool(poolArgs.StakingBufCap,
                                     poolArgs.StakingMaxNumber)
     print(
         Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Info(
             'staking buffer pool built by bufCap = %s and maxBufNumber = %s'
             % (poolArgs.StakingBufCap, poolArgs.StakingMaxNumber)))
     # init distribution buffer pool
     if self.__distributionBufferPool is not None and self.__distributionBufferPool.Closed(
     ) is False:
         self.__distributionBufferPool.Close()
     self.__distributionBufferPool = Pool(poolArgs.DistributionBufCap,
                                          poolArgs.DistributionMaxNumber)
     print(
         Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Info(
             'distribution buffer pool built by bufCap = %s and maxBufNumber = %s'
             %
             (poolArgs.DistributionBufCap, poolArgs.DistributionMaxNumber)))
     # init error buffer pool
     if self.__errorBufferPool is not None and self.__errorBufferPool.Closed(
     ) is False:
         self.__errorBufferPool.Close()
     self.__errorBufferPool = Pool(poolArgs.BroadcasterBufCap,
                                   poolArgs.BroadcasterMaxNumber)
     print(
         Logger(time.strftime(LOG_TIME_FOEMAT, time.localtime())).Info(
             'error buffer pool built by bufCap = %s and maxBufNumber = %s'
             % (poolArgs.ErrorBufCap, poolArgs.ErrorMaxNumber)))