咱們這次主要是使用PHP語言,娛樂平臺出租《企娥21717 93408》結合hash算法,來實現一個簡單的數據庫實例,它主要有四個功能,連接數據庫,查詢操作,插入操作,刪除操作,關閉數據庫連接操作,其它的大家可以後期補充完善下,咱廢話不多說,先來看代碼:
<?php
header('Content-type:text/html;charset=utf-8');
define('DB_INSERT',1);
define('DB_REPLACE',2);
define('DB_STORE',3);
define('DB_BUCKET_SIZE',262114);
define('DB_KEY_SIZE',128);
define('DB_INDEX_SIZE',DB_KEY_SIZE+12);
define('DB_KEY_EXISTS',1);
define('DB_FAILURE',-1);
define('DB_SUCCESS',0);
class DB{
private $idx_fp;
private $dat_fp;
private $closed;
public function open($path_name)
{
$idx_path = $path_name.".idx";
$dat_path = $path_name.".dat";
if (!file_exists($idx_path)) {
$init = true;
$mode = 'w+b';
}else{
$init = false;
$mode = 'r+b';
}
$this->idx_fp = fopen($idx_path,$mode);
if($init){
$elem = pack('L',0x00000000);
for ($i=0;$i<DB_BUCKET_SIZE;$i++) {
fwrite($this->idx_fp,$elem,4);
}
}
$this->dat_fp = fopen($dat_path,$mode);
if(!file_exists($dat_path)) {
return DB_FAILURE;
}
if(!$this->dat_fp) {
return DB_FAILURE;
}
return DB_SUCCESS;
}
private function _hash($str)
{
$str = substr(md5($str),0,8);
$hash = 0;
for ($i=0;$i<8;$i++) {
$hash += 33*$hash+ord($str[$i]);
}
return $hash&0x7FFFFFFF;
}
public function fetch($key)
{
$offset = ($this->_hash($key)%DB_BUCKET_SIZE)*4;
fseek($this->idx_fp,$offset,SEEK_SET);
$pos = unpack('L',fread($this->idx_fp,4));
$pos = $pos[1];
$found = false;
while ($pos) {
fseek($this->idx_fp,$pos,SEEK_SET);
$block = fread($this->idx_fp,DB_INDEX_SIZE);
$cp_key = substr($block,4,DB_KEY_SIZE);
if (!strncmp($key,$cp_key,strlen($key))) {
$data_off = unpack('L',substr($block,DB_KEY_SIZE+4,4));
$data_off = $data_off[1];
$data_len = unpack('L',substr($block,DB_KEY_SIZE+8,4));
$data_len = $data_len[1];
$found = true;
break;
}
$pos = unpack('L',substr($block,0,4));
$pos = $pos[1];
}
if(!$found) {
return null;
}
fseek($this->dat_fp,$data_off,SEEK_SET);
$data = fread($this->dat_fp,$data_len);
return $data;
}
public function insert($key,$data)
{
$offset = ($this->_hash($key)%DB_BUCKET_SIZE)*4;
$idx_off = fstat($this->idx_fp);
$idx_off = intval($idx_off['size']);
$dat_off = fstat($this->dat_fp);
$dat_off = intval($dat_off['size']);
$key_len = strlen($key);
if($key_len > DB_KEY_SIZE) {
return DB_FAILURE;
}
$block = pack('L',0x00000000);
$block .= $key;
$space = DB_KEY_SIZE-$key_len;
for ($i=0;$i<$space;$i++) {
$block .= pack('C',0x00);
}
$block .= pack('L',$dat_off);
$block .= pack('L',strlen($data));
fseek($this->idx_fp,$offset,SEEK_SET);
$pos = unpack('L',fread($this->idx_fp,4));
$pos = $pos[1];
if ($pos == 0) {
fseek($this->idx_fp,$offset,SEEK_SET);
fwrite($this->idx_fp,pack('L',$idx_off),4);
fseek($this->idx_fp,0,SEEK_END);
fwrite($this->idx_fp,$block,DB_INDEX_SIZE);
fseek($this->dat_fp,0,SEEK_END);
fwrite($this->dat_fp,$data,strlen($data));
return DB_SUCCESS;
}
$found = false;
while ($pos) {
fseek($this->idx_fp,$pos,SEEK_SET);
$tmp_block = fread($this->idx_fp,DB_INDEX_SIZE);
$cp_key = substr($tmp_block,4,DB_KEY_SIZE);
if(!strncmp($key,$cp_key,strlen($key))) {
$data_off = unpack('L',substr($tmp_block,DB_KEY_SIZE+4,4));
$data_off = $data_off[1];
$data_len = unpack('L',substr($tmp_block,DB_KEY_SIZE+8,4));
$data_len = $data_len[1];
$found = true;
break;
}
$prev = $pos;
$pos = unpack('L',substr($tmp_block,0,4));
$pos = $pos[1];
}
if ($found) {
return DB_KEY_EXISTS;
}
fseek($this->idx_fp,$prev,SEEK_SET);
fwrite($this->idx_fp,pack('L',$idx_off),4);
fseek($this->idx_fp,0,SEEK_END);
fwrite($this->idx_fp,$block,DB_INDEX_SIZE);
fseek($this->dat_fp,0,SEEK_END);
fwrite($this->dat_fp,$data,strlen($data));
return DB_SUCCESS;
}
public function delete($key)
{
$offset = ($this->_hash($key)%DB_BUCKET_SIZE)*4;
fseek($this->idx_fp,$offset,SEEK_SET);
$head = unpack('L',fread($this->idx_fp,4));
$head = $head[1];
$curr = $head;
$prev = 0;
while ($curr) {
fseek($this->idx_fp,$curr,SEEK_SET);
$block = fread($this->idx_fp,DB_INDEX_SIZE);
$next = unpack('L',substr($block,0,4));
$next = $next[1];
$cp_key = substr($block,4,DB_KEY_SIZE);
if(!strncmp($key,$cp_key,strlen($key))) {
$found = true;
break;
}
$prev = $curr;
$curr = $next;
}
if(!$found){
return DB_FAILURE;
}
if ($prev == 0) {
fseek($this->idx_fp,$offset,SEEK_SET);
fwrite($this->idx_fp,pack('L',$next),4);
}else{
fseek($this->idx_fp,$prev,SEEK_SET);
fwrite($this->idx_fp,pack('L',$next),4);
}
return DB_SUCCESS;
}
public function close()
{
if (!$this->closed) {
fclose($this->idx_fp);
fclose($this->dat_fp);
$this->closed = true;
}
}
}