Discussioni sul sistema operativo Linux
 

hash in ruby

MaxAdamo 31 Mag 2015 12:10
la domanda può sembrare ******* - e magari lo è veramente :) - ma gli hash in
ruby sono i dizionari python, quindi non riesco ad affinare bene la ricerca
google.
Io voglio creare un hash sum, che sia un numero compreso tra X e Y, partendo
da una determinata stringa.
Esempio pratico, Puppet ha la funzione fqdn_rand che genera un numero compreso
tra X e Y, associato a sua volta al nome dell'host.
In questo caso però non posso usare questa funzione, perché voglio un numero
che sia uguale tra gli host di uno stesso cluster.
MaxAdamo 31 Mag 2015 12:38
Il giorno domenica 31 maggio 2015 12:10:52 UTC+2, MaxAdamo ha scritto:

> tra X e Y, associato a sua volta al nome dell'host.
> In questo caso però non posso usare questa funzione, perché voglio un numero

> che sia uguale tra gli host di uno stesso cluster.

fin qui ci siamo:
require 'digest/md5'
Digest::MD5.hexdigest('miastringa').hex

e il resto che mi manca. E mi server un one-line statement, non un programma.
Alessandro Pellizzari 31 Mag 2015 18:49
Il Sun, 31 May 2015 03:10:51 -0700, MaxAdamo ha scritto:

> la domanda può sembrare ******* - e magari lo è veramente :) - ma gli
> hash in ruby sono i dizionari python, quindi non riesco ad affinare bene
> la ricerca google.
> Io voglio creare un hash sum, che sia un numero compreso tra X e Y,
> partendo da una determinata stringa.

Non ti serve un hash, ma una hashing function, e abbastanza specifica,
quindi o te la crei o ti adatti a quello che c'è.

> Esempio pratico, Puppet ha la funzione fqdn_rand che genera un numero
> compreso tra X e Y, associato a sua volta al nome dell'host.
> In questo caso però non posso usare questa funzione, perché voglio un
> numero che sia uguale tra gli host di uno stesso cluster.

Le funzioni di hash più comuni (come md5, sha1, sha256, ecc.) cercano di
ridurre al minimo le collisioni, quindi generano valori di hash molto
grandi.

Se vuoi un numero tra 1 e 1000, per esempio, ti devi scrivere tu la
funzione (e aspettarti molte collisioni). Se vuoi un numero a 32bit (da 1
a 4miliardi e rotti) fai l'md5 (o l'sha1 o...), prendi i primi 4 byte e
convertili da hex a dec (ma aspettati collisioni, anche se rare)

Altrimenti usa l'hash value calcolato come stringa, come fa git, e amen.

Bye.
Max_Adamo 31 Mag 2015 22:31
Il Sun, 31 May 2015 16:49:29 +0000, Alessandro Pellizzari ha scritto:

> Il Sun, 31 May 2015 03:10:51 -0700, MaxAdamo ha scritto:
>
>> la domanda può sembrare ******* - e magari lo è veramente :) - ma gli
>> hash in ruby sono i dizionari python, quindi non riesco ad affinare
>> bene la ricerca google.
>> Io voglio creare un hash sum, che sia un numero compreso tra X e Y,
>> partendo da una determinata stringa.
>
> Non ti serve un hash, ma una hashing function, e abbastanza specifica,
> quindi o te la crei o ti adatti a quello che c'è.
>
>> Esempio pratico, Puppet ha la funzione fqdn_rand che genera un numero
>> compreso tra X e Y, associato a sua volta al nome dell'host.
>> In questo caso però non posso usare questa funzione, perché voglio un
>> numero che sia uguale tra gli host di uno stesso cluster.
>
> Le funzioni di hash più comuni (come md5, sha1, sha256, ecc.) cercano di
> ridurre al minimo le collisioni, quindi generano valori di hash molto
> grandi.
>
> Se vuoi un numero tra 1 e 1000, per esempio, ti devi scrivere tu la
> funzione (e aspettarti molte collisioni). Se vuoi un numero a 32bit (da
> 1 a 4miliardi e rotti) fai l'md5 (o l'sha1 o...), prendi i primi 4 byte
> e convertili da hex a dec (ma aspettati collisioni, anche se rare)
>
> Altrimenti usa l'hash value calcolato come stringa, come fa git, e amen.
>
> Bye.

La collisione c'è ovviamente, ma nel caso spcifico non mi interessa per
niente: si tratta di ottenere la key di un hash (stavolta hash nel senso
di array...) e premetto che qualcosa ho già combinato (vedi sotto). Non so
ancora se funziona... ma ho preso pezzi in giro e li ho messi insieme.

A me serve un numero da zero a 3. In futuro se l'ambiente cresce potrebbe
servirmi un numero da zero a 6 :)

In sostanza, ho un paio di cluster Galera MariaDB/Percona, e diverse
applicazioni che si collegano in round-robin tramite haproxy, ma il round-
robin non è sicuro per qualsiasi applicazione (per via di un problema di
locking delle righe di mysql a livello di cluster).
In questo caso io, tramite puppet, chiamo la mia classe, con il parametro:
"haproxy_roundrobin => false"
Avendo diverse applicazioni che si devono connettere al DB, vorrei evitare
che tutte le applicazioni vadano ad insistere sullo stesso nodo. Allo
stesso modo, vorrei anche evitare che le persone debbano andare a
verificare quale nodo è più libero.

Al momento, nel template uso una cosa del genere:
<% if myhost == @nodes.sort[0] -%>

Ma in futuro, appena verifico lo script, mi serve un numero che:
1) ad ogni giro di puppet non cambi.
2) sia uguale su ciascun nodo per quella specifica applicazione (come
avevo già detto, puppet ha una funzione specifica che ti crea un numero
associato al nome host, ma in questo caso non posso usarlo).


Script:
require 'digest/md5'

# Generate a hash-sum from a given string between 0 and a given max-value
# - 1st arg is the string
# - 2nd arg is the max value
module Puppet::Parser::Functions
newfunction(:string_rand, :type => :rvalue) do |args|

if args.length != 2
raise Puppet::ParseError, "string_rand(): wrong number of args (#
{args.length}; 2 expected)"
end

basestring = args[0]
maxvalue = args[1]

unless maxvalue.is_a?(Numeric)
raise Puppet::ParseError, 'string_rand(): second arg must be a
Numeric'
end

Digest::MD5.hexdigest(basestring).hex % maxvalue
end
end




--
Massimiliano Adamo
MaxAdamo 1 Giu 2015 12:08
Il giorno domenica 31 maggio 2015 22:32:26 UTC+2, Max_Adamo ha scritto:
> Il Sun, 31 May 2015 16:49:29 +0000, Alessandro Pellizzari ha scritto:
>
>> Il Sun, 31 May 2015 03:10:51 -0700, MaxAdamo ha scritto:
>>
>>> la domanda può sembrare ******* - e magari lo è veramente :) - ma gli
>>> hash in ruby sono i dizionari python, quindi non riesco ad affinare
>>> bene la ricerca google.
>>> Io voglio creare un hash sum, che sia un numero compreso tra X e Y,
>>> partendo da una determinata stringa.
>>
>> Non ti serve un hash, ma una hashing function, e abbastanza specifica,
>> quindi o te la crei o ti adatti a quello che c'è.
>>
>>> Esempio pratico, Puppet ha la funzione fqdn_rand che genera un numero
>>> compreso tra X e Y, associato a sua volta al nome dell'host.
>>> In questo caso però non posso usare questa funzione, perché voglio un
>>> numero che sia uguale tra gli host di uno stesso cluster.
>>
>> Le funzioni di hash più comuni (come md5, sha1, sha256, ecc.) cercano di
>> ridurre al minimo le collisioni, quindi generano valori di hash molto
>> grandi.
>>
>> Se vuoi un numero tra 1 e 1000, per esempio, ti devi scrivere tu la
>> funzione (e aspettarti molte collisioni). Se vuoi un numero a 32bit (da
>> 1 a 4miliardi e rotti) fai l'md5 (o l'sha1 o...), prendi i primi 4 byte
>> e convertili da hex a dec (ma aspettati collisioni, anche se rare)
>>
>> Altrimenti usa l'hash value calcolato come stringa, come fa git, e amen.
>>
>> Bye.
>
> La collisione c'è ovviamente, ma nel caso spcifico non mi interessa per
> niente: si tratta di ottenere la key di un hash (stavolta hash nel senso
> di array...) e premetto che qualcosa ho già combinato (vedi sotto).

wahoo! questa e' la versione finale:

module Puppet::Parser::Functions
newfunction(:string_rand, :type => :rvalue, :doc => <<-EOS
Generates a hash-sum from a given string between 0 and a given max-value:
- the 1st arg is the string
- the 2nd arg is the max-value and must be an integer
EOS
) do |args|
require 'digest/md5'

if args.length != 2
raise Puppet::ParseError, "string_rand(): wrong number of args
(#{args.length}; 2 expected)"
end

basestring = args[0]
maxvalue = args[1]

Digest::MD5.hexdigest(basestring).hex % maxvalue.to_i
end
end

Links
Giochi online
Dizionario sinonimi
Leggi e codici
Ricette
Testi
Webmatica
Hosting gratis
   
 

Discussioni sul sistema operativo Linux | Tutti i gruppi | it.comp.os.linux.sys | Notizie e discussioni linux | Linux Mobile | Servizio di consultazione news.