Next: Expirační model a revalidace
Up: Implementace
Previous: Buckety
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
header.ftp?"ftp":"http",
req
header.host,
req
header.port,
*req
header.path?req
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 \)](img3.gif)
- 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
md5[0]%pet.asoc1size];
sprintf(entry
fname,"%s/%.2x/%.2x/%.2x/%s",
pet.buckets[bucketnum].name,
entry
md5[1]&0xf,
entry
md5[2]&0xf,
entry
md5[3]&0xf,
entry
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
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
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
srvsock
a req
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
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
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: Expirační model a revalidace
Up: Implementace
Previous: Buckety
Stanislav Pavlicek
2000-06-12