--------------------- PatchSet 5312 Date: 2002/10/09 04:52:02 Author: rbcollins Branch: rbcollins_cxxtest Tag: (none) Log: and more Members: src/Makefile.am:1.29.2.18->1.29.2.19 src/Store.h:1.1.2.5->1.1.2.6 src/filemap.c:1.6->1.6.44.1(DEAD) src/filemap.cc:1.1->1.1.2.1 src/pconn.c:1.7.18.1->1.7.18.2(DEAD) src/pconn.cc:1.1->1.1.2.1 src/store.cc:1.1.2.6->1.1.2.7 src/store_io.c:1.3.44.1->1.3.44.2(DEAD) src/store_io.cc:1.1->1.1.2.1 src/win32.c:1.6->1.6.14.1(DEAD) src/win32.cc:1.1->1.1.2.1 Index: squid/src/Makefile.am =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Makefile.am,v retrieving revision 1.29.2.18 retrieving revision 1.29.2.19 diff -u -r1.29.2.18 -r1.29.2.19 --- squid/src/Makefile.am 9 Oct 2002 04:39:55 -0000 1.29.2.18 +++ squid/src/Makefile.am 9 Oct 2002 04:52:02 -0000 1.29.2.19 @@ -63,7 +63,7 @@ endif if ENABLE_WIN32SPECIFIC -WIN32SOURCE = win32.c +WIN32SOURCE = win32.cc else WIN32SOURCE = endif @@ -113,7 +113,7 @@ unlinkd.cc \ ssl_support.c \ ssl_support.h \ - win32.c + win32.cc squid_SOURCES = \ access_log.cc \ @@ -147,7 +147,7 @@ event.c \ external_acl.cc \ fd.c \ - filemap.c \ + filemap.cc \ forward.c \ fqdncache.c \ ftp.c \ @@ -186,7 +186,7 @@ net_db.c \ Packer.cc \ $(XPROF_STATS_SOURCE) \ - pconn.c \ + pconn.cc \ peer_digest.c \ peer_select.c \ protos.h \ @@ -203,7 +203,7 @@ String.cc \ stmem.cc \ store.cc \ - store_io.c \ + store_io.cc \ StoreIOBuffer.h \ store_client.cc \ StoreClient.h \ Index: squid/src/Store.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/Store.h,v retrieving revision 1.1.2.5 retrieving revision 1.1.2.6 diff -u -r1.1.2.5 -r1.1.2.6 --- squid/src/Store.h 6 Oct 2002 03:52:33 -0000 1.1.2.5 +++ squid/src/Store.h 9 Oct 2002 04:52:02 -0000 1.1.2.6 @@ -1,6 +1,6 @@ /* - * $Id: Store.h,v 1.1.2.5 2002/10/06 03:52:33 rbcollins Exp $ + * $Id: Store.h,v 1.1.2.6 2002/10/09 04:52:02 rbcollins Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -135,7 +135,7 @@ SQUIDCEXTERN void storeAppendVPrintf(StoreEntry *, const char *, va_list ap); SQUIDCEXTERN int storeCheckCachable(StoreEntry * e); SQUIDCEXTERN void storeSetPrivateKey(StoreEntry *); -SQUIDCEXTERN int objectLen(const StoreEntry * e); +SQUIDCEXTERN ssize_t objectLen(const StoreEntry * e); SQUIDCEXTERN int contentLen(const StoreEntry * e); SQUIDCEXTERN HttpReply *storeEntryReply(StoreEntry *); SQUIDCEXTERN int storeTooManyDiskFilesOpen(void); --- squid/src/filemap.c Wed Feb 14 01:07:37 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,172 +0,0 @@ - -/* - * $Id: filemap.c,v 1.6 2001/10/24 09:42:12 squidadm Exp $ - * - * DEBUG: section 8 Swap File Bitmap - * AUTHOR: Harvest Derived - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "squid.h" - -/* Number of bits in a long */ -#if SIZEOF_LONG == 8 -#define LONG_BIT_SHIFT 6 -#define BITS_IN_A_LONG 0x40 -#define LONG_BIT_MASK 0x3F -#define ALL_ONES (unsigned long) 0xFFFFFFFFFFFFFFFF -#elif SIZEOF_LONG == 4 -#define LONG_BIT_SHIFT 5 -#define BITS_IN_A_LONG 0x20 -#define LONG_BIT_MASK 0x1F -#define ALL_ONES (unsigned long) 0xFFFFFFFF -#else -#define LONG_BIT_SHIFT 5 -#define BITS_IN_A_LONG 0x20 -#define LONG_BIT_MASK 0x1F -#define ALL_ONES (unsigned long) 0xFFFFFFFF -#endif - -#define FM_INITIAL_NUMBER (1<<14) - -fileMap * -file_map_create(void) -{ - fileMap *fm = xcalloc(1, sizeof(fileMap)); - fm->max_n_files = FM_INITIAL_NUMBER; - fm->nwords = fm->max_n_files >> LONG_BIT_SHIFT; - debug(8, 3) ("file_map_create: creating space for %d files\n", fm->max_n_files); - debug(8, 5) ("--> %d words of %d bytes each\n", - fm->nwords, (int) sizeof(*fm->file_map)); - fm->file_map = xcalloc(fm->nwords, sizeof(*fm->file_map)); - /* XXX account fm->file_map */ - return fm; -} - -static void -file_map_grow(fileMap * fm) -{ - int old_sz = fm->nwords * sizeof(*fm->file_map); - void *old_map = fm->file_map; - fm->max_n_files <<= 1; - assert(fm->max_n_files <= (1 << 24)); /* swap_filen is 25 bits, signed */ - fm->nwords = fm->max_n_files >> LONG_BIT_SHIFT; - debug(8, 3) ("file_map_grow: creating space for %d files\n", fm->max_n_files); - fm->file_map = xcalloc(fm->nwords, sizeof(*fm->file_map)); - debug(8, 3) ("copying %d old bytes\n", old_sz); - xmemcpy(fm->file_map, old_map, old_sz); - xfree(old_map); - /* XXX account fm->file_map */ -} - -int -file_map_bit_set(fileMap * fm, int file_number) -{ - unsigned long bitmask = (1L << (file_number & LONG_BIT_MASK)); - while (file_number >= fm->max_n_files) - file_map_grow(fm); - fm->file_map[file_number >> LONG_BIT_SHIFT] |= bitmask; - fm->n_files_in_map++; - return file_number; -} - -/* - * WARNING: file_map_bit_reset does not perform array bounds - * checking! It assumes that 'file_number' is valid, and that the - * bit is already set. The caller must verify both of those - * conditions by calling file_map_bit_test() first. - */ -void -file_map_bit_reset(fileMap * fm, int file_number) -{ - unsigned long bitmask = (1L << (file_number & LONG_BIT_MASK)); - fm->file_map[file_number >> LONG_BIT_SHIFT] &= ~bitmask; - fm->n_files_in_map--; -} - -int -file_map_bit_test(fileMap * fm, int file_number) -{ - unsigned long bitmask = (1L << (file_number & LONG_BIT_MASK)); - if (file_number >= fm->max_n_files) - return 0; - /* be sure the return value is an int, not a u_long */ - return (fm->file_map[file_number >> LONG_BIT_SHIFT] & bitmask ? 1 : 0); -} - -int -file_map_allocate(fileMap * fm, int suggestion) -{ - int word; - int bit; - int count; - if (suggestion >= fm->max_n_files) - suggestion = 0; - if (!file_map_bit_test(fm, suggestion)) - return suggestion; - word = suggestion >> LONG_BIT_SHIFT; - for (count = 0; count < fm->nwords; count++) { - if (fm->file_map[word] != ALL_ONES) - break; - word = (word + 1) % fm->nwords; - } - for (bit = 0; bit < BITS_IN_A_LONG; bit++) { - suggestion = ((unsigned long) word << LONG_BIT_SHIFT) | bit; - if (!file_map_bit_test(fm, suggestion)) { - return suggestion; - } - } - debug(8, 3) ("growing from file_map_allocate\n"); - file_map_grow(fm); - return file_map_allocate(fm, fm->max_n_files >> 1); -} - -void -filemapFreeMemory(fileMap * fm) -{ - safe_free(fm->file_map); - safe_free(fm); -} - -#ifdef TEST - -#define TEST_SIZE 1<<16 -main(argc, argv) -{ - int i; - - fm = file_map_create(TEST_SIZE); - - for (i = 0; i < TEST_SIZE; ++i) { - file_map_bit_set(i); - assert(file_map_bit_test(i)); - file_map_bit_reset(i); - } -} -#endif --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/filemap.cc Wed Feb 14 01:07:37 2007 @@ -0,0 +1,172 @@ + +/* + * $Id: filemap.cc,v 1.1.2.1 2002/10/09 04:52:02 rbcollins Exp $ + * + * DEBUG: section 8 Swap File Bitmap + * AUTHOR: Harvest Derived + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "squid.h" + +/* Number of bits in a long */ +#if SIZEOF_LONG == 8 +#define LONG_BIT_SHIFT 6 +#define BITS_IN_A_LONG 0x40 +#define LONG_BIT_MASK 0x3F +#define ALL_ONES (unsigned long) 0xFFFFFFFFFFFFFFFF +#elif SIZEOF_LONG == 4 +#define LONG_BIT_SHIFT 5 +#define BITS_IN_A_LONG 0x20 +#define LONG_BIT_MASK 0x1F +#define ALL_ONES (unsigned long) 0xFFFFFFFF +#else +#define LONG_BIT_SHIFT 5 +#define BITS_IN_A_LONG 0x20 +#define LONG_BIT_MASK 0x1F +#define ALL_ONES (unsigned long) 0xFFFFFFFF +#endif + +#define FM_INITIAL_NUMBER (1<<14) + +fileMap * +file_map_create(void) +{ + fileMap *fm = (fileMap *)xcalloc(1, sizeof(fileMap)); + fm->max_n_files = FM_INITIAL_NUMBER; + fm->nwords = fm->max_n_files >> LONG_BIT_SHIFT; + debug(8, 3) ("file_map_create: creating space for %d files\n", fm->max_n_files); + debug(8, 5) ("--> %d words of %d bytes each\n", + fm->nwords, (int) sizeof(*fm->file_map)); + fm->file_map = (unsigned long *)xcalloc(fm->nwords, sizeof(*fm->file_map)); + /* XXX account fm->file_map */ + return fm; +} + +static void +file_map_grow(fileMap * fm) +{ + int old_sz = fm->nwords * sizeof(*fm->file_map); + void *old_map = fm->file_map; + fm->max_n_files <<= 1; + assert(fm->max_n_files <= (1 << 24)); /* swap_filen is 25 bits, signed */ + fm->nwords = fm->max_n_files >> LONG_BIT_SHIFT; + debug(8, 3) ("file_map_grow: creating space for %d files\n", fm->max_n_files); + fm->file_map = (unsigned long *)xcalloc(fm->nwords, sizeof(*fm->file_map)); + debug(8, 3) ("copying %d old bytes\n", old_sz); + xmemcpy(fm->file_map, old_map, old_sz); + xfree(old_map); + /* XXX account fm->file_map */ +} + +int +file_map_bit_set(fileMap * fm, int file_number) +{ + unsigned long bitmask = (1L << (file_number & LONG_BIT_MASK)); + while (file_number >= fm->max_n_files) + file_map_grow(fm); + fm->file_map[file_number >> LONG_BIT_SHIFT] |= bitmask; + fm->n_files_in_map++; + return file_number; +} + +/* + * WARNING: file_map_bit_reset does not perform array bounds + * checking! It assumes that 'file_number' is valid, and that the + * bit is already set. The caller must verify both of those + * conditions by calling file_map_bit_test() first. + */ +void +file_map_bit_reset(fileMap * fm, int file_number) +{ + unsigned long bitmask = (1L << (file_number & LONG_BIT_MASK)); + fm->file_map[file_number >> LONG_BIT_SHIFT] &= ~bitmask; + fm->n_files_in_map--; +} + +int +file_map_bit_test(fileMap * fm, int file_number) +{ + unsigned long bitmask = (1L << (file_number & LONG_BIT_MASK)); + if (file_number >= fm->max_n_files) + return 0; + /* be sure the return value is an int, not a u_long */ + return (fm->file_map[file_number >> LONG_BIT_SHIFT] & bitmask ? 1 : 0); +} + +int +file_map_allocate(fileMap * fm, int suggestion) +{ + int word; + int bit; + int count; + if (suggestion >= fm->max_n_files) + suggestion = 0; + if (!file_map_bit_test(fm, suggestion)) + return suggestion; + word = suggestion >> LONG_BIT_SHIFT; + for (count = 0; count < fm->nwords; count++) { + if (fm->file_map[word] != ALL_ONES) + break; + word = (word + 1) % fm->nwords; + } + for (bit = 0; bit < BITS_IN_A_LONG; bit++) { + suggestion = ((unsigned long) word << LONG_BIT_SHIFT) | bit; + if (!file_map_bit_test(fm, suggestion)) { + return suggestion; + } + } + debug(8, 3) ("growing from file_map_allocate\n"); + file_map_grow(fm); + return file_map_allocate(fm, fm->max_n_files >> 1); +} + +void +filemapFreeMemory(fileMap * fm) +{ + safe_free(fm->file_map); + safe_free(fm); +} + +#ifdef TEST + +#define TEST_SIZE 1<<16 +main(argc, argv) +{ + int i; + + fm = file_map_create(TEST_SIZE); + + for (i = 0; i < TEST_SIZE; ++i) { + file_map_bit_set(i); + assert(file_map_bit_test(i)); + file_map_bit_reset(i); + } +} +#endif --- squid/src/pconn.c Wed Feb 14 01:07:37 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,263 +0,0 @@ - -/* - * $Id: pconn.c,v 1.7.18.1 2002/10/04 07:07:27 rbcollins Exp $ - * - * DEBUG: section 48 Persistent Connections - * AUTHOR: Duane Wessels - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "squid.h" -#include "Store.h" - -struct _pconn { - hash_link hash; /* must be first */ - int *fds; - int nfds_alloc; - int nfds; -}; -typedef struct _pconn pconn; - -#define PCONN_FDS_SZ 8 /* pconn set size, increase for better memcache hit rate */ -#define PCONN_HIST_SZ (1<<16) -int client_pconn_hist[PCONN_HIST_SZ]; -int server_pconn_hist[PCONN_HIST_SZ]; - -static PF pconnRead; -static PF pconnTimeout; -static const char *pconnKey(const char *host, u_short port); -static hash_table *table = NULL; -static struct _pconn *pconnNew(const char *key); -static void pconnDelete(struct _pconn *p); -static void pconnRemoveFD(struct _pconn *p, int fd); -static OBJH pconnHistDump; -static MemPool *pconn_fds_pool = NULL; -CBDATA_TYPE(pconn); - - - -static const char * -pconnKey(const char *host, u_short port) -{ - LOCAL_ARRAY(char, buf, SQUIDHOSTNAMELEN + 10); - snprintf(buf, SQUIDHOSTNAMELEN + 10, "%s.%d", host, (int) port); - return buf; -} - -static struct _pconn * -pconnNew(const char *key) -{ - pconn *p; - CBDATA_INIT_TYPE(pconn); - p = cbdataAlloc(pconn); - p->hash.key = xstrdup(key); - p->nfds_alloc = PCONN_FDS_SZ; - p->fds = memPoolAlloc(pconn_fds_pool); - debug(48, 3) ("pconnNew: adding %s\n", hashKeyStr(&p->hash)); - hash_join(table, &p->hash); - return p; -} - -static void -pconnDelete(struct _pconn *p) -{ - debug(48, 3) ("pconnDelete: deleting %s\n", hashKeyStr(&p->hash)); - hash_remove_link(table, (hash_link *) p); - if (p->nfds_alloc == PCONN_FDS_SZ) - memPoolFree(pconn_fds_pool, p->fds); - else - xfree(p->fds); - xfree(p->hash.key); - cbdataFree(p); -} - -static void -pconnRemoveFD(struct _pconn *p, int fd) -{ - int i; - for (i = 0; i < p->nfds; i++) { - if (p->fds[i] == fd) - break; - } - assert(i < p->nfds); - debug(48, 3) ("pconnRemoveFD: found FD %d at index %d\n", fd, i); - for (; i < p->nfds - 1; i++) - p->fds[i] = p->fds[i + 1]; - if (--p->nfds == 0) - pconnDelete(p); -} - -static void -pconnTimeout(int fd, void *data) -{ - struct _pconn *p = data; - assert(table != NULL); - debug(48, 3) ("pconnTimeout: FD %d %s\n", fd, hashKeyStr(&p->hash)); - pconnRemoveFD(p, fd); - comm_close(fd); -} - -static void -pconnRead(int fd, void *data) -{ - LOCAL_ARRAY(char, buf, 256); - struct _pconn *p = data; - int n; - assert(table != NULL); - statCounter.syscalls.sock.reads++; - n = FD_READ_METHOD(fd, buf, 256); - debug(48, 3) ("pconnRead: %d bytes from FD %d, %s\n", n, fd, - hashKeyStr(&p->hash)); - pconnRemoveFD(p, fd); - comm_close(fd); -} - -static void -pconnHistDump(StoreEntry * e) -{ - int i; - storeAppendPrintf(e, - "Client-side persistent connection counts:\n" - "\n" - "\treq/\n" - "\tconn count\n" - "\t---- ---------\n"); - for (i = 0; i < PCONN_HIST_SZ; i++) { - if (client_pconn_hist[i] == 0) - continue; - storeAppendPrintf(e, "\t%4d %9d\n", i, client_pconn_hist[i]); - } - storeAppendPrintf(e, - "\n" - "Server-side persistent connection counts:\n" - "\n" - "\treq/\n" - "\tconn count\n" - "\t---- ---------\n"); - for (i = 0; i < PCONN_HIST_SZ; i++) { - if (server_pconn_hist[i] == 0) - continue; - storeAppendPrintf(e, "\t%4d %9d\n", i, server_pconn_hist[i]); - } -} - -/* ========== PUBLIC FUNCTIONS ============================================ */ - - -void -pconnInit(void) -{ - int i; - assert(table == NULL); - table = hash_create((HASHCMP *) strcmp, 229, hash_string); - for (i = 0; i < PCONN_HIST_SZ; i++) { - client_pconn_hist[i] = 0; - server_pconn_hist[i] = 0; - } - pconn_fds_pool = memPoolCreate("pconn_fds", PCONN_FDS_SZ * sizeof(int)); - - cachemgrRegister("pconn", - "Persistent Connection Utilization Histograms", - pconnHistDump, 0, 1); - debug(48, 3) ("persistent connection module initialized\n"); -} - -void -pconnPush(int fd, const char *host, u_short port) -{ - struct _pconn *p; - int *old; - LOCAL_ARRAY(char, key, SQUIDHOSTNAMELEN + 10); - LOCAL_ARRAY(char, desc, FD_DESC_SZ); - if (fdNFree() < (RESERVED_FD << 1)) { - debug(48, 3) ("pconnPush: Not many unused FDs\n"); - comm_close(fd); - return; - } else if (shutting_down) { - comm_close(fd); - return; - } - assert(table != NULL); - strcpy(key, pconnKey(host, port)); - p = (struct _pconn *) hash_lookup(table, key); - if (p == NULL) - p = pconnNew(key); - if (p->nfds == p->nfds_alloc) { - debug(48, 3) ("pconnPush: growing FD array\n"); - p->nfds_alloc <<= 1; - old = p->fds; - p->fds = xmalloc(p->nfds_alloc * sizeof(int)); - xmemcpy(p->fds, old, p->nfds * sizeof(int)); - if (p->nfds == PCONN_FDS_SZ) - memPoolFree(pconn_fds_pool, old); - else - xfree(old); - } - p->fds[p->nfds++] = fd; - commSetSelect(fd, COMM_SELECT_READ, pconnRead, p, 0); - commSetTimeout(fd, Config.Timeout.pconn, pconnTimeout, p); - snprintf(desc, FD_DESC_SZ, "%s idle connection", host); - fd_note(fd, desc); - debug(48, 3) ("pconnPush: pushed FD %d for %s\n", fd, key); -} - -int -pconnPop(const char *host, u_short port) -{ - struct _pconn *p; - hash_link *hptr; - int fd = -1; - LOCAL_ARRAY(char, key, SQUIDHOSTNAMELEN + 10); - assert(table != NULL); - strcpy(key, pconnKey(host, port)); - hptr = hash_lookup(table, key); - if (hptr != NULL) { - p = (struct _pconn *) hptr; - assert(p->nfds > 0); - fd = p->fds[0]; - pconnRemoveFD(p, fd); - commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0); - commSetTimeout(fd, -1, NULL, NULL); - } - return fd; -} - -void -pconnHistCount(int what, int i) -{ - if (i >= PCONN_HIST_SZ) - i = PCONN_HIST_SZ - 1; - /* what == 0 for client, 1 for server */ - if (what == 0) - client_pconn_hist[i]++; - else if (what == 1) - server_pconn_hist[i]++; - else - assert(0); -} --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/pconn.cc Wed Feb 14 01:07:37 2007 @@ -0,0 +1,263 @@ + +/* + * $Id: pconn.cc,v 1.1.2.1 2002/10/09 04:52:02 rbcollins Exp $ + * + * DEBUG: section 48 Persistent Connections + * AUTHOR: Duane Wessels + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "squid.h" +#include "Store.h" + +struct _pconn { + hash_link hash; /* must be first */ + int *fds; + int nfds_alloc; + int nfds; +}; +typedef struct _pconn pconn; + +#define PCONN_FDS_SZ 8 /* pconn set size, increase for better memcache hit rate */ +#define PCONN_HIST_SZ (1<<16) +int client_pconn_hist[PCONN_HIST_SZ]; +int server_pconn_hist[PCONN_HIST_SZ]; + +static PF pconnRead; +static PF pconnTimeout; +static const char *pconnKey(const char *host, u_short port); +static hash_table *table = NULL; +static struct _pconn *pconnNew(const char *key); +static void pconnDelete(struct _pconn *p); +static void pconnRemoveFD(struct _pconn *p, int fd); +static OBJH pconnHistDump; +static MemPool *pconn_fds_pool = NULL; +CBDATA_TYPE(pconn); + + + +static const char * +pconnKey(const char *host, u_short port) +{ + LOCAL_ARRAY(char, buf, SQUIDHOSTNAMELEN + 10); + snprintf(buf, SQUIDHOSTNAMELEN + 10, "%s.%d", host, (int) port); + return buf; +} + +static struct _pconn * +pconnNew(const char *key) +{ + pconn *p; + CBDATA_INIT_TYPE(pconn); + p = cbdataAlloc(pconn); + p->hash.key = xstrdup(key); + p->nfds_alloc = PCONN_FDS_SZ; + p->fds = (int *)memPoolAlloc(pconn_fds_pool); + debug(48, 3) ("pconnNew: adding %s\n", hashKeyStr(&p->hash)); + hash_join(table, &p->hash); + return p; +} + +static void +pconnDelete(struct _pconn *p) +{ + debug(48, 3) ("pconnDelete: deleting %s\n", hashKeyStr(&p->hash)); + hash_remove_link(table, (hash_link *) p); + if (p->nfds_alloc == PCONN_FDS_SZ) + memPoolFree(pconn_fds_pool, p->fds); + else + xfree(p->fds); + xfree(p->hash.key); + cbdataFree(p); +} + +static void +pconnRemoveFD(struct _pconn *p, int fd) +{ + int i; + for (i = 0; i < p->nfds; i++) { + if (p->fds[i] == fd) + break; + } + assert(i < p->nfds); + debug(48, 3) ("pconnRemoveFD: found FD %d at index %d\n", fd, i); + for (; i < p->nfds - 1; i++) + p->fds[i] = p->fds[i + 1]; + if (--p->nfds == 0) + pconnDelete(p); +} + +static void +pconnTimeout(int fd, void *data) +{ + struct _pconn *p = (_pconn *)data; + assert(table != NULL); + debug(48, 3) ("pconnTimeout: FD %d %s\n", fd, hashKeyStr(&p->hash)); + pconnRemoveFD(p, fd); + comm_close(fd); +} + +static void +pconnRead(int fd, void *data) +{ + LOCAL_ARRAY(char, buf, 256); + struct _pconn *p = (_pconn *)data; + int n; + assert(table != NULL); + statCounter.syscalls.sock.reads++; + n = FD_READ_METHOD(fd, buf, 256); + debug(48, 3) ("pconnRead: %d bytes from FD %d, %s\n", n, fd, + hashKeyStr(&p->hash)); + pconnRemoveFD(p, fd); + comm_close(fd); +} + +static void +pconnHistDump(StoreEntry * e) +{ + int i; + storeAppendPrintf(e, + "Client-side persistent connection counts:\n" + "\n" + "\treq/\n" + "\tconn count\n" + "\t---- ---------\n"); + for (i = 0; i < PCONN_HIST_SZ; i++) { + if (client_pconn_hist[i] == 0) + continue; + storeAppendPrintf(e, "\t%4d %9d\n", i, client_pconn_hist[i]); + } + storeAppendPrintf(e, + "\n" + "Server-side persistent connection counts:\n" + "\n" + "\treq/\n" + "\tconn count\n" + "\t---- ---------\n"); + for (i = 0; i < PCONN_HIST_SZ; i++) { + if (server_pconn_hist[i] == 0) + continue; + storeAppendPrintf(e, "\t%4d %9d\n", i, server_pconn_hist[i]); + } +} + +/* ========== PUBLIC FUNCTIONS ============================================ */ + + +void +pconnInit(void) +{ + int i; + assert(table == NULL); + table = hash_create((HASHCMP *) strcmp, 229, hash_string); + for (i = 0; i < PCONN_HIST_SZ; i++) { + client_pconn_hist[i] = 0; + server_pconn_hist[i] = 0; + } + pconn_fds_pool = memPoolCreate("pconn_fds", PCONN_FDS_SZ * sizeof(int)); + + cachemgrRegister("pconn", + "Persistent Connection Utilization Histograms", + pconnHistDump, 0, 1); + debug(48, 3) ("persistent connection module initialized\n"); +} + +void +pconnPush(int fd, const char *host, u_short port) +{ + struct _pconn *p; + int *old; + LOCAL_ARRAY(char, key, SQUIDHOSTNAMELEN + 10); + LOCAL_ARRAY(char, desc, FD_DESC_SZ); + if (fdNFree() < (RESERVED_FD << 1)) { + debug(48, 3) ("pconnPush: Not many unused FDs\n"); + comm_close(fd); + return; + } else if (shutting_down) { + comm_close(fd); + return; + } + assert(table != NULL); + strcpy(key, pconnKey(host, port)); + p = (struct _pconn *) hash_lookup(table, key); + if (p == NULL) + p = pconnNew(key); + if (p->nfds == p->nfds_alloc) { + debug(48, 3) ("pconnPush: growing FD array\n"); + p->nfds_alloc <<= 1; + old = p->fds; + p->fds = (int *)xmalloc(p->nfds_alloc * sizeof(int)); + xmemcpy(p->fds, old, p->nfds * sizeof(int)); + if (p->nfds == PCONN_FDS_SZ) + memPoolFree(pconn_fds_pool, old); + else + xfree(old); + } + p->fds[p->nfds++] = fd; + commSetSelect(fd, COMM_SELECT_READ, pconnRead, p, 0); + commSetTimeout(fd, Config.Timeout.pconn, pconnTimeout, p); + snprintf(desc, FD_DESC_SZ, "%s idle connection", host); + fd_note(fd, desc); + debug(48, 3) ("pconnPush: pushed FD %d for %s\n", fd, key); +} + +int +pconnPop(const char *host, u_short port) +{ + struct _pconn *p; + hash_link *hptr; + int fd = -1; + LOCAL_ARRAY(char, key, SQUIDHOSTNAMELEN + 10); + assert(table != NULL); + strcpy(key, pconnKey(host, port)); + hptr = (hash_link *)hash_lookup(table, key); + if (hptr != NULL) { + p = (struct _pconn *) hptr; + assert(p->nfds > 0); + fd = p->fds[0]; + pconnRemoveFD(p, fd); + commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0); + commSetTimeout(fd, -1, NULL, NULL); + } + return fd; +} + +void +pconnHistCount(int what, int i) +{ + if (i >= PCONN_HIST_SZ) + i = PCONN_HIST_SZ - 1; + /* what == 0 for client, 1 for server */ + if (what == 0) + client_pconn_hist[i]++; + else if (what == 1) + server_pconn_hist[i]++; + else + assert(0); +} Index: squid/src/store.cc =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/store.cc,v retrieving revision 1.1.2.6 retrieving revision 1.1.2.7 diff -u -r1.1.2.6 -r1.1.2.7 --- squid/src/store.cc 6 Oct 2002 03:52:33 -0000 1.1.2.6 +++ squid/src/store.cc 9 Oct 2002 04:52:02 -0000 1.1.2.7 @@ -1,6 +1,6 @@ /* - * $Id: store.cc,v 1.1.2.6 2002/10/06 03:52:33 rbcollins Exp $ + * $Id: store.cc,v 1.1.2.7 2002/10/09 04:52:02 rbcollins Exp $ * * DEBUG: section 20 Storage Manager * AUTHOR: Harvest Derived @@ -73,7 +73,7 @@ StoreEntry *e; } lock_ctrl_t; -extern "C" OBJH storeIOStats; +extern OBJH storeIOStats; /* * local function prototypes @@ -1340,7 +1340,7 @@ storeSwapOut(e); } -int +ssize_t objectLen(const StoreEntry * e) { assert(e->mem_obj != NULL); --- squid/src/store_io.c Wed Feb 14 01:07:37 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,119 +0,0 @@ -#include "squid.h" -#include "Store.h" - - -static struct { - struct { - int calls; - int select_fail; - int create_fail; - int success; - } create; -} store_io_stats; - -OBJH storeIOStats; - -/* - * submit a request to create a cache object for writing. - * The StoreEntry structure is sent as a hint to the filesystem - * to what will be stored in this object, to allow the filesystem - * to select different polices depending on object size or type. - */ -storeIOState * -storeCreate(StoreEntry * e, STIOCB * file_callback, STIOCB * close_callback, void *callback_data) -{ - size_t objsize; - sdirno dirn; - SwapDir *SD; - storeIOState *sio; - - store_io_stats.create.calls++; - /* This is just done for logging purposes */ - objsize = objectLen(e); - if (objsize != -1) - objsize += e->mem_obj->swap_hdr_sz; - - /* - * Pick the swapdir - * We assume that the header has been packed by now .. - */ - dirn = storeDirSelectSwapDir(e); - if (dirn == -1) { - debug(20, 2) ("storeCreate: no valid swapdirs for this object\n"); - store_io_stats.create.select_fail++; - return NULL; - } - debug(20, 2) ("storeCreate: Selected dir '%d' for obj size '%ld'\n", dirn, (long int) objsize); - SD = &Config.cacheSwap.swapDirs[dirn]; - - /* Now that we have a fs to use, call its storeCreate function */ - sio = SD->obj.create(SD, e, file_callback, close_callback, callback_data); - if (NULL == sio) - store_io_stats.create.create_fail++; - else - store_io_stats.create.success++; - return sio; -} - - -/* - * storeOpen() is purely for reading .. - */ -storeIOState * -storeOpen(StoreEntry * e, STFNCB * file_callback, STIOCB * callback, - void *callback_data) -{ - SwapDir *SD = &Config.cacheSwap.swapDirs[e->swap_dirn]; - return SD->obj.open(SD, e, file_callback, callback, callback_data); -} - -void -storeClose(storeIOState * sio) -{ - SwapDir *SD = &Config.cacheSwap.swapDirs[sio->swap_dirn]; - if (sio->flags.closing) - return; - sio->flags.closing = 1; - SD->obj.close(SD, sio); -} - -void -storeRead(storeIOState * sio, char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data) -{ - SwapDir *SD = &Config.cacheSwap.swapDirs[sio->swap_dirn]; - SD->obj.read(SD, sio, buf, size, offset, callback, callback_data); -} - -void -storeWrite(storeIOState * sio, char *buf, size_t size, off_t offset, FREE * free_func) -{ - SwapDir *SD = &Config.cacheSwap.swapDirs[sio->swap_dirn]; - SD->obj.write(SD, sio, buf, size, offset, free_func); -} - -void -storeUnlink(StoreEntry * e) -{ - SwapDir *SD = INDEXSD(e->swap_dirn); - SD->obj.unlink(SD, e); -} - -off_t -storeOffset(storeIOState * sio) -{ - return sio->offset; -} - -/* - * Make this non-static so we can register - * it from storeInit(); - */ -void -storeIOStats(StoreEntry * sentry) -{ - storeAppendPrintf(sentry, "Store IO Interface Stats\n"); - storeAppendPrintf(sentry, "create.calls %d\n", store_io_stats.create.calls); - storeAppendPrintf(sentry, "create.select_fail %d\n", store_io_stats.create.select_fail); - storeAppendPrintf(sentry, "create.create_fail %d\n", store_io_stats.create.create_fail); - storeAppendPrintf(sentry, "create.success %d\n", store_io_stats.create.success); -} --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/store_io.cc Wed Feb 14 01:07:37 2007 @@ -0,0 +1,119 @@ +#include "squid.h" +#include "Store.h" + + +static struct { + struct { + int calls; + int select_fail; + int create_fail; + int success; + } create; +} store_io_stats; + +OBJH storeIOStats; + +/* + * submit a request to create a cache object for writing. + * The StoreEntry structure is sent as a hint to the filesystem + * to what will be stored in this object, to allow the filesystem + * to select different polices depending on object size or type. + */ +storeIOState * +storeCreate(StoreEntry * e, STIOCB * file_callback, STIOCB * close_callback, void *callback_data) +{ + ssize_t objsize; + sdirno dirn; + SwapDir *SD; + storeIOState *sio; + + store_io_stats.create.calls++; + /* This is just done for logging purposes */ + objsize = objectLen(e); + if (objsize != -1) + objsize += e->mem_obj->swap_hdr_sz; + + /* + * Pick the swapdir + * We assume that the header has been packed by now .. + */ + dirn = storeDirSelectSwapDir(e); + if (dirn == -1) { + debug(20, 2) ("storeCreate: no valid swapdirs for this object\n"); + store_io_stats.create.select_fail++; + return NULL; + } + debug(20, 2) ("storeCreate: Selected dir '%d' for obj size '%ld'\n", dirn, (long int) objsize); + SD = &Config.cacheSwap.swapDirs[dirn]; + + /* Now that we have a fs to use, call its storeCreate function */ + sio = SD->obj.create(SD, e, file_callback, close_callback, callback_data); + if (NULL == sio) + store_io_stats.create.create_fail++; + else + store_io_stats.create.success++; + return sio; +} + + +/* + * storeOpen() is purely for reading .. + */ +storeIOState * +storeOpen(StoreEntry * e, STFNCB * file_callback, STIOCB * callback, + void *callback_data) +{ + SwapDir *SD = &Config.cacheSwap.swapDirs[e->swap_dirn]; + return SD->obj.open(SD, e, file_callback, callback, callback_data); +} + +void +storeClose(storeIOState * sio) +{ + SwapDir *SD = &Config.cacheSwap.swapDirs[sio->swap_dirn]; + if (sio->flags.closing) + return; + sio->flags.closing = 1; + SD->obj.close(SD, sio); +} + +void +storeRead(storeIOState * sio, char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data) +{ + SwapDir *SD = &Config.cacheSwap.swapDirs[sio->swap_dirn]; + SD->obj.read(SD, sio, buf, size, offset, callback, callback_data); +} + +void +storeWrite(storeIOState * sio, char *buf, size_t size, off_t offset, FREE * free_func) +{ + SwapDir *SD = &Config.cacheSwap.swapDirs[sio->swap_dirn]; + SD->obj.write(SD, sio, buf, size, offset, free_func); +} + +void +storeUnlink(StoreEntry * e) +{ + SwapDir *SD = INDEXSD(e->swap_dirn); + SD->obj.unlink(SD, e); +} + +off_t +storeOffset(storeIOState * sio) +{ + return sio->offset; +} + +/* + * Make this non-static so we can register + * it from storeInit(); + */ +void +storeIOStats(StoreEntry * sentry) +{ + storeAppendPrintf(sentry, "Store IO Interface Stats\n"); + storeAppendPrintf(sentry, "create.calls %d\n", store_io_stats.create.calls); + storeAppendPrintf(sentry, "create.select_fail %d\n", store_io_stats.create.select_fail); + storeAppendPrintf(sentry, "create.create_fail %d\n", store_io_stats.create.create_fail); + storeAppendPrintf(sentry, "create.success %d\n", store_io_stats.create.success); +} --- squid/src/win32.c Wed Feb 14 01:07:37 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,110 +0,0 @@ - -/* - * $Id$ - * - * * * * * * * * Legal stuff * * * * * * * - * - * (C) 2001 Guido Serassio , - * inspired by previous work by Romeo Anghelache & Eric Stern. - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "squid.h" - -/* This code compiles only CygWin & Windows NT Port */ -#if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) -#include - -static unsigned int GetOSVersion(); - -/* ====================================================================== */ -/* LOCAL FUNCTIONS */ -/* ====================================================================== */ - -static unsigned int -GetOSVersion() -{ - OSVERSIONINFO osvi; - - safe_free(WIN32_OS_string); - memset(&osvi, '\0', sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx((OSVERSIONINFO *) & osvi); - switch (osvi.dwPlatformId) { - case VER_PLATFORM_WIN32_NT: - if (osvi.dwMajorVersion <= 4) { - WIN32_OS_string = xstrdup("Windows NT"); - return _WIN_OS_WINNT; - } - if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 0)) { - WIN32_OS_string = xstrdup("Windows 2000"); - return _WIN_OS_WIN2K; - } - if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 1)) { - WIN32_OS_string = xstrdup("Windows XP"); - return _WIN_OS_WINXP; - } - if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 2)) { - WIN32_OS_string = xstrdup("Windows .NET"); - return _WIN_OS_WINNET; - } - break; - case VER_PLATFORM_WIN32_WINDOWS: - if ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 0)) { - WIN32_OS_string = xstrdup("Windows 95"); - return _WIN_OS_WIN95; - } - if ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 10)) { - WIN32_OS_string = xstrdup("Windows 98"); - return _WIN_OS_WIN98; - } - if ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 90)) { - WIN32_OS_string = xstrdup("Windows Me"); - return _WIN_OS_WINME; - } - break; - case VER_PLATFORM_WIN32s: - WIN32_OS_string = xstrdup("Windows 3.1 with WIN32S"); - return _WIN_OS_WIN32S; - break; - default: - break; - } - WIN32_OS_string = xstrdup("Unknown Windows system"); - return _WIN_OS_UNKNOWN; -} - -/* ====================================================================== */ -/* PUBLIC FUNCTIONS */ -/* ====================================================================== */ - -void -WIN32_Exit() -{ - _exit(0); -} - -int -WIN32_Subsystem_Init() -{ - WIN32_OS_version = GetOSVersion(); - if ((WIN32_OS_version == _WIN_OS_UNKNOWN) || (WIN32_OS_version == _WIN_OS_WIN32S)) - return 1; - if (atexit(WIN32_Exit) != 0) - return 1; - return 0; -} -#endif --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/win32.cc Wed Feb 14 01:07:37 2007 @@ -0,0 +1,110 @@ + +/* + * $Id: win32.cc,v 1.1.2.1 2002/10/09 04:52:02 rbcollins Exp $ + * + * * * * * * * * Legal stuff * * * * * * * + * + * (C) 2001 Guido Serassio , + * inspired by previous work by Romeo Anghelache & Eric Stern. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "squid.h" + +/* This code compiles only CygWin & Windows NT Port */ +#if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) +#include + +static unsigned int GetOSVersion(); + +/* ====================================================================== */ +/* LOCAL FUNCTIONS */ +/* ====================================================================== */ + +static unsigned int +GetOSVersion() +{ + OSVERSIONINFO osvi; + + safe_free(WIN32_OS_string); + memset(&osvi, '\0', sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx((OSVERSIONINFO *) & osvi); + switch (osvi.dwPlatformId) { + case VER_PLATFORM_WIN32_NT: + if (osvi.dwMajorVersion <= 4) { + WIN32_OS_string = xstrdup("Windows NT"); + return _WIN_OS_WINNT; + } + if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 0)) { + WIN32_OS_string = xstrdup("Windows 2000"); + return _WIN_OS_WIN2K; + } + if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 1)) { + WIN32_OS_string = xstrdup("Windows XP"); + return _WIN_OS_WINXP; + } + if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 2)) { + WIN32_OS_string = xstrdup("Windows .NET"); + return _WIN_OS_WINNET; + } + break; + case VER_PLATFORM_WIN32_WINDOWS: + if ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 0)) { + WIN32_OS_string = xstrdup("Windows 95"); + return _WIN_OS_WIN95; + } + if ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 10)) { + WIN32_OS_string = xstrdup("Windows 98"); + return _WIN_OS_WIN98; + } + if ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 90)) { + WIN32_OS_string = xstrdup("Windows Me"); + return _WIN_OS_WINME; + } + break; + case VER_PLATFORM_WIN32s: + WIN32_OS_string = xstrdup("Windows 3.1 with WIN32S"); + return _WIN_OS_WIN32S; + break; + default: + break; + } + WIN32_OS_string = xstrdup("Unknown Windows system"); + return _WIN_OS_UNKNOWN; +} + +/* ====================================================================== */ +/* PUBLIC FUNCTIONS */ +/* ====================================================================== */ + +void +WIN32_Exit() +{ + _exit(0); +} + +int +WIN32_Subsystem_Init() +{ + WIN32_OS_version = GetOSVersion(); + if ((WIN32_OS_version == _WIN_OS_UNKNOWN) || (WIN32_OS_version == _WIN_OS_WIN32S)) + return 1; + if (atexit(WIN32_Exit) != 0) + return 1; + return 0; +} +#endif