@@ -3,6 +3,7 @@ local ffi = require('ffi')
33local vshard = require (' vshard' )
44local fun = require (' fun' )
55local bit = require (' bit' )
6+ local log = require (' log' )
67
78local const = require (' crud.common.const' )
89local schema = require (' crud.common.schema' )
@@ -15,6 +16,8 @@ local ShardingError = errors.new_class('ShardingError', {capture_stack = false})
1516local GetSpaceFormatError = errors .new_class (' GetSpaceFormatError' , {capture_stack = false })
1617local FilterFieldsError = errors .new_class (' FilterFieldsError' , {capture_stack = false })
1718local NotInitializedError = errors .new_class (' NotInitialized' )
19+ local StorageInfoError = errors .new_class (' StorageInfoError' )
20+ local fiber_clock = require (' fiber' ).clock
1821
1922local utils = {}
2023
@@ -748,4 +751,87 @@ function utils.list_slice(list, start_index, end_index)
748751 return slice
749752end
750753
754+ --- Polls replicas for storage state
755+ --
756+ -- @function storage_info
757+ --
758+ -- @tparam ?number opts.timeout
759+ -- Function call timeout
760+ --
761+ -- @return a table of storage states by replica uuid.
762+ function utils .storage_info (opts )
763+ local replicasets , err = vshard .router .routeall ()
764+ if replicasets == nil then
765+ return nil , StorageInfoError :new (" Failed to get all replicasets: %s" , err .err )
766+ end
767+
768+ opts = opts or {}
769+
770+ local futures_by_replicas = {}
771+ local replica_state_by_uuid = {}
772+ local async_opts = {is_async = true }
773+ local timeout = opts .timeout or const .DEFAULT_VSHARD_CALL_TIMEOUT
774+
775+ for _ , replicaset in pairs (replicasets ) do
776+ for replica_uuid , replica in pairs (replicaset .replicas ) do
777+ replica_state_by_uuid [replica_uuid ] = {
778+ status = " error" ,
779+ is_master = replicaset .master == replica
780+ }
781+ local ok , res = pcall (replica .conn .call , replica .conn , " _crud.storage_info_on_storage" ,
782+ {}, async_opts )
783+ if ok then
784+ futures_by_replicas [replica_uuid ] = res
785+ else
786+ local err_msg = string.format (" Error getting storage info for %s" , replica_uuid )
787+ if res ~= nil then
788+ log .error (" %s: %s" , err_msg , res )
789+ replica_state_by_uuid [replica_uuid ].message = tostring (res )
790+ else
791+ log .error (err_msg )
792+ replica_state_by_uuid [replica_uuid ].message = err_msg
793+ end
794+ end
795+ end
796+ end
797+
798+ local deadline = fiber_clock () + timeout
799+ for replica_uuid , future in pairs (futures_by_replicas ) do
800+ local wait_timeout = deadline - fiber_clock ()
801+ if wait_timeout < 0 then
802+ wait_timeout = 0
803+ end
804+
805+ local result , err = future :wait_result (wait_timeout )
806+ if result == nil then
807+ future :discard ()
808+ local err_msg = string.format (" Error getting storage info for %s" , replica_uuid )
809+ if err ~= nil then
810+ if err .type == ' ClientError' and err .code == box .error .NO_SUCH_PROC then
811+ replica_state_by_uuid [replica_uuid ].status = " uninitialized"
812+ else
813+ log .error (" %s: %s" , err_msg , err )
814+ replica_state_by_uuid [replica_uuid ].message = tostring (err )
815+ end
816+ else
817+ log .error (err_msg )
818+ replica_state_by_uuid [replica_uuid ].message = err_msg
819+ end
820+ else
821+ replica_state_by_uuid [replica_uuid ].status = result [1 ].status or " uninitialized"
822+ end
823+ end
824+
825+ return replica_state_by_uuid
826+ end
827+
828+ --- Storage status information.
829+ --
830+ -- @function storage_info_on_storage
831+ --
832+ -- @return a table with storage status.
833+ function utils .storage_info_on_storage ()
834+ return {status = " running" }
835+ end
836+
751837return utils
0 commit comments