MongoDB의 shell command 중 sharding 정보를 출력해주는 sh.status() 또는 db.printShardingStatus()는,

PHP 드라이버에서 구현된 함수나 커맨드가 없음.

이걸 어떻게 해볼까 하다가 MongoDB shell 에서는 ()를 붙여서 함수를 호출하지 않으면 함수의 내용이 출력된다는 것에 착안하여 sh.status 부터 출력해 봄.


아래는 sh.status 의 함수내용.

그냥 printShardingStatus() 라는 함수를 호출하고 있음.


mongos> sh.status

function ( verbose , configDB ) {

    // TODO: move the actual command here

    printShardingStatus( configDB , verbose );

}



그래서 이번엔 printShardingStatus 의 함수내용을 출력해 봄.

뭐가 좀 긴데, 결국은 config DB에서 이런 저런 내용을 조합해서 뿌려주는 것.


mongos> printShardingStatus

function ( configDB , verbose ){

    if (configDB === undefined)

        configDB = db.getSisterDB('config')


    var version = configDB.getCollection( "version" ).findOne();

    if ( version == null ){

        print( "printShardingStatus: this db does not have sharding enabled. be sure you are connecting to a mongos from the shell and not to a mongod." );

        return;

    }


    var raw = "";

    var output = function(s){

        raw += s + "\n";

    }

    output( "--- Sharding Status --- " );

    output( "  sharding version: " + tojson( configDB.getCollection( "version" ).findOne() ) );


    output( "  shards:" );

    configDB.shards.find().sort( { _id : 1 } ).forEach(

        function(z){

            output( "\t" + tojsononeline( z ) );

        }

    );


    output( "  databases:" );

    configDB.databases.find().sort( { name : 1 } ).forEach(

        function(db){

            output( "\t" + tojsononeline(db,"",true) );


            if (db.partitioned){

                configDB.collections.find( { _id : new RegExp( "^" +

                    RegExp.escape(db._id) + "\\." ) } ).

                    sort( { _id : 1 } ).forEach( function( coll ){

                        if ( coll.dropped == false ){

                            output( "\t\t" + coll._id );

                            output( "\t\t\tshard key: " + tojson(coll.key) );

                            output( "\t\t\tchunks:" );


                            res = configDB.chunks.group( { cond : { ns : coll._id } , key : { shard : 1 },

                                reduce : function( doc , out ){ out.nChunks++; } , initial : { nChunks : 0 } } );

                            var totalChunks = 0;

                            res.forEach( function(z){

                                totalChunks += z.nChunks;

                                output( "\t\t\t\t" + z.shard + "\t" + z.nChunks );

                            } )


                            if ( totalChunks < 20 || verbose ){

                                configDB.chunks.find( { "ns" : coll._id } ).sort( { min : 1 } ).forEach(

                                    function(chunk){

                                        output( "\t\t\t" + tojson( chunk.min ) + " -->> " + tojson( chunk.max ) +

                                                " on : " + chunk.shard + " " + tojson( chunk.lastmod ) + " " +

                                                ( chunk.jumbo ? "jumbo " : "" ) );

                                    }

                                );

                            }

                            else {

                                output( "\t\t\ttoo many chunks to print, use verbose if you want to force print" );

                            }


                            configDB.tags.find( { ns : coll._id } ).sort( { min : 1 } ).forEach(

                                function( tag ) {

                                    output( "\t\t\t tag: " + tag.tag + "  " + tojson( tag.min ) + " -->> " + tojson( tag.max ) );

                                }

                            )

                        }

                    }

                )

            }

        }

    );


    print( raw );

}





위 내용을 그대로 PHP로 컨버팅하여, 출력하지 않고 반환하는 함수를 만들어 봄.

Mongo shell의 printShardingStatus() 에서는 chunk 수가 20개가 넘으면 그냥 '많다'고 하고 넘어가는데,

아래 함수에선 수가 얼마가 되든 전부 반환값에 구겨넣는다는 것 말고는 동일.



// 매개변수 $m은 접속이 된 MongoClient의 인스턴스임

function getShardingStatus($m)

{

    if (!$m) return false;


    $configDB = $m->config;


    // databases

    $c = $configDB->databases->find();

    foreach ($c as $v) {

        if ($v['partitioned'] === false) continue;


        $aDb[] = $v['_id'];

    }


    if (count($aDb)<1) return false;


    $result = array();


    foreach ($aDb as $db) {

        $pattern = "/^".$db."\./";


        $q = array(

            '_id' => new MongoRegex($pattern)

        );


        // collections

        $c = $configDB->collections->find($q)->sort(array('_id'=>1));

        foreach ($c as $v) {

            if ($v['dropped'] === true) continue;


            $col = preg_replace($pattern, '', $v['_id']);

            $ns = $v['_id'];

            $qq = array(

                'ns' => $ns

            );


            // chunks

            $chunks = array();

            $cc = $configDB->chunks->find($qq)->sort(array('min'=>1));

            foreach ($cc as $vv) {

                $chunk = array(

                    'min'     => $vv['min'],

                    'max'     => $vv['max'],

                    'shard'   => $vv['shard'],

                    'lastmod' => $vv['lastmod']

                );

                if (isset($vv['jumbo'])) $chunk['jumbo'] = $vv['jumbo'];


                $chunks[] = $chunk;

            }


            // tags

            $tags = array();

            $cc = $configDB->tags->find($qq)->sort(array('min'=>1));

            foreach ($cc as $vv) {

                $tags[] = array(

                    'tag' => $vv['tag'],

                    'min' => $vv['min'],

                    'max' => $vv['max']

                );

            }


            $result[$db][$col] = array(

                'chunks' => $chunks,

                'tags'   => $tags

            );

        }

    }


    return $result;

}



$m = new MongoClient('mongodb://USER_ID:PASSWD@HOSTNAME:PORT');


// 해당 MongoDB의 모든 DB.Collection.chunks 정보를 다 받아옴.

$shard_status = getShardingStatus($m);





[참조]

http://stackoverflow.com/questions/12691215/mongodb-db-printshardingstatus-sh-status-call-in-java-and-javascript

Posted by bloodguy
,