Skip to content

Commit

Permalink
Merge pull request #1 from dekuan/dev
Browse files Browse the repository at this point in the history
brand new
  • Loading branch information
dekuan committed Aug 3, 2017
2 parents e48e3a5 + 77e2d48 commit cc3d994
Show file tree
Hide file tree
Showing 3 changed files with 298 additions and 0 deletions.
36 changes: 36 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name" : "dekuan/dedid",
"description" : "An unique id generator for distributed database by DeKuan, Inc.",
"type" : "library",
"license" : "proprietary",
"authors" :
[
{
"name" : "liuqixing",
"email" : "liuqixing@dekuan.org"
}
],
"extra":
{
"branch-alias":
{
"dev-master" : "0.3.x-dev"
}
},
"require":
{
"php" : ">=5.3.0"
},
"require-dev" :
{
"phpunit/phpunit" : "~4.0"
},
"autoload":
{
"psr-4" : { "dekuan\\" : "src" }
},
"autoload-dev" :
{
"psr-4" : { "dekuan\\" : "src" }
}
}
172 changes: 172 additions & 0 deletions src/CDId.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
<?php

namespace dekuan\dedid;

//
// STRUCTURE
// ================================================================================
//
//
// 0 xxxxxx xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xx xxxxxxxx
// - ------ ------- -------------------------------------------- -----------
// Host Table Escaped Time (in millisecond) Random
// 1 6 7 40 bits 10 bits
// 0~63 0~127 0~34 (years) 0~1023
//
//
// host
// 01111110 00000000 00000000 00000000 00000000 00000000 00000000 00000000
// 7E 00 00 00 00 00 00 00
//
// table
// 00000001 11111100 00000000 00000000 00000000 00000000 00000000 00000000
// 01 FC 00 00 00 00 00 00
//
// escaped time
// 00000000 00000011 11111111 11111111 11111111 11111111 11111100 00000000
// 00 03 FF FF FF FF FC 00
//
// random
// 00000000 00000000 00000000 00000000 00000000 00000000 00000011 11111111
// 00 00 00 00 00 00 03 FF
//


/**
* CDId
*/
class CDId
{
protected static $g_cInstanceDId;

/**
* Offset from Unix Epoch
*
* Unix Epoch : January 1, 1970 00:00:00 GMT
* Epoch Offset : November 7, 2016 00:00:00 GMT
*/
CONST EPOCH_OFFSET = 1478476800000;





public function __construct()
{
}
public function __destruct()
{
}
static function getInstance()
{
if ( is_null( self::$g_cInstanceDId ) || ! isset( self::$g_cInstanceDId ) )
{
self::$g_cInstanceDId = new self();
}
return self::$g_cInstanceDId;
}


/**
* Generate an unique id
*
* @param $nHost int host id ( 0 ~ 63 )
* @param $nTable int table id ( 0 ~ 127 )
* @param $arrData &array details about the id
* @return int(64) id
*/
public function createId( $nHost, $nTable, & $arrData = null )
{
if ( ! $this->isValidHostId( $nHost ) )
{
return null;
}
if ( ! $this->isValidTableId( $nTable ) )
{
return null;
}

// ...
$nRet = 0;
$nTime = $this->getEscapedTime();
$nRand = rand( 0, 0x3FF );

$nHostV = ( ( $nHost << 57 ) & 0x7E00000000000000 );
$nTabV = ( ( $nTable << 50 ) & 0x01FC000000000000 );
$nTimeV = ( ( $nTime << 10 ) & 0x0003FFFFFFFFFC00 );
$nRandV = ( ( $nRand << 0 ) & 0x00000000000003FF );

$nRet = ( $nHostV + $nTabV + $nTimeV + $nRandV );

// ...
if ( ! is_null( $arrData ) )
{
$arrData =
[
'host' => $nHost,
'table' => $nTable,
'time' => $nTime,
'rand' => $nRand,
];
}

return intval( $nRet );
}

/**
* Parse an unique id
*
* @param $nId int 64 bits unique id
* @return array details about the id
*/
public function parseId( $nId )
{
if ( ! is_numeric( $nId ) )
{
return null;
}

$nHost = ( ( $nId & 0x7E00000000000000 ) >> 57 );
$nTable = ( ( $nId & 0x01FC000000000000 ) >> 50 );
$nTime = ( ( $nId & 0x0003FFFFFFFFFC00 ) >> 10 );
$nRand = ( ( $nId & 0x00000000000003FF ) >> 0 );

return
[
'host' => $nHost,
'table' => $nTable,
'time' => $nTime,
'rand' => $nRand,
];
}

public function isValidHostId( $nVal )
{
return is_numeric( $nVal ) && ( $nVal >= 0 ) && ( $nVal <= 63 );
}
public function isValidTableId( $nVal )
{
return is_numeric( $nVal ) && ( $nVal >= 0 ) && ( $nVal <= 127 );
}


/**
* Get UNIX timestamp in millisecond
*
* @return int Timestamp in millisecond, for example: 1501780592275
*/
public function getUnixTimestamp()
{
return floor( microtime( true ) * 1000 );
}

/**
* Get escaped time in millisecond
*
* @return int time in millisecond
*/
public function getEscapedTime()
{
return intval( $this->getUnixTimestamp() - self::EPOCH_OFFSET );
}
}
90 changes: 90 additions & 0 deletions tests/TestIdGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

@ ini_set( 'date.timezone', 'Etc/GMT+0' );
@ date_default_timezone_set( 'Etc/GMT+0' );

@ ini_set( 'display_errors', 'on' );
@ ini_set( 'max_execution_time', '60' );
@ ini_set( 'max_input_time', '0' );
@ ini_set( 'memory_limit', '4096M' );

// mb 环境定义
mb_internal_encoding( "UTF-8" );

// Turn on output buffering
ob_start();


require_once( __DIR__ . "/../vendor/autoload.php");
require_once( __DIR__ . "/../src/CDId.php");



use dekuan\dedid\CDId;



/**
* Created by PhpStorm.
* User: xing
* Date: 03/08/2017
* Time: 9:07 PM
*/
class TestIdGenerator extends PHPUnit_Framework_TestCase
{
public function testCreateNew()
{
$cDId = CDId::getInstance();

$arrResult = [];
$arrUnique = [];
$nHostMax = 63;
$nTableMax = 127;

for ( $i = 0; $i < 1; $i ++ )
{
for ( $nHost = 0; $nHost <= $nHostMax; $nHost ++ )
{
for ( $nTable = 0; $nTable <= $nTableMax; $nTable ++ )
{
$arrD = [];
$nNewId = $cDId->createId( $nHost, $nTable, $arrD );
$arrId = $cDId->parseId( $nNewId );

$sHexId = dechex( $nNewId );

// ...
$this->assertSame( $arrId, $arrD );

$arrItem =
[
'h' => $nHost,
't' => $nTable,
'id' => $nNewId,
'r' => $arrId,
];
//$sKey = sprintf( "%d", $nNewId );

$arrResult[] = $arrItem;
$arrUnique[ $nNewId ] = $arrItem;
}
}
}


var_dump( count( $arrResult ), count( $arrUnique ) );
//
// file_put_contents( 'result.json', json_encode( $arrResult ) );
// file_put_contents( 'unique.json', json_encode( $arrUnique ) );

}


////////////////////////////////////////////////////////////////////////////////
// Private
//




}

0 comments on commit cc3d994

Please sign in to comment.