Binární zápis do souboru

webhope

Re:Binární zápis do souboru
« Odpověď #30 kdy: 13. 12. 2013, 09:50:09 »
Není to možný aby se přepisovali. Zapisuji tři bajty, každý má své místo. Pro zjednodušení si to představ jako kontejner, který má kapacitu jednoho záznamu a jedné konkrétní IP, začínající na \1:
\2\3\4
kde číslo bajtu současně znamená číslo v pořadí v IP. A teď si to představ, že tam bude záznamů více
V tom případě by si měl jen jeden řádek, který má tři bajty. V případě, že chceš vytvořit kontejner pro dvě IP (začínající na 1 a na 2) zapsal bych tam:
\2\3\4\2\3\4
Když chceš mít kontejner pro 254 záznamů, ale každý začíná na jiné číslo, bude to 254xsekvence \2\3\4 . Když bys tam chtěl mít max. dvě stejné IP adresy tak budeš 254x opakovat sekvenci \2\3\4\2\3\4 ... z toho vyplývá, že každá IP a každé číslo má svoje místo a nemůže se přepsat.

Citace
Ale problém s hledáním konce dat testováním na hodnotu \0 tam pořád vidím.
Ve skutečnosti nehledám konec dat, ale začátek dat kam mohu psát a pak vracím true;
Kód: [Vybrat]
if ( $byte === "\x00" ){
...
return true;
break;
}
Při pokusu vložit IP, když najde nulu, zapíše 3 bajty a ukončí vkládání. Dále nepokračuje.

Hodnota \0 nemůže být součástí záznamu, protože ascii tabulka začíná od jedničky :-)
Citace
a smyčkou také testuješ zda je IP blokována.
Zkontroloval jsem. Je tam return false; ale nedal jsem tam break; takže to opravuju. I když teoreticky by se program měl ukončit hned při return, php není Javascript, nemohou jet dva procesy současně! Asi to zas smažu ! :-)
Tabulka má kapacitu 249 IP (nyní) ale stejně podle mého názoru je to zbytečně moc. Stačilo by 200, s tím, že se to každou hodinu aktualizuje (soubor se znova založí).
Kód: [Vybrat]
Data nemáš na úrovni stejně významných bajtů IP adresy nijak tříděna. To přece mohou být stovky průchodů, když bude tabulka více zaplněna.Jestli myslíš ten počátek, tak tam není třídění třeba. V jednom řádku jsou všechny IP začínající např. na 124. Máš, pravdu, že bych to mohl setřídit čísla druhé v pořadí, jestli myslíš toto, ale to prakticky nejhraje roli, protože to ničemu nepomůže.

Citace
Přelétl jsem další komentáře a prošel podrobněji ten (původní) kód a teprve teď mi došlo, k čemu ten kód má vlastně sloužit: k jednoduchém ukládání a vyhledávání JEDNOTLIVÝCH IP adres, tedy žádná magie, žádné intervaly, žádné podsítě. Proč tedy ty IP adresy jednoduše neukládáš do databáze třeba jako 32bit unsigned integer do jednoho indexovaného sloupce? Neřešilo by to vše, co potřebuješ?
Jistě, možností existuje více. Jak už tu padlo, mohl bych použít sqllite a bylo by to taky efektivní. Tohle je v podstatě jen na trénning. Myslím, ale že to splní svůj účel stejně jako by to splnilo načítání ze souboru. Obojí je rychlé. Ale tímhle jsem se něco naučil, hlavně co se týče té binární logiky. Chci zkusit ještě udělat ten dynamický kontejner pro blockované IP, kde bude neomezený počet IP, ale rychlost vyhledávání prakticky taky neomezená (vyhledávací čas v ms očekávám nula - podle výsledků včerejšího měření ... jestli jsem to dělal dobře).


webhope

Re:Binární zápis do souboru
« Odpověď #31 kdy: 13. 12. 2013, 11:39:28 »
Jak jsem psal, že by se tento binární princip dal použít i na sestrojení vlastní databáze, tak mě napadl jeden dobrý důvod proč ano. Představte si, že si odněkud z netu stáhnete webové stránky používající mysql, případně sqlite, zdrojový kód moc nezkoumáte, ale rozhodnete se to nakonfigurovat a spustit. Časem se může stát, že na databází bude proveden útok pomocí některých metod jako
javascript injection, sql injection nebo SQL Injection Host (http://shiflett.org/blog/2006/mar/server-name-versus-http-host) (když útočník změní hlavičku odesílaného požadavku tak, aby obsahoval útočný skript a vy tu hlavičku ukládáte třeba jen do session tabulky, nebo do tabulky se statistikama, tak se ukládaný kód změní ve smrtelnou past). Tohle by se ale nikdy nemohlo stát v případě vlastnoručně napsané třídy, kde místo queries voláte přímo metody k jednotlivým třídám (příklad: users.insert("pepa@seznam.cz","mojeheslovmd5");. Takový přístup by byl nejen jednodušší, ale i bezpečnější.

none_

Re:Binární zápis do souboru
« Odpověď #32 kdy: 13. 12. 2013, 13:53:53 »
Relační databáze mají dobrý důvod, proč existují a jsou používány. Prostě určitý typ úloh řeší dobře.

Jinak to, co popisuješ je základ každého ORM. Jenom se tam vetsinou nedela users.insert(jmeno, prijmeni), ale users.insert(user).

Každopádně takovýmto zaobalením bezpečnost nezvýšíš. Pouze můžeš odstranit rizika spojená s SQL databázemi. Ať už tak, že ta tvoje třída bude důsledně ošetřovat všechny vstupy, nebo tak, že na pozadí budeš používat něco jiného než SQL databázi. Ale třeba ten javascript injection neodstraníš. Když ti někdo do DB uloží do políčka jméno uživatele javascript a ty ho potom někde zobrazíš v neescapované podobě, tak máš aplikaci stejně v háji, až používáš relační databázi, objektovou nebo key-value...

webhope

Re:Binární zápis do souboru
« Odpověď #33 kdy: 13. 12. 2013, 14:05:09 »
none_: to je fakt, je javascriptový útok na to nemá vliv.

petr: ještě mě napadlo jestli si nemyslel to, že když překročím oněch 250 IP ček, tak že se to bude zapisovat do dalšího segmentu. To jsem sice původně plánoval očetřit, ale vlastně jsem se k tomu ještě nedostal, takže to udělám dnes. Jde jen o to si hlídat počet načtených bajtů.

webhope

Re:Binární zápis do souboru
« Odpověď #34 kdy: 13. 12. 2013, 14:07:02 »
vlastně zase kecám. vždyť je tam ta smyčka for která končí po 250 bajtech... takže se to přepsat nemůže


none_

Re:Binární zápis do souboru
« Odpověď #35 kdy: 13. 12. 2013, 14:10:18 »

petr

Re:Binární zápis do souboru
« Odpověď #36 kdy: 13. 12. 2013, 18:46:03 »
Neztrácej čas vracením se k tomu, že jsem v předminulém (asi) komentáři psal, že se ti bajty IP adres ukládají objednu pozici vedle sebe a dojde k přepisování. To mě zmátl ten testovací kód, který jsem bral jako součást funkce a považoval jsem za testovací naopak ten die(); smazal jsem si z toho komentáře. Myslel jsem, že je to jasné z mého posledním komentáře. Takže se omlouvám za čeření vody.

Ale v tom posledním komentáři jsem psal už o jiných věcech a po přečtení reakce mi nezbývá než tě na něj znovu odkázat. Zkusím to napsat znovu trochu jinak a podrobněji:

Mluvil jsem o přepisování záznamů IP adres, které mají jako druhý nejvýznamnější bajt nulu. Takovou IP adresu (s druhým bajtem 0) při ukládání další IP adresy, která má stejný první bajt, přepíšeš, protože v souboru testuješ na \0 jako konec dat a pokud tam je, zapíšeš novou IP adresu a tedy přepíšeš předchozí (která měla druhý bajt 0). ASCII s tím přece nijak nesouvisí, chr(0) == \0 == \x00

O smyčkách jsem mluvil kvůli tomu, že tu datovou strukturu právě moc efektivní nemáš. Při zápisu hledáš smyčkou konec dat (\0) při čtení zase musíš prohledávat smyčkou záznamy dokud nenajdeš shodu nebo konec (\0).  Píšu musíš, protože metoda checkIP v tom kódu, je nefunkční - smyčka se přeruší při prvním bajtu, který nedopovídá druhému bajtu IP adresy, a tedy téměř vždy skončí bez vrácení hodnoty.

Pokud to opravíš, tak abys při plné tabulce zjistil, že IP adresa NENÍ v blacklistu, což bude asi naprostá většina, projdeš smyčkou segmentLength krát, vždy jeden seek a jeden fread,  tj. 250x (dle původního kódu),  v nejhorším případě ale provedeš seek a read 3x za průchod, což je 750x. Možná je to zanedbatelné, ale jeden SQL dotaz do indexovaného pole nebo projití binárního stromu (což může být to stejné) bude
IMHO mnohem rychlejší. Ten nejhorší případ je pro tabulku zaplněnou ip adresama které se liší jen v posledním bajtu.

Co se týče dynamického kontaineru (teď to máš omezené na 250 IP adres), vždyť to řeší databáze. SQL injection přece vůbec nemusíš řešit, vždyť potřebuješ uložit/vyhledat jedno číslo, které bude vždy číslem. Pokud navíc předpokládáš podvržené IP adresy na vstupu nebo nějaký balast tak je celá tvoje aplikace k ničemu.

Pokud se jen učíš, dobře, praktický význam to ale podle mě nemá - řešení pomocí databáze (nepotřebuješ relační) je triviální, efektivnější, neomezené počtem ip adres a rozšiřitelné. Pokud například použiješ B-Tree index, což bude stejně nejefektivnější, tak je triviální třeba kontroloval i rozsahy IP adres (jediným dotazem), tj. zda třeba daná IP není součásti blokované sítě. Pokud chceš udělat něco co bude efektivnější než databáze, tak ty adresy budeš muset stejně ukládat do binárního stromu.

Musím se přiznat, že mnohdy nevím, na co reaguješ, např:
Citace
Zkontroloval jsem. Je tam return false; ale nedal jsem tam break; takže to opravuju. I když teoreticky by se program měl ukončit hned při return, php není Javascript, nemohou jet dva procesy současně! Asi to zas smažu ! :-)

Javascript není Javascript, nemohou jet dva procesy současně! :) ?

I když nevím jak to souvisí s tím, co jsem ti psal.

Specifikace ECMAScriptu (javascriptu) nedefinuje žádné mechanismy pro multithreading. Nicméně pro Javascript se dají použít web workers (součást specifikace HTML5), pro PHP zase pthreads.

webhope

Re:Binární zápis do souboru
« Odpověď #37 kdy: 13. 12. 2013, 20:30:58 »
Tak zase z mého úhlu pohledu. IP adresa sice může obsahovat nuly, ale mám pocit, že toto platí jen v místní síti. Na veřejné síti se nuly neobjevují. Takže máš pravdu, že adresa vnitřní sítě např. 127.0.0.1 má jako první bajt 127, ale posuzuju podle druhého bajtu, který je 0 a tudíž by opravdu došlo k chybě. Nicméně, počítám s tím že tyto adresy tam prostě nebudou. Počítám, že zapisuji proxy adresy, ale připomínka je to dobrá. Tzn. co bych tam měl zapsat místo nuly, 255 do celého souboru?

Pokud jde o konec metody checkIP tak tam je to takto:
Kód: [Vybrat]
if(...){...}
else
{ return true; // no more ips to check
}
endfor;
echo  " end of check method  ";
return true;
}

Tobě jde o to, že fread($hf,1) volám ze smyčky místo fread($hf,250) bez smyčky? ale fread dělá v podstatě to samé protože data uvnitř fread se čtou pomocí smyčky, ne? Já každopádně žádné zpoždění nenaměřil, možná to neumím měřit, ale prostě to nějak vidím jako zanedbatelné. SQL dotaz by sice nevyžadoval smyčku, ale máš zdržení způsobené databází, které je větší než když to čteš ze souboru který máš na disku kde jsou webovky. Přece mysql taky používá nějaké vyhledávací mechanismy, které i kdyby byly seberychlejší, musí řešit spoustu věcí okolo vrácení těch správných dat. To jsou operace, které nevidíš, ale dějí se na straně mysql serveru, takže nějaké zpoždění tam bude + doba přenosu + čas na to aby php vyhodnotilo vrácenou odpověď ....

Podvržené IP adresy? To myslíš co a jak by to útočník udělal?

Jak říkám, řešit tenhle proxy kontainer přes db (mysql) je podle mě totální mrhání prostředky. Vždyť se to bude neustále měnit a přepisovat, nepotřebuju zdržení kvůli připojení a odeslání a vybavení mysql požadavku. Takže omezení adres mi vůbec nevadí a není to žádný problém. Ohledně binárního stromu už nevím o čem mluvíš.

webhope

Re:Binární zápis do souboru
« Odpověď #38 kdy: 13. 12. 2013, 20:48:00 »
A nezapomel si na to, že když unikátní IP vkládáš do db, tak ta taky musí kontrolovat jedinečnost, tj. porovnat všechny IP? Což bude logicky mnohem náročnější počet. Vem si tedy ten extrémní případ, že je tabulka skoro plná: 249*254 záznamů. Tak při vkládání musí porovnat 63246 záznamů (IP adres) tedy 252984 bajtů. Já porovnávám 249 ajpin konkrétně 747 bajtů.

Z relační db znám jen to mysql to ten druhý typ jako uložiště znám jen mysql lite. Tam by se ušetřil ten čas na přenost, ale podle mě by to bylo nastejno. Pro mě je hlavní si to zkusit, to co pro tebe nemá praktický význam pro mě může mít význam i praktický.

webhope

Re:Binární zápis do souboru
« Odpověď #39 kdy: 13. 12. 2013, 20:51:14 »
Chtěl jsem říct ne mysql lite ale sqlite. Ale z databázemi jsem moc nepracoval takže je nemám v malíčku, takže ty jak to třeba popisuješ pro tebe by to nebyl problém. Mě každopádně láká ta možnost napsat vlastní třídu a vyzkoušet něco jak by to bylo nebo nebylo efektivní, i když o neefektivnosti nebo neužitečnosti nejsem přesvědčen (spíš si myslím, že je to řešení psané na míru).

petr

Re:Binární zápis do souboru
« Odpověď #40 kdy: 14. 12. 2013, 22:17:43 »
Chtěl jsem říct ne mysql lite ale sqlite. Ale z databázemi jsem moc nepracoval takže je nemám v malíčku, takže ty jak to třeba popisuješ pro tebe by to nebyl problém. ...
Ten problém je skutečně triviální, jeden sloupec, jeden index. To by jsi určitě zvládl.

Mě každopádně láká ta možnost napsat vlastní třídu a vyzkoušet něco jak by to bylo nebo nebylo efektivní...
A já to tak taky vnímám...

... (spíš si myslím, že je to řešení psané na míru).
Na míru čeho? Bude mít ta množina IP adres nějakou charakteristiku nebo nějaká vyplývá z toho, že to budou proxy servery? Já jsem tam nic speciálního neviděl, ten problém se mi jeví jako zcela obecné vyhledávání v množině čísel.

Tak zase z mého úhlu pohledu. IP adresa sice může obsahovat nuly, ale mám pocit, že toto platí jen v místní síti. Na veřejné síti se nuly neobjevují. Takže máš pravdu, že adresa vnitřní sítě např. 127.0.0.1 má jako první bajt 127, ale posuzuju podle druhého bajtu, který je 0 a tudíž by opravdu došlo k chybě. Nicméně, počítám s tím že tyto adresy tam prostě nebudou. Počítám, že zapisuji proxy adresy, ale připomínka je to dobrá. Tzn. co bych tam měl zapsat místo nuly, 255 do celého souboru?

Ne, když se pro jednoduchost budeme zabývat jen druhým nejvýznamnějším bajtem, tak jakákoliv hodnota včetně 0 či 255 může být součástí veřejné IP adresy koncového zařízení.

Co se týče adres, které mají v druhém bajtu 0 a se kterými nemusíš počítat, tak jsou IMHO následující:
- 127.0.x.x - část rozsahu 127.x.x.x pro loopback
- 10.0.x.x - lokální síť třídy A
- [>=224].0.x.x - multicast a část rezervovaného rozsahu [240-255].x.x.x
- broadcast pro každou síť, který má v bitech pro hosta samé jedničky (nejvyšší adresa v síti), např. x.0.0.255 (broadcast sítí třídy A)
- samotné adresy sítí, tj. ne koncových zařízení, které mají v bitech pro hosta samé nuly (nejnižší adresa v síti), např. x.0.0.0 - adresy všech sítí třídy A
Co ale s tím?

Takže tabulku klidně inicializovat nulama můžeš, ale aby jsi našel konec dat (první prázdný záznam), musíš kontroloval, zda jsou v tabulce nuly na pozicích všech bajtů záznamu IP adresy, protože máš záznam rozdělen na 3 bajty. Potom by mohly záznamy kolidovat jen s adresami sítí třídy A (x.0.0.0), protože hodnota 1. bajtu ti data rozděluje na segmenty, ale adresy sítí tam nebudou. Nejlepší je stejně ukládat si počet záznamů, a potom nemusíš vůbec hledat konec, budeš ho vždy znát: začátek segmentu + počet záznamů * (1 bajt).

Další věc je ta, že po zaplnění tabulky ji vyprázdníš, tudíž ztratíš informace o všech blokovaných IP adresách a začneš znovu. To asi není, to co bys chtěl. Co tam bude ty blokované IP adresy přidávat? Ideální je uchovávat si časy posledního "zásahu" pro každou blokovanou adresu a pokud ti dojde místo, nahradit ten záznam, který měl zásah před nejdelší dobou. Případně to kombinovat s četnosti záznamů apod. Triviální pro databázi (druhé pole, druhý index) nebo vytvořit druhý binární strom.

Pokud jde o konec metody checkIP tak tam je to takto:
Kód: [Vybrat]
if(...){...}
else
{ return true; // no more ips to check
}
endfor;
echo  " end of check method  ";
return true;
}

Tobě jde o to, že fread($hf,1) volám ze smyčky místo fread($hf,250) bez smyčky? ...

Psal jsem "smyčka se přeruší při prvním bajtu, který nedopovídá druhému bajtu IP adresy  a tedy téměř vždy skončí bez vrácení hodnoty".
Kód: [Vybrat]
    public function checkIP ($ip)
    {
        $arr = $this->splitIp($ip);
        $segmentBegin = ($arr[0] - 1) * $this->segmentLength;
        if (! $this->FRWBHandler)
            $this->FRWBHandler = @fopen($this->file, "r+b");
        $fh = & $this->FRWBHandler;
        for ($i = $segmentBegin; $i <= $segmentBegin + $this->segmentLength; $i ++) :
            fseek($fh, $i);
            $byte = fread($fh, 1);
            if ($byte !== "\x00") {
                if ($byte === "\x" . $arr[1]) {
                    fseek($fh, $i + $this->segmentLength);
                    $byte = fread($fh, 2);
                    if ($byte === "\x" . $arr[2]) {
                        fseek($fh, $i + 2 * $this->segmentLength);
                        $byte = fread($fh, 1);
                        if ($byte === "\x" . $arr[3])
                            return false; // this ip is blocked
                    }
                }
                break;
            } else
                return true; // no more ips to check
        endfor
        ;
    }
Špatně je ten "break", místo něho musí být "continue" a také to, že za smyčkou nevracíš true (to už jsi tam doplnil).
Ale abys ošetřil ty případné nuly v IP adresách, tak by jsi musel v každém průchodu kontrolovat všechny 3 bajty IP adresy.

Dále píšeš o režii databáze, jasně to se musí brát v úvahu, proto jsem psal "Pokud chceš udělat něco co bude efektivnější než databáze". Ale ta režie není závislá na velikosti souboru, algoritmu vyhledávání, ale spíš jak jsi psal na komunikaci mezi skriptem a databázovým serverem. Určitě to lze implementovat s menší režií bez databáze. Ta sqlite vypadá pro tenhle účel zajímavě. Defakto ti ale stačí implementovat binární strom.

Mám pocit, že jsi jednou psal, že zkoušíš udělat optimální algoritmus, jindy že ti rychlost postačuje. Kdyby jsi do jednoho souboru ukládal 250 x 32bit číslo jako IP adresu a při každém testu procházel vše, nemohlo by to být pomalejší než to máš teď. To rozdělování IP adresy na jednotlivé bajty a jejich ukládání do zvláštních segmentů nemá ve tvé implementaci téměř žádný smysl, musíš stejně otestovat všech 250 záznamů. Výjimkou je pouze ten první bajt, který neukládáš, ale určuje ti segment, ale zase ti kvůli tomu narostla velikost dat 256x.

Kdyby jsi byl důsledný, a udělal to i pro ostatní komponenty IP adresy, tak máš vlastně pole o 4 rozměrech, bitmapu o 222(?)*256*256*254 záznamech pro kompletní rozsah IP adres, tj. soubor o velikost 440MiB, tam by jsi skutečně nemusel nic hledat, a vždy by jsi přečetl nebo zapsal pouze 4 bity. Nevýhoda - veliký soubor zabírající místo na disku, nic efektivnějšího nelze ale vymyslet. Buď tedy tohle, nebo chceš mít uložen jen omezený počet IP adres a potom musíš mít seznam setříděn nebo uložen v binárním stromu. Záleží na tom kolik těch IP adres bude, a jak často se budou zapisovat, protože při zápisu musíš záznamy setřídit nebo rebalancovat strom. Budeš-li mít záznamy setříděné nebo v úplném binárním stromu, potřebuješ ke zjištění, zda IP adresa NENÍ přítomna v 250 záznamech MAXIMÁLNĚ 8 testů. Ty jich potřebuješ VŽDY 250 * 3, takže 750. Použití prvního bajtu IP adresy jako čísla segmentu ti to zredukovalo na 750 z 1000 testů ale 256x ti narostla velikost tabulky. Obě možností můžeš kombinovat a hledat kompromis mezi rychlostí a potřebnou velikostí tabulky, ale pokud se bude jednat víceméně o náhodné IP adresy, tak nemáš podle čeho optimalizovat.

Navíc kromě té kompletní bitmapy má sotva smysl ukládat komponenty IP adresy zvlášt - převeď ji na 32bit číslo.

petr

Re:Binární zápis do souboru
« Odpověď #41 kdy: 14. 12. 2013, 23:05:05 »
Zase v obou metodách addIP a checkIP vidím na začátku
Kód: [Vybrat]
$segmentBegin = ($arr[0] - 1) * $this->segmentLength;, tzn. že addIP() ti přepisuje data, a ani checkIP() nemůže fungovat. Musí tam přece být
Kód: [Vybrat]
$segmentBegin = ($arr[0] - 1) * $this->segmentLength * 3;.

A jestli tedy uhádám, jak ten kód má vypadat, nebo vypadá v současné době, tak není pravda co jsem psal, že pojme 250 IP adres ale pojme 250 - 250*254 adres v závislosti na hodnotách 1. komponenty IP adresy. A také není pravda, že po každé musíš  otestovat 750 čísel ale 3 - 750 čísel.

Končím. Asi jsem blbej, protože nechápu, jak ti to může fungovat.

webhope

Re:Binární zápis do souboru
« Odpověď #42 kdy: 14. 12. 2013, 23:57:28 »
Dneska to už nedávám odpovědět na všechny věci, ale tak snad aspoň částečně:

rozlišuj mezi třemi věcmi o kterých jsem tu mluvil. Původní řešení se týká seznamu proxy serverů, ten je třeba aktualizovat a stačí mi na to malý soubor. Já se rozhodl tento soubor pravidelně doplňovat o informace, takže se mohou ukládat dejme tomu i ajpiny několik staré dejme tomu 24 hodin nebo více. Zakládání databáze kvůli tomu mi příjde zbytečné.

Něco jiného je blokování uživatelů - psal jsem, že mi stačí udělat dynamicky se rozšiřující soubor (rozšíří se v místě druhého bajtu ajpiny když to bude potřebovat). Do toho souboru bude stejně tak rychlý přístup jako v tom řešení výše.

Zatřetí možnost udělat na podobném principu i databázi uživatelů. Samozžejmě výhoda je v tom, že nemusím se obtěžovat se zprávou externí databáze.

S těma ajpinama s nulama jsem se teda ještě nesetkal, ale mám pocit, že je velmi malá pravděpodobnost že na netu na ně někdy narazím. Jednoduché řešení: ajpina, která obsahuje na druhém bajtu nulu nebude moci být zapsána. Blokaci takového uživatele lbych možná mohl provést pomocí zablokování domény? Nebo zablokování celé sítě? Totiž k tomu slouží ta hlavička, kterou jsem tam přidal v nové verzi. Blokování prvních dvou bajtů a prvních třech bajtů a blokování domén.

Dneska končím.

webhope

Re:Binární zápis do souboru
« Odpověď #43 kdy: 15. 12. 2013, 10:04:54 »
Ano ve staré verzi byla chyba, nemá tam být
Kód: [Vybrat]
$segmentBegin = ($arr[0] - 1) * $this->segmentLength;
ale
Kód: [Vybrat]
$segmentBegin = ($arr[0] - 1) * $this->rowLength; // což je trojnásobek délky segmentu :-)
Citace
Nejlepší je stejně ukládat si počet záznamů, a potom nemusíš vůbec hledat konec, budeš ho vždy znát: začátek segmentu + počet záznamů * (1 bajt).

No jo, jenže já musím před přidáním ajpiny nejdříve zkontrolovat jestli ta IP již není v seznamu. A právě během této kontroly v nové verzi zjistím, kde pro daný řádek je konec dat. Takže vlastně začínám číst rovnou tam kde skončila kontrola :-) . Ale postřeh to byl dobrý, to tě chválím.

Citace
Špatně je ten "break", místo něho musí být "continue" a také to, že za smyčkou nevracíš true (to už jsi tam doplnil).
Ale abys ošetřil ty případné nuly v IP adresách, tak by jsi musel v každém průchodu kontrolovat všechny 3 bajty IP adresy.
V nové verzi je return true; Ale proč continue? Pro ten blok kde je break; platí
Kód: [Vybrat]
$byte == \x00 // první bajt je nulaCož znamená: pokud jsem našel konec dat, aniž bych našel hledanou IP adresu v seznamu, pak vracím true, protože je vše v pořádku. Funkce addIP pak může pokračovat v přidání ajpiny.

Co se týče databáze tak už chápu, vyjadřoval ses k tomu mému třetímu návrhu. Na zbytek tvé reakce bych odpověděl někdy později (binární strom). Dík za pomoc a diskusi.

webhope

Re:Binární zápis do souboru
« Odpověď #44 kdy: 15. 12. 2013, 12:43:55 »
Citace
Mám pocit, že jsi jednou psal, že zkoušíš udělat optimální algoritmus, jindy že ti rychlost postačuje. Kdyby jsi do jednoho souboru ukládal 250 x 32bit číslo jako IP adresu a při každém testu procházel vše, nemohlo by to být pomalejší než to máš teď.
jestli myslíš soubor txt, tak pomalejší by to bylo v tom, že by se vytvářelo pole o velikosti cca 250 prvků. Nějaké pole sice v nové třídě používám taky, to se ale prakticky vztahuje jen k těm vkládaným číslům, takže pokud vkládám 10 čísel, bude mít pole nakonec velikost 10 prvků. Ale rychlost u txt asi celkově malá, taky zanedbatelná.

Ještě jsem uvažoval nad tím jestli tam je možnost přepsání souboru txt, ale v módu append by to myslím nebylo možné.

Citace
To rozdělování IP adresy na jednotlivé bajty a jejich ukládání do zvláštních segmentů nemá ve tvé implementaci téměř žádný smysl, musíš stejně otestovat všech 250 záznamů.
Ne, testuji jen ten řádek, do kterého chci vkládat data. Tzn. pokud chci doplnit 10 ajpin, testuju jen deset řádků, ve kterých  prohledávám jen několik bajtů. V tom je právě rozdíl oproti txt souboru. Myslím, že budu doplňovat ajpiny každých 2 a půl minuty a za tu dobu by mohlo přibýt tak 3-10 ajpin odhadem. Možná jen 2-5 teď si nejsem jistý jak rychle se to objevuje.
Ještě ale dodatek: během iniciačního vkládání mohu vložit těch ajpin třeba 100 a v nich bude třeba čínská proxy, kde se opakuje bajt na třetím řádu, takže bloknu tuhle ajpinu obecně. Tím pádem ten počet ajpin co budu přidávat ještě ubude. Prostě do hlavičky zapíšu např. 124.50.64 a tyto ajpiny budou blokovány ještě před tím než začnu hloubkově porovnávat...

To mi připomíná, že musím ještě dodělat funkci na detekci podobných adres když vkládám adresy.
 
Citace
Výjimkou je pouze ten první bajt, který neukládáš, ale určuje ti segment, ale zase ti kvůli tomu narostla velikost dat 256x.
Ale velikost souboru tu nehraje roli. Ten soubor má 186 kBajt, ale je jedno jak je velký, i kdyby měl jeden 100 mega, tak by to nemělo mít vliv na rychlost.

Citace
Kdyby jsi byl důsledný, a udělal to i pro ostatní komponenty IP adresy, tak máš vlastně pole o 4 rozměrech, bitmapu o 222(?)*256*256*254 záznamech pro kompletní rozsah IP adres, tj. soubor o velikost 440MiB,
Jenže já dělám třídu a soubor na míru. Nepotřebuju tam vkládat něco s čím se v praxi nesetkám... Je to psáno tak aby to nylo na 3 bajty. Tvůj výpočet ale stejně nechápu, ale tím se nezatěžuj, to není nutné rozebírat. Jestli si ovšem nemyslel jeden řádek pro jednu adresu :-) lol - to by byl snad soubor o velikosti 4096 megabajt což je rovných 4 giga :-).

Citace
tam by jsi skutečně nemusel nic hledat, a vždy by jsi přečetl nebo zapsal pouze 4 bity. Nevýhoda - veliký soubor zabírající místo na disku, nic efektivnějšího nelze ale vymyslet.

Ten 4 gigabajtový soubor by byl super effektivní lol :-)

Citace
Budeš-li mít záznamy setříděné nebo v úplném binárním stromu, potřebuješ ke zjištění, zda IP adresa NENÍ přítomna v 250 záznamech MAXIMÁLNĚ 8 testů. Ty jich potřebuješ VŽDY 250 * 3, takže 750. Použití prvního bajtu IP adresy jako čísla segmentu ti to zredukovalo na 750 z 1000 testů ale 256x ti narostla velikost tabulky. Obě možností můžeš kombinovat a hledat kompromis mezi rychlostí a potřebnou velikostí tabulky, ale pokud se bude jednat víceméně o náhodné IP adresy, tak nemáš podle čeho optimalizovat.
Stále nevím co je to binární strom. Ale asi tuším co myslíš, ale nevím jak takovou věc zrealizovat. Ale nechtělo by se mi řešit třídu na binární strom. Myslím že to tak nechám :-)