// close the database connection static void CloseHashStorage() { if ( ms_hashMap ) { _hash_drv_close(ms_hashMap); free(ms_hashMap); ms_hashMap = NULL; _hash_drv_lock_free(&ms_hashLock, DSPAM_USER_NAME); } }
int _hash_drv_autoextend( hash_drv_map_t map, int extents, unsigned long last_extent_size) { struct _hash_drv_header header; struct _hash_drv_spam_record rec; int i, lastsize; _hash_drv_close(map); map->fd = open(map->filename, O_RDWR); if (map->fd < 0) { LOG(LOG_WARNING, "unable to resize hash. open failed: %s", strerror(errno)); return EFAILURE; } memset(&header, 0, sizeof(struct _hash_drv_header)); memset(&rec, 0, sizeof(struct _hash_drv_spam_record)); if (extents == 0 || !map->pctincrease) header.hash_rec_max = map->extent_size; else header.hash_rec_max = last_extent_size + (last_extent_size * (map->pctincrease/100.0)); LOGDEBUG("adding extent last: %d(%ld) new: %d(%ld) pctincrease: %1.2f", extents, last_extent_size, extents+1, header.hash_rec_max, (map->pctincrease/100.0)); lastsize=lseek (map->fd, 0, SEEK_END); if(write (map->fd, &header, sizeof(struct _hash_drv_header))!=sizeof(struct _hash_drv_header)) { ftruncate(map->fd,lastsize); close(map->fd); LOG(LOG_WARNING, "unable to resize hash. open failed: %s", strerror(errno)); return EFAILURE; } for(i=0;i<header.hash_rec_max;i++) if(write (map->fd, &rec, sizeof(struct _hash_drv_spam_record))!=sizeof(struct _hash_drv_spam_record)) { ftruncate(map->fd,lastsize); close(map->fd); LOG(LOG_WARNING, "unable to resize hash. open failed: %s", strerror(errno)); return EFAILURE; } close(map->fd); _hash_drv_open(map->filename, map, 0, map->max_seek, map->max_extents, map->extent_size, map->pctincrease, map->flags); return 0; }
int _ds_shutdown_storage (DSPAM_CTX * CTX) { struct _hash_drv_storage *s; struct nt_node *node_nt; struct nt_c c_nt; int lock_result; if (!CTX || !CTX->storage) return EINVAL; s = (struct _hash_drv_storage *) CTX->storage; /* Close open file handles to directories (iteration functions) */ node_nt = c_nt_first (s->dir_handles, &c_nt); while (node_nt != NULL) { DIR *dir; dir = (DIR *) node_nt->ptr; closedir (dir); node_nt = c_nt_next (s->dir_handles, &c_nt); } nt_destroy (s->dir_handles); if (CTX->operating_mode != DSM_CLASSIFY) _hash_drv_set_spamtotals (CTX); /* Close connection to hash database only if we're not concurrent */ if (!s->dbh_attached) { _hash_drv_close(s->map); free(s->map); lock_result = _hash_drv_lock_free (s, (CTX->group) ? CTX->group : CTX->username); if (lock_result < 0) return EUNKNOWN; } free (CTX->storage); CTX->storage = NULL; return 0; }
int dspam_shutdown_driver (DRIVER_CTX *DTX) { #ifdef DAEMON DSPAM_CTX *CTX; if (DTX && DTX->CTX) { char *HashConcurrentUser; CTX = DTX->CTX; HashConcurrentUser = READ_ATTRIB("HashConcurrentUser"); if (DTX->flags & DRF_STATEFUL) { hash_drv_map_t map; int connection_cache = 1, i; if (READ_ATTRIB("HashConnectionCache") && !HashConcurrentUser) connection_cache = strtol(READ_ATTRIB("HashConnectionCache"), NULL, 0); LOGDEBUG("unloading hash database from memory"); if (DTX->connections) { for(i=0;i<connection_cache;i++) { LOGDEBUG("unloading connection object %d", i); if (DTX->connections[i]) { if (!HashConcurrentUser) { pthread_mutex_destroy(&DTX->connections[i]->lock); } else { pthread_rwlock_destroy(&DTX->connections[i]->rwlock); map = (hash_drv_map_t) DTX->connections[i]->dbh; if (map) _hash_drv_close(map); } free(DTX->connections[i]->dbh); free(DTX->connections[i]); } } free(DTX->connections); } } } #endif return 0; }
int cssstat(const char *filename) { struct _hash_drv_map map; hash_drv_header_t header; hash_drv_spam_record_t rec; unsigned long filepos = sizeof(struct _hash_drv_header); unsigned long nfree = 0, nused = 0; unsigned long efree, eused; unsigned long extents = 0; unsigned long i; unsigned long hash_rec_max = HASH_REC_MAX; unsigned long max_seek = HASH_SEEK_MAX; unsigned long max_extents = 0; unsigned long extent_size = HASH_EXTENT_MAX; int flags = 0; if (READ_ATTRIB("HashRecMax")) hash_rec_max = strtol(READ_ATTRIB("HashRecMax"), NULL, 0); if (READ_ATTRIB("HashExtentSize")) extent_size = strtol(READ_ATTRIB("HashExtentSize"), NULL, 0); if (READ_ATTRIB("HashMaxExtents")) max_extents = strtol(READ_ATTRIB("HashMaxExtents"), NULL, 0); if (MATCH_ATTRIB("HashAutoExtend", "on")) flags = HMAP_AUTOEXTEND; if (READ_ATTRIB("HashMaxSeek")) max_seek = strtol(READ_ATTRIB("HashMaxSeek"), NULL, 0); if (_hash_drv_open(filename, &map, 0, max_seek, max_extents, extent_size, 0, flags)) { return EFAILURE; } header = map.addr; printf("filename %s length %ld\n", filename, (long) map.file_len); while(filepos < map.file_len) { printf("extent %lu: record length %lu\n", extents, (unsigned long) header->hash_rec_max); efree = eused = 0; for(i=0;i<header->hash_rec_max;i++) { rec = map.addr+filepos; if (rec->hashcode) { eused++; nused++; } else { efree++; nfree++; } filepos += sizeof(struct _hash_drv_spam_record); } header = map.addr + filepos; filepos += sizeof(struct _hash_drv_header); extents++; printf("\textent records used %lu\n", eused); printf("\textent records free %lu\n", efree); } _hash_drv_close(&map); printf("total database records used %lu\n", nused); printf("total database records free %lu\n", nfree); printf("total extents %lu\n", extents); return 0; }
int _ds_init_storage (DSPAM_CTX * CTX, void *dbh) { struct _hash_drv_storage *s = NULL; hash_drv_map_t map = NULL; int ret; if (CTX == NULL) return EINVAL; if (!CTX->home) { LOG(LOG_ERR, ERR_AGENT_DSPAM_HOME); return EINVAL; } if (CTX->flags & DSF_MERGED) { LOG(LOG_ERR, ERR_DRV_NO_MERGED); return EINVAL; } if (CTX->storage) return EINVAL; /* Persistent driver storage */ s = calloc (1, sizeof (struct _hash_drv_storage)); if (s == NULL) { LOG(LOG_CRIT, ERR_MEM_ALLOC); return EUNKNOWN; } /* If running in HashConcurrentUser mode, use existing hash mapping */ if (dbh) { map = dbh; s->dbh_attached = 1; } else { map = calloc(1, sizeof(struct _hash_drv_map)); if (!map) { LOG(LOG_CRIT, ERR_MEM_ALLOC); free(s); return EUNKNOWN; } s->dbh_attached = 0; } s->map = map; /* Mapping defaults */ s->hash_rec_max = HASH_REC_MAX; s->max_seek = HASH_SEEK_MAX; s->max_extents = 0; s->extent_size = HASH_EXTENT_MAX; s->pctincrease = 0; s->flags = HMAP_AUTOEXTEND; if (READ_ATTRIB("HashRecMax")) s->hash_rec_max = strtol(READ_ATTRIB("HashRecMax"), NULL, 0); if (READ_ATTRIB("HashExtentSize")) s->extent_size = strtol(READ_ATTRIB("HashExtentSize"), NULL, 0); if (READ_ATTRIB("HashMaxExtents")) s->max_extents = strtol(READ_ATTRIB("HashMaxExtents"), NULL, 0); if (!MATCH_ATTRIB("HashAutoExtend", "on")) s->flags = 0; if (READ_ATTRIB("HashPctIncrease")) { s->pctincrease = atoi(READ_ATTRIB("HashPctIncrease")); if (s->pctincrease > 100) { LOG(LOG_ERR, "HashPctIncrease out of range; ignoring"); s->pctincrease = 0; } } if (READ_ATTRIB("HashMaxSeek")) s->max_seek = strtol(READ_ATTRIB("HashMaxSeek"), NULL, 0); if (!dbh && CTX->username != NULL) { char db[MAX_FILENAME_LENGTH]; int lock_result; if (CTX->group == NULL) _ds_userdir_path(db, CTX->home, CTX->username, "css"); else _ds_userdir_path(db, CTX->home, CTX->group, "css"); lock_result = _hash_drv_lock_get (CTX, s, (CTX->group) ? CTX->group : CTX->username); if (lock_result < 0) goto BAIL; ret = _hash_drv_open(db, s->map, s->hash_rec_max, s->max_seek, s->max_extents, s->extent_size, s->pctincrease, s->flags); if (ret) { _hash_drv_close(s->map); free(s); return EFAILURE; } } CTX->storage = s; s->dir_handles = nt_create (NT_INDEX); if (_hash_drv_get_spamtotals (CTX)) { LOGDEBUG ("unable to load totals. using zero values."); memset (&CTX->totals, 0, sizeof (struct _ds_spam_totals)); } return 0; BAIL: free(s); return EFAILURE; }