mkyx Posted September 10, 2013 Report Share Posted September 10, 2013 olá, pessoal, Será que alguém poderia me esclarecer, pois estou ficando de cabelo em pé. Acontece de maneira intermitente, não é sempre. O sistema operacional dos terminais é w7 e w8 e o servidor é 2003server. No módulo do caixa, eu tenho os seguintes arquivos: CAIXA.DBF, PEDIDOS.DBF, PRODUTOS.DBF CORRENTE.DBF, CHEQUES.DBF, CARTOES.DBF, SELLER.DBF, e outros de segundas necessidades. Todos os produtos que passam pela caixa, são gravados imediatamente no arquivo PRODUTOS.DBF, depois que finaliza a venda, grava nos demais. É aí que acontece o inexplicável, os itens que já foram gravados no produtos.dbf, grava o recebimento no arquivo CAIXA.DBF, mas NÃO GRAVA NO ARQUIVOS PEDIDOS.DBF, e grava no corrente.dbf ou no cheques.dbf Às vezes, além de não gravar no pedidos.dbf, tb não grava no caixa.dbf. (varia de vez em quando, esse erro!) O exemplo abaixo, é como eu gravo no produtos.dbf e sigo a mesma sintaxe para gravar nos demais arquivos. = acrescento o registro em branco -> bloqueio o registro -> gravo os dados -> libero a memória -> desbloqueio o registro dbappend dbrlock replace dbcommit dbunlock . . . select arq_prod arq_prod->(dbsetorder(1)) do while .t. arq_prod->(dbappend()) if !arq_prod->(NetErr()) exit endif enddo IF REGLOCK(100) replace arq_prod->data_mov with data_cx,arq_prod->hora_mov with time(),arq_prod->cod_venda with str(nume,13),arq_prod->operador with user000,arq_prod->saldo_atua with sda,arq_prod->custo with pcu0,arq_prod->terminal with str(t_maq,3) replace arq_prod->estado with esta00,arq_prod->codigo with cod,arq_prod->quantidade with qtd,arq_prod->unitario with pru,arq_prod->val_total with pt,ARQ_prod->UNIDADE WITH UNID,arq_prod->cliente with strzero(val(C_CODCLI),6) replace arq_prod->comis_av with cav,arq_prod->comis_ap with cap,arq_prod->vendedor with strZERO(codve,6),ARQ_PROD->CAIXA WITH COD_CX,ARQ_PROD->PERIODO WITH COD_PERI,arq_prod->n_item with str(c_item,3),ARQ_PROD->OBSERVACAO WITH "BALCAO" REPLACE ARQ_PROD->CLA_FISCAL WITH CACA01,ARQ_PROD->SIT_TRIBUT WITH CACA02,ARQ_PROD->POR_ICMS WITH CACA03,ARQ_PROD->POR_IPI WITH CACA04,ARQ_PROD->REDUCAO WITH CACA05,ARQ_PROD->IVA_MVA WITH CACA06,ARQ_PROD->ICMS_SUBS WITH CACA07 REPLACE ARQ_PROD->POR_PIS WITH CACA08,ARQ_PROD->POR_COFINS WITH CACA09,arq_prod->retorno with ret_ent,arq_prod->desc_indiv with des_inv REPLACE ARQ_PROD->RETORNO WITH RET_ENT n_reg:=arq_prod->(recno()) IF ESTA00="D" QT_DEV:=QT_DEV+1 ELSE QT_LEVA:=QT_LEVA+1 ENDIF do while .t. ARQ_PROD->(dbcommit()) if !arq_prod->(NetErr()) exit endif enddo do while .t. ARQ_PROD->(dbunlock()) if !arq_prod->(NetErr()) exit endif enddo . . . return .t. ******************** FUNCTION REGLOCK(TEMPO) // FUNÇÃO BLOQUEADORA DE REGISTROS PARA GRAVAR, ALTERA OU EXCLUIRLOCAL A:=1_dbf:=dbf()DO WHILE A=1 IF (_dbf)->(dbrlock((_dbf)->(RECNO()))) A:=0 LOOP ENDIF tempo:=10000 DO WHILE TEMPO>0 IF (_dbf)->(DBRLOCK((_dbf)->(RECNO()))) TEMPO=-10 ENDIF SYSWAIT(0.3) TEMPO=TEMPO-1 ENDDO A:=0 IF TEMPO>=0 IF MSGYESNO("NÃO CONSEGUI BLOQUEIAR O REGISTRO PARA GRAVAR OS DADOS, TENTA NOVAMENTE?","ATENÇÃO: PROBLEMA NO ARQUIVO!") A:=1 ELSE A:=1000 ENDIF ENDIFENDDOIF A=1000 MSGINFO("DADOS NÃO FORAM GRAVADOS!","PERDA DAS INFORMAÇÃES:") RETURN .F.ENDIFRETURN(.T.) AGORA ALTEREI A FUNÇÃO BLOQUEADORA DE REGISTRO POR ESTA: ( VAMOS VER O QUE VAI DAR...) FUNCTION REGLOCK(TPO)LOCAL tempo:=0_dbf:=dbf()DO WHILE .t. IF (_dbf)->(dbrlock((_dbf)->(RECNO()))) exit ENDIF SYSWAIT(0.3) TEMPO=TEMPO+1 IF TEMPO>100000 TEMPO:=0 MSGINFO("TEM ALGUMA COISA ERRADA COM ESTE ARQUIVO!"+CHR(13)+CHR(13)+"JÁ PASSOU DE 100.000, O NÚMERO DE TENTATIVAS"+CHR(13)+"PARA BLOQUEAR O ARQUIVOS.","ATENÇÃO:") ENDIFENDDORETURN(.T.) OBRIGADO A TODOS QUE PUDEREM ME AJUDAR. FWH 8.02 COMPILADOR Xharbour Quote Link to comment Share on other sites More sharing options...
SAOliveira Posted September 10, 2013 Report Share Posted September 10, 2013 IF (_dbf)->(dbrlock((_dbf)->(RECNO()))) ???????????????? Quote Link to comment Share on other sites More sharing options...
mkyx Posted September 10, 2013 Author Report Share Posted September 10, 2013 ESTA LINHA RETORNA VERDADE, SE BLOQUEOU COM SUCESSO O REGISTRO CORRENTE. Quote Link to comment Share on other sites More sharing options...
kapiaba Posted September 10, 2013 Report Share Posted September 10, 2013 Nunca vi nada parecido nem faz sentido... do while .t. ARQ_PROD->(dbcommit()) if !arq_prod->(NetErr()) exit endif enddo do while .t. ARQ_PROD->(dbunlock()) if !arq_prod->(NetErr()) exit endif enddo Quote Link to comment Share on other sites More sharing options...
kapiaba Posted September 10, 2013 Report Share Posted September 10, 2013 EXEMPLO: IF INCLUSAO ADICIONE(0) ELSE // ALTERACAO TRAVEREG(0) ENDIF REPLACES... DESTRAVA(0) //---------------------------------------------------------------------------// FUNCTION TRAVEREG(TEMPO) // trava o registro. DO WHILE .NOT. REGLOCK(TEMPO) SYSREFRESH() MSGWAIT("AGUARDE ACESSO ARQUIVO","Bloqueando o registro...Aguarde",01) ENDDO RETURN(0) FUNCTION REGLOCK(TEMPO) * TENTA TRAVAR O REGISTRO ATUAL * PAR: 1 - NUMERICO - TEMPO ESPERA LOCAL SEMPRE, TELA IF RLOCK() RETURN(.T.) && BLOQUEADO ENDIF SEMPRE = (TEMPO = 0 ) DO WHILE (SEMPRE .OR. TEMPO > 0 ) .AND. INKEY() <> 27 SYSREFRESH() IF RLOCK() RETURN(.T.) && BLOQUEADO ENDIF SYSWAIT( .5 ) TEMPO = TEMPO-.5 ENDDO RETURN( .F. ) && NAO BLOQUEADO FUNCTION ADICIONE(TEMPO) // adicione um registro DO WHILE .NOT. ADIREG(TEMPO) SYSREFRESH() MSGWAIT("AGUARDE ACESSO ARQUIVO","Adição de novo registro...Aguarde",01) ENDDO RETURN(0) FUNCTION ADIREG(TEMPO) * RETORNA VERDADEIRA SE O REGISTRO FOI APENDADO.O NOVO REG.PASSA A SER O REG.ATUAL BLOQUEADO * PAR: 1-NUMERICO-TEMPO DE ESPERA LOCAL SEMPRE, TELA APPEND BLANK IF .NOT. NETERR() TRAVEREG(0) RETURN(.T.) ENDIF SEMPRE = ( TEMPO = 0 ) DO WHILE( SEMPRE .OR. TEMPO > 0 ) .AND. INKEY() <> 27 SYSREFRESH() APPEND BLANK IF .NOT. NETERR() TRAVEREG(0) RETURN(.T.) ENDIF SYSWAIT(.5) TEMPO = TEMPO - .5 ENDDO RETURN( .F. ) && NAO BLOQUEADO FUNCTION DESTRAVA() // destrava o registro. COMMIT UNLOCK RETURN(NIL) Quote Link to comment Share on other sites More sharing options...
mkyx Posted September 10, 2013 Author Report Share Posted September 10, 2013 Infelizmente a rotina acima não funciona comigo, só dá pau. Falta controle (neterr()) do commit e unlock e reglock, além disso falta os alias dos arquivos Obrigado, por enquanto. Quote Link to comment Share on other sites More sharing options...
kapiaba Posted September 10, 2013 Report Share Posted September 10, 2013 Rapaz, é muito simples: Botao da INCLUSAO: ACTION( lIncuir := .T., SALVAR_DADOS() ) Botao da ALTERAÇÃO ACTION( lIncluir := .F., SALVAR_DADOS() ) FUNCTION SALVAR_DADOS( lIncluir ) IF lIncluir ADICIONE() ELSE TRAVEREG() ENDIF REPLACES... DESTRAVA() RETURN NIL Quote Link to comment Share on other sites More sharing options...
mkyx Posted September 10, 2013 Author Report Share Posted September 10, 2013 Nesse caso como fica os comandos para tratamento dos comandos de gravação??? Quote Link to comment Share on other sites More sharing options...
kapiaba Posted September 10, 2013 Report Share Posted September 10, 2013 comandos para tratamento dos comandos de gravação? Explique... Porfa. Quote Link to comment Share on other sites More sharing options...
SAOliveira Posted September 10, 2013 Report Share Posted September 10, 2013 Amigo faça da forma mais simples que existe. Travar o registro. While(!Seu_Alias->(rLock())) ; EndDo Grave tudo o que precisar. Seu_Alias(dbCommit()) Destrave o registro. Seu_Alias(dbUnlock()) Teste e veja o resultado. Quote Link to comment Share on other sites More sharing options...
Valdir Posted September 10, 2013 Report Share Posted September 10, 2013 Olá... Além das dicas do amigos acima, faça algumas alterações na sua forma de programar : - Dentro do "While" sempre coloque uma "Sysrefresh()", isso irá aliviar o processamento numa rede. - Nunca coloque o "DbCommit()" dentro do "While", isso força a gravação a cada registro inserido e "pode" estar causando lentidão e perda de pacotes em sua rede. - Deixe para colocar o "DbCoomit()" após o "EndDo" As vezes já ocorreu comigo um bug do RddCdx, que não grava as informações após estar usando um arquivo (.Dbf) por muito tempo. Pelo menos é isso que imagino. Para resolver isso, passei a fechar e reabrir os mesmo arquivo durante algumas situações. Um abraço Quote Link to comment Share on other sites More sharing options...
oribeiro Posted September 11, 2013 Report Share Posted September 11, 2013 Não entendi o funcionamento do sysrefresh() em rede. Por favor, explique melhor esse comando. Obrigado, Quote Link to comment Share on other sites More sharing options...
kapiaba Posted September 11, 2013 Report Share Posted September 11, 2013 Não entendi o funcionamento do sysrefresh() em rede. Por favor, explique melhor esse comando. Obrigado, SysRefresh() Atualiza todas as mensagens(operações) pendentes. Sintaxe SysRefresh ( ) --> lRet Retorno lRet(logico) Retorna verdadeiro (.T.), se o processo for realizado com sucesso; caso contrário, falso (.F.). Exemplos SysRefresh() http://www.masteradvpl.com.br/index.php/forum/2-advpl/1924-enchoice http://dc466.4shared.com/doc/Kih-ePcl/preview.html Quote Link to comment Share on other sites More sharing options...
oribeiro Posted September 11, 2013 Report Share Posted September 11, 2013 Parece que o objetivo é fazer com que o Windows não dê a impressão de que está congelado enquanto se executa um processamento longo. Apenas não entendi como isso pode aliviar o processamento em rede. Refresh do sistemaAo realizar processos que ocupem uma grande quantidade de tempo, como por exemplo rastrear uma informação em uma grande base de dados, devemos levar em conta que o Windows não poderá atualizar todo o sistema até que o processo termine. Por exemplo, se existisse um relógio no vídeo, este ficaria completamente parado até que a busca terminasse. Para resolver este problema, o FiveWin incorpora uma função “SysRefresh()” que pode ser chamada tantas vezes quantas forem necessárias e que permitirá atualizar o sistema ao executar processos longos: DO WHILE !Eof() .... SysRefresh() ... SKIPENDDO Quote Link to comment Share on other sites More sharing options...
Erciley Junior Posted September 11, 2013 Report Share Posted September 11, 2013 Não vi nada demais nem de errado no código dele, apesar de eu não fazer desta forma Valdir, o DBCOMMIT dele está dentro de um while, mas se NETERR não retornar "erro", é feito um EXIT, ou seja, isso não está pesando nada, além de achar desnecessário colocar isso dentro do WHILE, já q teoricamente só será executado uma única vez, digo o mesmo referente ao UNLOCK..... sei lá, acho q o erro não está aí ^^ Quote Link to comment Share on other sites More sharing options...
Jorge Andrade Posted September 11, 2013 Report Share Posted September 11, 2013 Olá... Além das dicas do amigos acima, faça algumas alterações na sua forma de programar : - Dentro do "While" sempre coloque uma "Sysrefresh()", isso irá aliviar o processamento numa rede. - Nunca coloque o "DbCommit()" dentro do "While", isso força a gravação a cada registro inserido e "pode" estar causando lentidão e perda de pacotes em sua rede. - Deixe para colocar o "DbCoomit()" após o "EndDo" As vezes já ocorreu comigo um bug do RddCdx, que não grava as informações após estar usando um arquivo (.Dbf) por muito tempo. Pelo menos é isso que imagino. Para resolver isso, passei a fechar e reabrir os mesmo arquivo durante algumas situações. Um abraço Mkyx, Não vou opinar sobre o problema citado, pq todas as informações citadas pelos companheiros no sentido de esclarecer tal questão estão corretas, contudo, o Valdir tem razão quando destaca a descarga do BUFFER em disco a cada registro gravado. É contra-producente o tempo que vc perde descarregando um registro por vez em disco, mesmo que o tempo seja ínfimo, ainda assim na soma geral do tempo executado registro a registro vc acaba perdendo, pq com certeza em algum momento vc estará concorrendo com outros aplicativos da rede, então o melhor é descarregar em blocos Vc pode criar uma função que faça esta gravação a cada X registros, seria a mesma coisa que o sistema faz quando BUFFER está cheio no processo de SWAP ou então coloque o COMMIT fora do WHILE como citou o Valdir para que seja executado após o final total do processamento do arquivo envolvido. []s, Quote Link to comment Share on other sites More sharing options...
kapiaba Posted September 11, 2013 Report Share Posted September 11, 2013 Ineteressante também, é que notamos aqui, que com WINDOWS XP y WINDOWS SERVER, o consumo de memória é exaustivo, optamos então por usar o comando: HB_GCALL( .T. ) // na entrada e saida do programa e nos processamentos, HB_GCALL( .F. ) // só limpa a memória se tiver Basuras/Lixo; abs, Quote Link to comment Share on other sites More sharing options...
Valdir Posted September 11, 2013 Report Share Posted September 11, 2013 Parece que o objetivo é fazer com que o Windows não dê a impressão de que está congelado enquanto se executa um processamento longo. Apenas não entendi como isso pode aliviar o processamento em rede.Refresh do sistemaAo realizar processos que ocupem uma grande quantidade de tempo, como por exemplo rastrear uma informação em uma grande base de dados, devemos levar em conta que o Windows não poderá atualizar todo o sistema até que o processo termine. Por exemplo, se existisse um relógio no vídeo, este ficaria completamente parado até que a busca terminasse. Para resolver este problema, o FiveWin incorpora uma função “SysRefresh()” que pode ser chamada tantas vezes quantas forem necessárias e que permitirá atualizar o sistema ao executar processos longos: DO WHILE !Eof() .... SysRefresh() ... SKIP ENDDO Olá Oscar... Blz ? Como você mesmo postou acima, a Fivewin utiliza o comando Sysrefresh() para descarregar o buffer durante um processamento. Essa é uma caracteristica do Windows. Tive problemas com isso num cliente. No Servidor estevam instalados além do meu Sistema, alguns aplicativos e o Autocad Dai meu caro... como dizia meu amigo Kapiaba... é o cão chupando manga. Passei a usar o Sysrefresh() fora do while e a perda de pacotes cessaram. Para resolver de uma vez, foi necessário instalar o meu Sistema em outro Servidor. abração. Não vi nada demais nem de errado no código dele, apesar de eu não fazer desta forma Valdir, o DBCOMMIT dele está dentro de um while, mas se NETERR não retornar "erro", é feito um EXIT, ou seja, isso não está pesando nada, além de achar desnecessário colocar isso dentro do WHILE, já q teoricamente só será executado uma única vez, digo o mesmo referente ao UNLOCK..... sei lá, acho q o erro não está aí ^^ Olá Erciley... Blz ? Faça um teste... cronometre a gravação de 10.000 registros através do while sem e depois com o o refresh()... isso numa rede..oK ? Veja a diferença de performance. abração. Quote Link to comment Share on other sites More sharing options...
oribeiro Posted September 12, 2013 Report Share Posted September 12, 2013 Entendi! Muito obrigado pela explicação. Quote Link to comment Share on other sites More sharing options...
Erciley Junior Posted September 12, 2013 Report Share Posted September 12, 2013 Olá Erciley... Blz ? Faça um teste... cronometre a gravação de 10.000 registros através do while sem e depois com o o refresh()... isso numa rede..oK ? Veja a diferença de performance. abração. Olá Valdir, bem e você? ^^ Bom, em nenhum momento eu disse que este procedimento que você acabou de citar, não deixe o processo lento, o que eu disse, é que o processamento postado pelo mkyx no "post nº1" NÃO faz isso que você citou, por isso não vejo problemas no código dele em relação ao DBCOMMIT e ao DBUNLOCK (leia atentamente o código dele, o DBCOMMIT só será executado uma única vez, apesar de ele ter deixado esse DBCOMMIT em um WHILE). É claro que nessa situação que você descreveu, tenha uma diferença enorme de performance, já constatei isso, mas não é o caso do mkyx. Leia o código dele "identado" select arq_prod arq_prod->(dbsetorder(1)) do while .t. arq_prod->(dbappend()) if !arq_prod->(NetErr()) exit endif enddo //BLOQUEOU O REGISTRO IF REGLOCK(100) replace arq_prod->data_mov with data_cx REPLACE arq_prod->hora_mov with time() REPLACE arq_prod->cod_venda with str(nume,13) REPLACE arq_prod->operador with user000 REPLACE arq_prod->saldo_atua with sda REPLACE arq_prod->custo with pcu0 REPLACE arq_prod->terminal with str(t_maq,3) replace arq_prod->estado with esta00 REPLACE arq_prod->codigo with cod REPLACE arq_prod->quantidade with qtd REPLACE arq_prod->unitario with pru REPLACE arq_prod->val_total with pt REPLACE ARQ_prod->UNIDADE WITH UNID REPLACE arq_prod->cliente with strzero(val(C_CODCLI),6) replace arq_prod->comis_av with cav REPLACE arq_prod->comis_ap with cap REPLACE arq_prod->vendedor with strZERO(codve,6) REPLACE ARQ_PROD->CAIXA WITH COD_CX REPLACE ARQ_PROD->PERIODO WITH COD_PERI REPLACE arq_prod->n_item with str(c_item,3) REPLACE ARQ_PROD->OBSERVACAO WITH "BALCAO" REPLACE ARQ_PROD->CLA_FISCAL WITH CACA01 REPLACE ARQ_PROD->SIT_TRIBUT WITH CACA02 REPLACE ARQ_PROD->POR_ICMS WITH CACA03 REPLACE ARQ_PROD->POR_IPI WITH CACA04 REPLACE ARQ_PROD->REDUCAO WITH CACA05 REPLACE ARQ_PROD->IVA_MVA WITH CACA06 REPLACE ARQ_PROD->ICMS_SUBS WITH CACA07 REPLACE ARQ_PROD->POR_PIS WITH CACA08 REPLACE ARQ_PROD->POR_COFINS WITH CACA09 REPLACE arq_prod->retorno with ret_ent REPLACE arq_prod->desc_indiv with des_inv REPLACE ARQ_PROD->RETORNO WITH RET_ENT n_reg:=arq_prod->(recno()) IF ESTA00="D" QT_DEV:=QT_DEV+1 ELSE QT_LEVA:=QT_LEVA+1 ENDIF do while .t. //SE NÃO RETORNAR ERRO = NETERR FALSE, EXECUTE "EXIT" //QUAL A NECESSIDADE DISSO ESTAR EM UM WHILE? -----> NENHUMA AO MEU VER ARQ_PROD->(dbcommit()) if !arq_prod->(NetErr()) exit endif enddo do while .t. //SE NÃO RETORNAR ERRO = NETERR FALSE, EXECUTE "EXIT" //QUAL A NECESSIDADE DISSO ESTAR EM UM WHILE? -----> NENHUMA AO MEU VER ARQ_PROD->(dbunlock()) if !arq_prod->(NetErr()) exit endif enddo ENDIF Quote Link to comment Share on other sites More sharing options...
Valdir Posted September 12, 2013 Report Share Posted September 12, 2013 Olá Erciley... Ok... entendi. A minha dúvida é se está ou não sendo gravado mais de um registro. Não consegui visualizar isso no seu exemplo e muito menos no dele... heheheheheheheeh... abração. Quote Link to comment Share on other sites More sharing options...
Erciley Junior Posted September 12, 2013 Report Share Posted September 12, 2013 Pelo postado é apenas um registro..... mas é isso que você falou, tá muito bagunçado ^^ Se eu pego esse código eu ia xingar o povo daki, kkkkkkkkkkkkk (brincadeira mkyt --- ou não ^^) Abraço. Quote Link to comment Share on other sites More sharing options...
syspel Posted September 13, 2013 Report Share Posted September 13, 2013 ola pessoal bom dia tambem estou com o mesmo problema uma determinda hora ele nao grava tambem porque o arquivo e grande tem mais 300 notas isto e um defeito do xharbour ou index cdx ? xharbour 1.21 bcc555 dbf paulo syspel Quote Link to comment Share on other sites More sharing options...
Erciley Junior Posted September 13, 2013 Report Share Posted September 13, 2013 FW2.6 + xHarbour 0.99.5 e FW8.01 + xHarbour 1.1 não possuem esse problema, pelo menos nunca tivemos problema com isso, mesmo trabalhando com tabelas (DBF) com mais de 670 mil registros. Quote Link to comment Share on other sites More sharing options...
mkyx Posted September 16, 2013 Author Report Share Posted September 16, 2013 Coloquei um monte de controle nos dbappend(), dbcommit(), dbunlock() e sysrefresh() junto a estes comandos, e parece que estão sumindo os problemas com Windows 2003 server, agora só falta trocar as aberturas dos arquivos de USE NOMEDOARQUIVO por dbusearea() Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.