pzg's blog

PHP写的小型数据库

插入数据

include ‘pdbm.php’;

$timestart = explode(‘ ‘, microtime());
$timestart = $timestart[0] + $timestart[1];

$pdbm = new Pdbm(‘test’);
$pdbm->open(PDBM_CREAT | PDBM_REWD);

for ($i = 0; $i < 100000; $i++) {
    $pdbm->insert(“key{$i}”, “value{$i}”);
}

$timetime = explode(‘ ‘, microtime());
$timetime = $timetime[0] + $timetime[1];

echo $timetime – $timestart;
//*/

获取数据

include ‘pdbm.php’;

$timestart = explode(‘ ‘, microtime());
$timestart = $timestart[0] + $timestart[1];

$pdbm = new Pdbm(‘test’);
$pdbm->open(PDBM_REWD);

$val = $pdbm->fetch(‘key9999’);
if ($val == NULL) {
    echo ‘Not found</br>’;
} else {
    echo $val.”<br/>”;
}

//$pdbm->delete(‘key100’); //delete data

$val = $pdbm->fetch(‘key100’);
if ($val == NULL) {
    echo ‘Not found</br>’;
} else {
    echo $val.”<br/>”;
}

$timetime = explode(‘ ‘, microtime());
$timetime = $timetime[0] + $timetime[1];

echo $timetime – $timestart;
//*/

‘pdbm.php’

<?php
/*  This file is part of PDBM, the GNU data base manager, by Philip A. Nelson.
    Copyright (C) 2010, 2011  Free Software Foundation, Inc.

    PDBM 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, or (at your option)
    any later version.

    PDBM 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 may contact the author by:
       e-mail: 280259971@qq.com
    author: liexusong
*************************************************************************/

function int_pack($int) {
 return pack(“I”, $int);
}

function int_unpack($bin) {
 $ret = unpack(“I”, $bin);
 return $ret[1];
}

function zero_block() {
 return pack(“I”, 0).
     pack(“I”, 0).
     pack(“I”, 0).
     pack(“I”, 0).
     pack(“I”, 0).
     pack(“I”, 0).
     pack(“I”, 0).
     pack(“I”, 0).
     pack(“I”, 0).
     pack(“I”, 0).
     pack(“I”, 0).
     pack(“I”, 0).
     pack(“I”, 0).
     pack(“I”, 0).
     pack(“I”, 0).
     pack(“I”, 0).
     pack(“I”, 0).
     pack(“I”, 0).
     pack(“I”, 0).
     pack(“I”, 0);
}

define(‘PDBM_READ’,  1);
define(‘PDBM_WRITE’, 2);
define(‘PDBM_REWD’,  3);

define(‘PDBM_CREAT’, 4);

define(‘PDBM_HASHBUCKET_SIZE’, 10240);
define(‘PDBM_BLOCK_SIZE’, 80);

class IndexHead {
 var $keyLength;
 var $key;
 var $indexNext;
 var $dataOffset;
 var $dataLength;
}

class Pdbm {
 var $version;
 var $dbname;
 var $mode;
 var $index_fp;
 var $data_fp;
 var $hash_bucket = array();
 
 function Pdbm($dbname) {
  $this->dbname = $dbname;
  $this->version = “1.0.0”;
  if (!function_exists(‘pack’)) {
   exit(‘”pack” function is not exists in your system’);
  }
 }
 
 function _init() {
  if (PDBM_CREAT & $this->mode) {
   for ($i = 0; $i < PDBM_HASHBUCKET_SIZE; $i++) {
    $this->hash_bucket[$i] = new IndexHead();
    $this->hash_bucket[$i]->keyLength = 0;
    $this->hash_bucket[$i]->key = NULL;
    $this->hash_bucket[$i]->indexNext = 0;
    $this->hash_bucket[$i]->dataOffset = 0;
    $this->hash_bucket[$i]->dataLength = 0;
    
    fwrite($this->index_fp, zero_block(), PDBM_BLOCK_SIZE);
   }
   fflush($this->index_fp);/* write data into the index file */
  } else {
   for ($i = 0; $i < PDBM_HASHBUCKET_SIZE; $i++) {
    $buf = fread($this->index_fp, PDBM_BLOCK_SIZE);
    
    $this->hash_bucket[$i] = new IndexHead();
    $this->hash_bucket[$i]->keyLength = int_unpack(substr($buf, 0, 4));
    $this->hash_bucket[$i]->key = substr($buf, 4, 64);
    $this->hash_bucket[$i]->indexNext = int_unpack(substr($buf, 68, 4));
    $this->hash_bucket[$i]->dataOffset = int_unpack(substr($buf, 72, 4));
    $this->hash_bucket[$i]->dataLength = int_unpack(substr($buf, 76, 4));
   }
  }
 }
 
 function open($flags) {
  $this->mode = $flags;
  $dbname = $this->dbname;
  
  if (PDBM_CREAT & $this->mode) {
   if (PDBM_READ & $this->mode) {
    $this->index_fp = fopen(“{$dbname}.ind”, “wb+”);
    $this->data_fp  = fopen(“{$dbname}.dat”, “wb+”);
   } else {
    $this->index_fp = fopen(“{$dbname}.ind”, “wb”);
    $this->data_fp  = fopen(“{$dbname}.dat”, “wb”);
   }
  } else if (PDBM_REWD & $this->mode) {
   $this->index_fp = fopen(“{$dbname}.ind”, “rb+”);
   $this->data_fp  = fopen(“{$dbname}.dat”, “ab+”);
  } else if (PDBM_WRITE & $this->mode) {
   $this->index_fp = fopen(“{$dbname}.ind”, “ab”);
   $this->data_fp  = fopen(“{$dbname}.dat”, “ab”);
  } else {
   $this->index_fp = fopen(“{$dbname}.ind”, “rb”);
   $this->data_fp  = fopen(“{$dbname}.dat”, “rb”);
  }
  
  $this->_init();
  
  if (!$this->index_fd && !$this->data_fp) {
   return true;
  } else {
   return false;
  }
 }
 
 function insert($key, $val) {
  $index = $this->hash($key);
  
  $ioffset = fstat($this->index_fp);
  $ioffset = intval($ioffset[‘size’]);
  
  $doffset = fstat($this->data_fp);
  $doffset = intval($doffset[‘size’]);
  
  $keylen  = strlen($key);
  $datalen = strlen($val);
  
  if ($keylen == 0 || $keylen > 64) return false;
  if ($datalen == 0) return false;
  
  $bucket = $this->hash_bucket[$index];
  if ($bucket->keyLength == 0) {
   $this->hash_bucket[$index]->keyLength = $keylen;
   $this->hash_bucket[$index]->key = $key;
   $this->hash_bucket[$index]->indexNext = 0;
   $this->hash_bucket[$index]->dataOffset = $doffset;
   $this->hash_bucket[$index]->dataLength = $datalen;
   
   $bucketoffset = PDBM_BLOCK_SIZE * $index;
   fseek($this->index_fp, $bucketoffset, SEEK_SET);
   
   /* write data into index file */
   fwrite($this->index_fp, int_pack($this->hash_bucket[$index]->keyLength), 4);
   fwrite($this->index_fp, $this->hash_bucket[$index]->key, $this->hash_bucket[$index]->keyLength);
   fseek($this->index_fp, 64 – $this->hash_bucket[$index]->keyLength, SEEK_CUR);
   fwrite($this->index_fp, int_pack($this->hash_bucket[$index]->indexNext), 4);
   fwrite($this->index_fp, int_pack($this->hash_bucket[$index]->dataOffset), 4);
   fwrite($this->index_fp, int_pack($this->hash_bucket[$index]->dataLength), 4);
   fflush($this->index_fp);
   
   //echo $this->hash_bucket[$index]->key;
   
   /* write data into data file */
   fwrite($this->data_fp, $val, $datalen);
   fflush($this->data_fp);
   
  } else {
   
   if ($bucket->indexNext == 0) {
    fseek($this->index_fp, PDBM_BLOCK_SIZE * $index, SEEK_SET);
    fseek($this->index_fp, 68, SEEK_CUR);
    fwrite($this->index_fp, int_pack($ioffset), 4);
   } else {
    $nextbucket = new IndexHead();
    while ($bucket->indexNext != 0) {
     fseek($this->index_fp, $bucket->indexNext, SEEK_SET);
     $buf = fread($this->index_fp, PDBM_BLOCK_SIZE);
     
     //$nextbucket->keyLength = int_unpack(substr($buf, 0, 4));
     //$nextbucket->key = substr($buf, 4, 64);
     $nextbucket->indexNext = int_unpack(substr($buf, 68, 4));
     //$nextbucket->dataOffset = int_unpack(substr($buf, 72, 4));
     //$nextbucket->dataLength = int_unpack(substr($buf, 76, 4));
     
     $bucket = $nextbucket;
    }
    
    fseek($this->index_fp, 12, SEEK_CUR);
    fwrite($this->index_fp, int_pack($ioffset), 4);
   }
   
   fseek($this->index_fp, $ioffset, SEEK_SET);
   fwrite($this->index_fp, int_pack($keylen), 4);
   fwrite($this->index_fp, $key, $keylen);
   fseek($this->index_fp, 64 – $keylen, SEEK_CUR);
   fwrite($this->index_fp, int_pack(0), 4);
   fwrite($this->index_fp, int_pack($doffset), 4);
   fwrite($this->index_fp, int_pack($datalen), 4);
   fflush($this->index_fp);
   
   fwrite($this->data_fp, $val, $datalen);
   fflush($this->data_fp);
  }
  
  return true;
 }
 
 function fetch($key) {
  $index = $this->hash($key);
  
  $bucket = $this->hash_bucket[$index];
  if ($bucket->keyLength == 0 && $bucket->indexNext == 0) {
   return NULL;
  }
  
  $nextbucket = new IndexHead();
  while ($bucket->indexNext != 0) {
   if ($bucket->keyLength == 0 || strncmp($bucket->key, $key, $bucket->keyLength) != 0) {
    fseek($this->index_fp, $bucket->indexNext, SEEK_SET);
    $buf = fread($this->index_fp, PDBM_BLOCK_SIZE);
    
    $nextbucket->keyLength = int_unpack(substr($buf, 0, 4));
    $nextbucket->key = substr($buf, 4, 64);
    $nextbucket->indexNext = int_unpack(substr($buf, 68, 4));
    $nextbucket->dataOffset = int_unpack(substr($buf, 72, 4));
    $nextbucket->dataLength = int_unpack(substr($buf, 76, 4));
    
    $bucket = $nextbucket;
   } else {
    break;
   }
  }
  
  if ($bucket->keyLength == 0) {
   return NULL;
  } else {
   if (strncmp($key, $bucket->key, $bucket->keyLength) == 0) {
    fseek($this->data_fp, $bucket->dataOffset, SEEK_SET);
    $ret = fread($this->data_fp, $bucket->dataLength);
   } else {
    $ret = NULL;
   }
   
   return $ret;
  }
 }
 
 function delete($key) {
  $index = $this->hash($key);
  
  $bucket = $this->hash_bucket[$index];
  if ($bucket->keyLength == 0 && $bucket->indexNext == 0) {
   return NULL;
  }
  
  if ($bucket->keyLength > 0 && strncmp($bucket->key, $key, $bucket->keyLength) == 0) {
   fseek($this->index_fp, PDBM_BLOCK_SIZE * $index, SEEK_SET);
   fwrite($this->index_fp, int_pack(0), 4);
   fflush($this->index_fp);
   return true;
  }
  
  $nextbucket = new IndexHead();
  while ($bucket->indexNext != 0) {
   if ($bucket->keyLength == 0 || strncmp($bucket->key, $key, $bucket->keyLength) != 0) {
    fseek($this->index_fp, $bucket->indexNext, SEEK_SET);
    $buf = fread($this->index_fp, PDBM_BLOCK_SIZE);
    
    $nextbucket->keyLength = int_unpack(substr($buf, 0, 4));
    $nextbucket->key = substr($buf, 4, 64);
    $nextbucket->indexNext = int_unpack(substr($buf, 68, 4));
    $nextbucket->dataOffset = int_unpack(substr($buf, 72, 4));
    $nextbucket->dataLength = int_unpack(substr($buf, 76, 4));
    
    $bucket = $nextbucket;
   } else {
    break;
   }
  }
  
  if ($bucket->keyLength == 0) {
   return false;
  } else {
   if (strncmp($key, $bucket->key, $bucket->keyLength) == 0) {
    fseek($this->index_fp, -(PDBM_BLOCK_SIZE), SEEK_CUR);
    fwrite($this->index_fp, int_pack(0), 4);
    $ret = true;
   } else {
    $ret = false;
   }
   
   fflush($this->index_fp);
   return $ret;
  }
 }
 
 function hash($key) {
  $seed = 131;
  $hash = 0;
  $i = 0;
  
  while (isset($key{$i})) {
   $hash = $hash * $seed + ord($key{$i});
   $i++;
  }
  return ($hash & 0x7FFFFFFF) % PDBM_HASHBUCKET_SIZE;
 }
 
 function isexists() {
  if (file_exists($this->dbname.’.ind’)) {
   return true;
  } else {
   return false;
  }
 }
 
 function version() {
  return $this->version;
 }
}
?>

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注