Árvore de páginas

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.

Pagetitle
Tabelas Temporarias Compartilhadas - Exemplo de Fila
Tabelas Temporarias Compartilhadas - Exemplo de Fila

No exemplo abaixo, imagine que criamos uma função de Hashing "pesada" ... onde para determinar um Hash de uma determinada palavra, são necessárias mais de 256 mil calculos por palavra. E temos uma lista de palavras para calcular o "SuperHash". Usando tabelas temporárias compartilhadas, conseguimos criar uma fila para alguns jobs (a gosto do freguês ou da capacidade da máquina) para cada job processar uma palavra. 

Bloco de código

/* Exemplo de criação de fila de processamento */ 

user function MyHash()
	Local cTable
	Local aStru := {}
	Local nI, nTimer
	Local nJobs := 3

	aadd(aStru,{"PALAVRA","C",20,0})
	aadd(aStru,{"JOBID","C",2,0})
	aadd(aStru,{"HEXHASH","C",40,0})
	aadd(aStru,{"TEMPO","N",12,3})
	
	tclink()

	DbCreate("%SHTMP%",aStru,"TOPCONN")
	cTable := tcconfig("GETTEMPNAME=%SHTMP%")

	// 7 palavras para processamento
	aPalavras := {}
	aadd(aPalavras,"ARQUIPELAGO")
	aadd(aPalavras,"AUTOMOVEL")
	aadd(aPalavras,"ONIBUS")
	aadd(aPalavras,"PARALELEPIPEDO")
	aadd(aPalavras,"BETERRABA")
	aadd(aPalavras,"PTERODACTILO")
	aadd(aPalavras,"CHEWBACCA")

	// abre a tabela
	USE (cTable) ALIAS TMP SHARED NEW VIA "TOPCONN"

	// acrescenta as palavras no arquivo
	aeval( aPalavras , { |x| dbappend(), TMP->PALAVRA := x , dbrunlock() })

	// Limpa variavel global de controle
	PutGlbValue("PROCJOBS","")

	// Inicia os jobs
	For nI := 1 to nJobs
		StartJob("U_JOBHASH",getenvserver(),.f.,strzero(nI,2),cTable)
		Sleep(100)
	Next

	// Inicia contagem de tempo
	nTimer := seconds()

	// Espera os jobs terminarem
	MsgRun("Calculando Hashes","Aguarde ... ",{|| WaitProcs(nJobs) } )

	// Mostra os dados processados
	// lendo a propria tabela

	DBGotop()
	While !eof()
		conout(TMP->PALAVRA+" => "+TMP->HEXHASH+' (JOB '+TMP->JOBID+') em '+str(TMP->TEMPO,12,3)+' s.')
		DbSkip()
	Enddo

	// Fecha a tabela
	DbCloseArea()
	
	// Apaga a tabela
	TcDelFile(cTable)

	MsgInfo("Tempo Total : "+str(seconds()-nTimer,12,3)+" s.","Atenção")

return

// Espera o processamento estar temrinado
// Usa uma variavel global em memoria para controle 
STATIC Function WaitPRocs(nJobs)

	Local cOk := replicate(".",nJobs)
	While !killapp() .and. GetGlbValue("PROCJOBS") != cOk
		Sleep(250)
	Enddo

RETURN


// Job de processamento 
// Recebe o nome da tabela, processa os dados pendentes 
// Ao temrinar , acrescenta um "." na global de controle

USER Function JOBHASH(cIdJob,cTable)
	Local cPalavra, cJobRun
	Local cRet
	Local nTimer

	tclink()

	USE (cTable) ALIAS TMP SHARED NEW VIA "TOPCONN"

	While !Eof()

		cPalavra := Alltrim(TMP->PALAVRA)
		cJobRun := TMP->JOBID

		IF dbrlock(recno())

			// Se bloqueou , pode processsar
			// mas verifica se já nao está processado ...

			If !empty(TMP->HEXHASH)
				conout("Job ["+cIdJob+"] ["+cPalavra+"] foi processada pelo Job ["+cJobRun+"]")
				dbrunlock()
				dbskip()
				LOOP
			Endif

			conout("Job ["+cIdJob+"] ["+cPalavra+"] sendo calculado ... aguarde ...")

			// Atualiza o JobId que está processando esse registro 
			// e faz flush da informação pro banco de dados 
			TMP->JOBID := cIdJob
			DBCommit()

			nTimer := seconds()
			cRet := SuperHash(cPalavra)
			conout("Job ["+cIdJob+"] ["+cPalavra+"] calculado em "+str(seconds()-nTimer,12,3)+" s.")

			// atualiza no registro o hash calculado
			// e o tempo que demorou 
			TMP->HEXHASH := cRet
			TMP->TEMPO := round(seconds()-nTimer,3)

			// e Solta o bloqueio
			Dbrunlock()

		else

			// Nao bloqueou , esta sendo processada por outro job
			conout("Job ["+cIdJob+"] ["+cPalavra+"] ignorada -- em processamento pelo Job ["+cJobRun+"] ")

		Endif

		// Vai para o proximo
		DbSkip()

	ENDDO

	PutGlbValue("PROCJOBS",GetGlbValue("PROCJOBS")+'.')

	DbCloseArea()

RETURN

// Aplica SHA1 262144 para cada palavra 
// retorna SHA1 no formato hexadecimal ( 40 caracteres ) 

STATIC function SuperHash(cPalavra)
	Local nI
	For nI := 1 to 256 * 1024
		cPalavra := SHA1(cPalavra,2)
	Next
RETURN cPalavra



...

Agora , ao colocarmos 3 jobs processando, podemos ter um resultado assim:

Bloco de código

Job [01] [ARQUIPELAGO] sendo calculado ... aguarde ...
Job [02] [ARQUIPELAGO] ignorada -- em processamento pelo Job [01]
Job [02] [AUTOMOVEL] sendo calculado ... aguarde ...
Job [03] [ARQUIPELAGO] ignorada -- em processamento pelo Job [01]
Job [03] [AUTOMOVEL] ignorada -- em processamento pelo Job [02]
Job [03] [ONIBUS] sendo calculado ... aguarde ...
Job [01] [ARQUIPELAGO] calculado em        3.169 s.
Job [01] [AUTOMOVEL] ignorada -- em processamento pelo Job [02]
Job [01] [ONIBUS] ignorada -- em processamento pelo Job [03]
Job [01] [PARALELEPIPEDO] sendo calculado ... aguarde ...
Job [03] [ONIBUS] calculado em        3.161 s.
Job [03] [PARALELEPIPEDO] ignorada -- em processamento pelo Job [01]
Job [03] [BETERRABA] sendo calculado ... aguarde ...
Job [02] [AUTOMOVEL] calculado em        3.321 s.
Job [02] [ONIBUS] foi processada pelo Job [03]   <===== REPARE AQUI 
Job [02] [PARALELEPIPEDO] ignorada -- em processamento pelo Job [01]
Job [02] [BETERRABA] ignorada -- em processamento pelo Job [03]
Job [02] [PTERODACTILO] sendo calculado ... aguarde ...
Job [01] [PARALELEPIPEDO] calculado em        3.413 s.
Job [01] [BETERRABA] ignorada -- em processamento pelo Job [03]
Job [01] [PTERODACTILO] ignorada -- em processamento pelo Job [02]
Job [01] [CHEWBACCA] sendo calculado ... aguarde ...
Job [03] [BETERRABA] calculado em        3.405 s.
Job [03] [PTERODACTILO] ignorada -- em processamento pelo Job [02]
Job [03] [CHEWBACCA] ignorada -- em processamento pelo Job [01]
Job [02] [PTERODACTILO] calculado em        3.411 s.
Job [02] [CHEWBACCA] ignorada -- em processamento pelo Job [01]
Job [01] [CHEWBACCA] calculado em        2.813 s.

ARQUIPELAGO          => 53be976968beeb949b9e17515b388ff1be51c582 (JOB 01) em        3.169 s.
AUTOMOVEL            => abb157df53f6b89befdb93084b3855c9b89752b2 (JOB 02) em        3.321 s.
ONIBUS               => 9ca3cf8e0d8030ffd85a62782ccafd047cf80bca (JOB 03) em        3.161 s.
PARALELEPIPEDO       => 797525c9c858a969417569ff9dc309a9a7b245ad (JOB 01) em        3.413 s.
BETERRABA            => 667320efb1e4194f125b2139448a04d897bf9f8d (JOB 03) em        3.405 s.
PTERODACTILO         => 4891a5682a28f4472531a05387d51bd43cdb7874 (JOB 02) em        3.411 s.
CHEWBACCA            => 8122c6c9720adb5971b57468766ce32efdb71140 (JOB 01) em        2.813 s.

...