⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 storage.cxx

📁 完全免费的邮件发送程序。delphi 6.0
💻 CXX
📖 第 1 页 / 共 2 页
字号:
	} while (--len != 0);
    }
    delete[] stack_bottom;
    gc_stack = NULL;

    curr_free_page = NULL;
    hdr->free_page_chain = NULL; // will be reconstructed
    memset(hdr->free_block_chain, 0, sizeof hdr->free_block_chain);

    // ... and sweep
    size_t n_deallocated_objects = 0;
    size_t n_free_objects = 0;
    size_t n_used_objects = 0;
    size_t used_size = 0;
    storage_free_block* bp = (storage_free_block*)((char*)hdr + page_size);
    storage_free_block* end_of_storage = 
	(storage_free_block*)((char*)hdr + hdr->file_size);
    while (bp < end_of_storage) { 
	size_t size = bp->size + sizeof(object_header);
	if (size > page_size/2) { // large object
	    if (bp->cid & object_header::gc_marked) {
		bp->cid &= ~object_header::gc_marked;
		n_used_objects += 1;
		used_size += size;
	    } else { 
		n_deallocated_objects += bp->cid != object_header::free_object;
		n_free_objects += 1;
		free_page(bp);
	    }
	    bp = (storage_free_block*)ALIGN((long)bp + size, page_size);
	} else { 			    
	    int n = ((size+7) >> 3) - 1;
	    size = block_size[n];
	    storage_free_block* end_of_page = 
		(storage_free_block*)((char*)bp + page_size - size + 1);
	    storage_free_block chain_hdr;
	    storage_free_block* chain = &chain_hdr; 
	    size_t used = n_used_objects;
	    do { 
		if (bp->cid & object_header::gc_marked) {
		    bp->cid &= ~object_header::gc_marked;
		    n_used_objects += 1;
		    used_size += size;
		} else { 
		    n_deallocated_objects += 
			bp->cid != object_header::free_object;
		    n_free_objects += 1;
		    bp->cid = object_header::free_object;
		    chain = chain->next = bp;
		}
		bp = (storage_free_block*)((char*)bp+size);
	    } while (bp < end_of_page);

	    if (used == n_used_objects) { 
		// there are no used objects at this page
		free_page(chain_hdr.next); // free the whole page
	    } else {
		chain->next = hdr->free_block_chain[block_chain[n]];
		hdr->free_block_chain[block_chain[n]] = chain_hdr.next;
	    } 
	    bp = (storage_free_block*)ALIGN((long)bp, page_size);
	}
    }

    TRACE_MSG(("Free %ld objects\n"
	       "Total in storage %ld free and %ld used objects\n"
	       "Currently %ld bytes out of %ld are used\n", 
	       n_deallocated_objects, n_free_objects, n_used_objects,
	       used_size, hdr->file_size));
    return n_deallocated_objects;
}
		     
inline void storage::call_constructor(object_header* hp) 
{ 
    get_object_class(hp->cid)->constructor((object*)(hp+1));
}


void storage::adjust_references(long shift)
{
    storage_free_block* bp = (storage_free_block*)((char*)hdr + page_size);
    storage_free_block* end_of_storage = 
	(storage_free_block*)((char*)hdr + hdr->file_size);
    if (shift == 0) { // minimize number of modified objects
	do { 
	    size_t size = bp->size + sizeof(object_header);
	    if (size > page_size/2) { // large object
		if (bp->cid != object_header::free_object) {
		    call_constructor(bp);
		}
		bp = (storage_free_block*)ALIGN((long)bp + size, page_size);
	    } else { 			    
		size = block_size[((size+7) >> 3) - 1];
		storage_free_block* end_of_page = 
		    (storage_free_block*)((char*)bp + page_size - size + 1);
		do { 
		    if (bp->cid != object_header::free_object) { 
			call_constructor(bp);
		    }
		    bp = (storage_free_block*)((char*)bp+size);
		} while (bp < end_of_page);
		bp = (storage_free_block*)ALIGN((long)bp, page_size);
	    }
	} while (bp < end_of_storage);
    } else { // shift != 0
	do { 
	    size_t size = bp->size + sizeof(object_header);
	    if (size > page_size/2) { // large object
		if (bp->cid == object_header::free_object) {
		    if (bp->next != NULL) { 
			*(char**)&bp->next += shift;
		    }
		} else { 
		    call_constructor(bp);
		}
		bp = (storage_free_block*)ALIGN((long)bp + size, page_size);
	    } else { 			    
		size = block_size[((size+7) >> 3) - 1];
		storage_free_block* end_of_page = 
		    (storage_free_block*)((char*)bp + page_size - size + 1);
		do { 
		    if (bp->cid == object_header::free_object) { 
			if (bp->next != NULL) { 
			    *(char**)&bp->next += shift;
			}
		    } else { 
			call_constructor(bp);
		    }
		    bp = (storage_free_block*)((char*)bp+size);
		} while (bp < end_of_page);
		bp = (storage_free_block*)ALIGN((long)bp, page_size);
	    }
	} while (bp < end_of_storage);
    }
}

void storage::flush()
{
    CS(mutex);
    if (!data_file.flush()) { 
	handle_error("flush");
    }
}

void storage::commit()
{
    CS(mutex);
    if (!data_file.commit()) { 
	handle_error("commit");
    }
}

void storage::rollback()
{
    CS(mutex);
    if (!data_file.rollback()) { 
	handle_error("rollback");
    } else { 
	curr_free_page = hdr->free_page_chain;
    }
}

void storage::close()
{
    CS2(global_mutex, mutex);

    delete[] app_class_mapping;
    delete[] dbs_class_mapping;

    storage *sp, **spp = &chain;
    while ((sp = *spp) != this) { 
	spp = &sp->next;
    }
    *spp = sp->next;

    if (!data_file.close()) { 
	handle_error("close");
    }    
}


void* storage::alloc_page(int cid, size_t size)
{
    storage_free_block* bp = NULL;
    size_t aligned_size = ALIGN(size + sizeof(object_header), page_size);
    if (hdr->free_page_chain != NULL) { 
	storage_free_block** bpp = &curr_free_page->next;
	while ((bp = *bpp) != NULL && bp->size < size) { 
	    bpp = &bp->next;
	}
	if (bp == NULL) { 
	    bpp = &hdr->free_page_chain;
	    storage_free_block* save_next = curr_free_page->next;
	    curr_free_page->next = NULL;
	    while ((bp = *bpp) != NULL && bp->size < size) { 
		bpp = &bp->next;
	    }
	    curr_free_page->next = save_next;
	}
	if (bp != NULL) { 
	    if (bp->size > aligned_size) { 
		curr_free_page = bp;
		bp->size -= aligned_size;
		bp = (storage_free_block*)
		    ((char*)bp + bp->size + sizeof(object_header));
	    } else { 
		*bpp = bp->next;
		curr_free_page = bp->next ? bp->next : hdr->free_page_chain;
	    } 	    
	} 
    } 
    if (bp == NULL) { 
	bp = (storage_free_block*)((char*)hdr + hdr->file_size);
	hdr->file_size += aligned_size;
	if (!data_file.set_size(hdr->file_size)) { 
	    handle_error("set_size");
	} 
	if (hdr->page_map != NULL && cid != object_header::page_map_cid) { 
	    size_t old_map_size = hdr->page_map->size;
	    if (hdr->file_size > old_map_size*page_size*8) {
		// file_size+map_size+map_header >= page_size*8*map_size
		size_t new_map_size = 
		    (hdr->file_size + sizeof(object_header) + page_size*8-2)
 		                       / (page_size*8 - 1);
		// reserve space for future
		new_map_size = ALIGN(new_map_size + sizeof(object_header),
				     page_size)*2 - sizeof(object_header); 
		TRACE_MSG(("storage::alloc: reallocate page map, old size=%ld,"
			   " new size=%ld\n", old_map_size, new_map_size));
		storage_page_map* new_map = (storage_page_map*)
		    ((char*)alloc_page(object_header::page_map_cid, 
				       new_map_size)-sizeof(object_header));
		memcpy(new_map->bits, hdr->page_map->bits, old_map_size);
		memset(new_map->bits + old_map_size, 0, 
		       new_map_size - old_map_size);
		free_page(hdr->page_map);
		hdr->page_map = new_map;
	    }
	} 
    }
    bp->cid = cid;
    bp->size = size;
    if (size + sizeof(object_header) <= page_size/2) { 
        int n = ((size + sizeof(object_header) + 7) >> 3) - 1;
	size = block_size[n];
	storage_free_block* end_of_page = 
	    (storage_free_block*)((char*)bp + page_size - size + 1);
	storage_free_block* cp = (storage_free_block*)((char*)bp + size);
	do { 
	    cp->cid = object_header::free_object;
	    cp = cp->next = (storage_free_block*)((char*)cp + size);
	} while (cp < end_of_page);
	cp = (storage_free_block*)((char*)cp - size);
	cp->next = hdr->free_block_chain[block_chain[n]];
	hdr->free_block_chain[block_chain[n]] = 
	    (storage_free_block*)((char*)bp+size);
    } else if (aligned_size > page_size && cid != object_header::page_map_cid){
	if (hdr->page_map == NULL) { 
	    // file_size+map_size+map_header >= page_size*8*map_size
	    size_t map_size = 
		(hdr->file_size+sizeof(object_header)+page_size*8-2)
		                   / (page_size*8 - 1);
	    map_size = ALIGN(map_size + sizeof(object_header), page_size)
		       * init_page_map_size - sizeof(object_header); 
	    TRACE_MSG(("storage::alloc: allocate page map, size=%ld\n", 
		       map_size));
	    hdr->page_map = (storage_page_map*)
		((char*)alloc_page(object_header::page_map_cid, map_size)
		 - sizeof(object_header));
	    memset(hdr->page_map->bits, 0, map_size);
	}
	int page_no = size_t((char*)bp - (char*)hdr) / page_size; 
	int n_pages = aligned_size / page_size - 1;
	do { 
	    page_no += 1;
	    hdr->page_map->bits[page_no >> 3] |= 1 << (page_no & 7);
	} while (--n_pages != 0);
    } 
    return (object_header*)bp+1;
}



void storage::free_page(object_header* hp)
{
    storage_free_block *bp, *prev;
    storage_free_block *fp = (storage_free_block*)hp;

    if (curr_free_page != NULL && curr_free_page < fp) { 
	prev = curr_free_page;
	bp = prev->next;
    } else { 
	prev = NULL;
	bp = hdr->free_page_chain; 
    }

    while (bp != NULL && bp < fp) { 
	 prev = bp;
	 bp = bp->next;
    }
    assert(bp != fp/*object can't be deallocated twice*/);

    size_t aligned_size = ALIGN(fp->size + sizeof(object_header), page_size);
    fp->size = aligned_size - sizeof(object_header);
    if (aligned_size > page_size 
	&& fp->cid != object_header::free_object // reconstruction of free list
	&& fp->cid != object_header::page_map_cid) // allocation of page map
    {  
	assert(hdr->page_map != NULL);
	int page_no = size_t((char*)fp - (char*)hdr) / page_size; 
	int n_pages = aligned_size / page_size - 1;
	do { 
	    page_no += 1;
	    hdr->page_map->bits[page_no >> 3] &= ~(1 << (page_no & 7));
	} while (--n_pages != 0);
    }
    fp->cid = object_header::free_object;
    fp->next = bp;

    if (prev == NULL) { 
	hdr->free_page_chain = fp;
    } else { 
	if ((char*)prev + prev->size + sizeof(object_header) == (char*)fp) {
	    prev->size += fp->size + sizeof(object_header);
	    fp = prev;
	} else { 
	    prev->next = fp;
	}
    }
    if ((char*)fp + fp->size + sizeof(object_header) == (char*)bp) { 
	fp->size += bp->size + sizeof(object_header);
	fp->next = bp->next;
    }
    curr_free_page = fp;
}

char* storage::get_error_text(char* buf, size_t buf_size)
{
    return data_file.get_error_text(buf, buf_size);
}

storage::~storage() {}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -