next up previous contents index
Next: Expirační model a revalidace Up: Implementace Previous: Buckety

Zpracování záznamu

Z každého požadavku je nutné sestavit jeho jednoznačnou identifikaci, ze které se opět jednoznačně1 určí jméno příslušného záznamu. Tato identifikace se skládá z jednobytového (unsigned char) kódu HTTP metody požadavku (viz položka url_method ve struktuře sg_entry_t) a URL, sestavené ze struktury request_cl následovně:

...

sprintf(url,"%s://%s:%d%s",

          req \( \rightarrow \)header.ftp?"ftp":"http",

          req \( \rightarrow \)header.host,

          req \( \rightarrow \)header.port,

          *req \( \rightarrow \)header.path?req \( \rightarrow \)header.path:"/");

...

Dalším krokem je přiřazení souboru na FS, k čemuž slouží následující datové struktury v globální struktuře pet_global_t:

int bucketcount;
- počet bucketů
sg_bucketinfo_t *buckets;
- pole o velikosti bucketcount, jehož položky obsahují informace o všech bucketech
int asoc1size;
- tato položka je rovna \( \sum _{i=0}^{bucketcount-1}buckets[i].sizefactor \)
int *asoc1;
- pole o velikosti asoc1size, které slouží jako ``směrovač'' do bucketů, obsahuje čísla bucketů (indexy do pole buckets), každé tolikrát kolik je sizefactor příslušného bucketu. Např. v konfiguraci z předchozí kapitoly (3 buckety, první měl sizefactor 3, druhý 5 a třetí 7) by pole mělo velikost 15 prvků (3+5+7) a obsahovalo 3x 3ku, 5x pětku a 7x 7mičku.
V případě zaplnění, tedy výpadku některého z bucketů, je vytvořeno modifikované asociativní pole asoc2 o velikosti asoc2size, do kterého nejsou zaplněné buckety zahrnuty. Pokud dojde k výpadku všech bucketů, pak je proměnná asoc2size nastavena na 0 a tím je zamezeno vytváření nových záznamů do doby, kdy se kapacita alespoň jednoho z bucketů uvolní.

Určení jména souboru je tedy provedeno následovně:

bucketnum=pet.asoc1[entry \( \rightarrow \)md5[0]%pet.asoc1size];

sprintf(entry \( \rightarrow \)fname,"%s/%.2x/%.2x/%.2x/%s",

        pet.buckets[bucketnum].name,

        entry \( \rightarrow \)md5[1]&0xf,

        entry \( \rightarrow \)md5[2]&0xf,

        entry \( \rightarrow \)md5[3]&0xf,

        entry \( \rightarrow \)md5s);

Pro práci se záznamem modul storage nabízí následující funkce:

int sg_initentry(request_cl *req,sg_entry_t *entry);
Tato funkce inicializuje strukturu sg_entry_t, na kterou ukazuje argumentem entry, tak aby odpovídala záznamu pro požadavek, daný argumentem req.

int sg_initentryurl(sg_entry_t *entry,
                    method_t method,
                    char *url);
Tato funkce může sloužit k vytvoření záznamu, který nepochází přímo z požadavku od klienta, její parametry tedy nejsou určeny z request_cl, ale jsou přímo specifikovány v argumentech. Jejím výsledkem je inicializovaná struktura sg_entry_t, která obsahuje md5digest a jméno souboru, přiřazené tomuto záznamu.

int sg_updateentryhash(sg_entry_t *entry,
                       unsigned char *string,
                       int slen);
V některých případech je nutné připojit k url v sg_entry_t další informaci, teprve díky které bude tento řetězec jednoznačně identifikovat požadavek klienta2, k tomu slouží výše uvedená funkce s následujícími parametry:

entry
- záznam, jehož URL má být modifikována
string
- řetězec, který bude připojen za url v položce entry a kterým bude md5digest aktualizován
slen
- délka počáteční části řetězce, který bude použit pro aktualizaci
int sg_destroyentry(sg_entry_t *entry);
Tato funkce uvolní všechny datové struktury spojené s příslušným záznamem, na který ukazuje argument entry. Je typicky volána po ukončení zpracování záznamu.

int sg_getentryfd(sg_entry_t *entry,bool create);
Funkce nastavuje položku entry \( \rightarrow \)efd, což je file descriptor daného záznamu. Pokud uspěje, vrací RET_OK, jinak RET_ERR.

entry
- ukazatel na záznam
create
- pokud je tento argument nastaven na TRUE, funkce smaže soubor (pokud již existuje) a vrátí filedescriptor nově vytvořeného záznamu, pokud je argument nastaven na FALSE a soubor existuje, funkce nastaví entry \( \rightarrow \)efd a skončí s RET_OK, v opačném případě vrací RET_ERR
int sg_transferdata(request_cl *req,sg_entry_t *entry);
Tato funkce je zodpovědná za přenos dat z cílového serveru klientovi a případné vytvoření záznamu, pokud HTTP transakce splňuje požadavky pro cachování. Vstupními argument jsou ukazatel na strukturu request_cl, na které musí být provedeno spojení s cílovým serverem a klientem (otevřené sockety req \( \rightarrow \)srvsock a req \( \rightarrow \)sock) a na socket cílového serveru musí být odeslán požadavek. V první fází je načtena hlavička z odpovědi serveru, je na ní provedena klasifikace a je určeno zda je dokument cachovatelný. Pokud ano, data jsou přenášena klientovi současně s vytvářením záznamu, pokud ne, záznam není vytvořen a data jsou jen kopírována na klientův socket.

int sg_checkentry(sg_entry_t *entry);
 Úkolem této funkce je analýza záznamu, která zahrnuje vyhledání záznamu na FS a jeho následné zpracování mechanismem expiračního modelu (viz oddíl Expirační model a revalidace). Výsledkem této funkce je nastavení položky entry \( \rightarrow \)status, která může nabývat hodnot SG_MISS, pokud záznam není nalezen, SG_HIT_DISK pokud záznam existuje a je čerstvý a SG_HIT_DISK_EXPIRED, pokud záznam existuje, ale je starý. V případě, že funkce nalezne záznam na disku, ponechává otevřený file descriptor v entry \( \rightarrow \)efd, připravený pro další následné zpracování.

int sg_process(sg_entry_t *entry);
sg_process spolu s sg_transferdata tvoří v podstatě základní interface modulu storage, kterým jsou provázány s kostrou celého proxy serveru. Funkce nejdříve volá sg_checkentry pro klasifikaci záznamu, přičemž nově nastavený status záznamu rozhoduje o dalším zpracování. V případě SG_MISS funkce skončí bez dalších akcí, pokud je status nastaven na SG_HIT_DISK, záznam je tedy čerstvý a je neprodleně odeslán klientovi, čímž je zpracování také u konce. Složitější akce nastane v případě statusu SG_HIT_DISK_EXPIRED, který signalizuje, že je na záznamu nutné provést revalidaci (detailní popis průběhu revalidace je v oddílu Expirační model a revalidace), ovšem pouze v případě, že není nastavena konfigurační volba ``sg_revalidate_through_modules''. Při aktivaci této volby je v případě expirace předáno řízení ostatním modulům a to z důvodu možnosti umístění proxy za firewallem, kdy není možné kontaktovat cílový server přímo, ale pouze prostřednictvím nadřízené proxy (viz dokumentace k ICP modulu)

int sg_initheader(int fd,sg_header_t *resp);

int sg_destroyheader(sg_header_t *resp);

char *sg_getheaderfield(sg_header_t *resp,char *fname);

Výše zmíněné funkce umožňují získání položek a stavového kódu odpovědi z cílového serveru, případně libovolného záznamu na FS. Argumentem funkce sg_initheader je file descriptor, ze kterého je možné číst hlavičku odpovědi (může to být buď socket, na který byl odeslán požadavek nebo soubor záznamu na FS), výsledkem pak inicializovaná struktura sg_header_t. Funkce sg_getheaderfield vyhledá v hašovací tabulce položku z hlavičky a vrátí ukazatel na její hodnotu (NULL pokud se daná položka v hlavičce nevyskytuje) a konečně funkce sg_destroyheader uvolní všechny datové struktury alokované funkcí sg_initheader.


next up previous contents index
Next: Expirační model a revalidace Up: Implementace Previous: Buckety
Stanislav Pavlicek
2000-06-12