49 #define COMPATIBLE_NETSCHEDULE_VERSION "4.10.0"
55 namespace netschedule {
88 "Could not bind a UDP socket: " <<
IO_StatusStr(status));
95 string*
cmd,
unsigned remaining_seconds)
97 if (remaining_seconds > 0) {
130 string* attr_values,
size_t attr_count)
141 if ((attr_it = attr_parser.
FindFirst(*attr_names)) !=
143 *attr_values = attr_it->value;
148 }
while (--attr_count > 0);
167 *ns_node = parser(
"ns_node");
169 const auto reason = parser(
"reason");
220 *ns_node = *next_server;
236 static const STimeout two_seconds = {2, 0};
250 switch (notif_type) {
287 const CDeadline& deadline,
string* server_host)
294 if (timeout.
sec == 0 && timeout.
usec == 0)
316 printf(
"Using UDP port %hu\n",
GetPort());
377 return ns_conf ?
"netschedule_conf_from_netschedule" :
"netcache_conf_from_netschedule";
381 m_Registry(
registry), m_Sections(sections), m_NsConf(ns_conf), m_Mode(eImplicit)
385 const auto param =
"load_config_from_ns";
396 if (name ==
"queue_name")
return true;
400 if (name ==
"timeout") {
407 if (name ==
"client_name")
return false;
411 name.erase(0,
prefix.size());
440 auto retry_guard =
impl->m_Service->CreateRetryGuard(retry_mode);
456 for (
auto& param : queue_params) {
457 auto name = param.first;
460 mem_registry->Set(section, name, param.second);
464 if (mem_registry->
Empty())
return false;
479 version = &app->GetFullVersion();
480 name = app->GetProgramDisplayName();
486 auto package_name =
version->GetPackageName();
488 if (!package_name.empty()) {
506 auth +=
" client_type=\"admin\"";
510 auth +=
" client_type=\"submitter\"";
514 auth +=
" client_type=\"worker node\"";
518 auth +=
" client_type=\"reader\"";
525 auth +=
" client_node=\"";
531 auth +=
" client_session=\"";
537 auth +=
" client_version=\"";
538 auth +=
version->GetVersionInfo().Print();
555 auth +=
"\r\nVERSION";
582 (user.empty() ?
kEmptyStr : user +
'@') +
587 bool affinities_initialized =
false;
604 if (!affinities_initialized &&
registry.
Get(sections,
"use_affinities",
false)) {
605 affinities_initialized =
true;
620 }
while (loader(
this));
626 string version_info(connection.
Exec(
m_Auth,
false));
630 string attr_name, attr_value;
631 string ns_node, ns_session;
635 if (attr_name ==
"ns_node")
636 ns_node = attr_value;
637 else if (attr_name ==
"ns_session")
638 ns_session = attr_value;
639 else if (attr_name ==
"server_version")
643 if (!ns_node.empty() && !ns_session.empty()) {
647 if (server_props->ns_node != ns_node ||
648 server_props->ns_session != ns_session) {
650 server_props->ns_node = ns_node;
651 server_props->ns_session = ns_session;
652 server_props->version =
version;
654 server_props->affs_synced =
false;
674 if (err_msg ==
"Job not found") {
713 const string& service_name,
const string& client_name,
714 const string& queue_name,
bool wn,
bool try_config) :
715 m_Mode(GetMode(wn, try_config)),
722 registry_builder, sections);
723 Init(registry_builder, sections);
728 m_Mode(parent->m_Mode),
729 m_SharedData(parent->m_SharedData),
730 m_RetryOnException(parent->m_RetryOnException),
732 m_Queue(parent->m_Queue),
733 m_ProgramVersion(parent->m_ProgramVersion),
734 m_ClientNode(parent->m_ClientNode),
735 m_ClientSession(parent->m_ClientSession),
736 m_AffinityPreference(parent->m_AffinityPreference),
737 m_UseEmbeddedStorage(parent->m_UseEmbeddedStorage)
742 const string& conf_section ) :
748 const string& conf_section) :
759 const string& client_name,
const string& queue_name) :
766 m_Impl->m_ProgramVersion = pv;
768 m_Impl->UpdateAuthString();
773 return m_Impl->m_ProgramVersion;
789 case eDone:
return "Done";
825 #define EXTRACT_WARNING_TYPE(warning_type) \
826 if (NStr::StartsWith(warn_msg, "e" #warning_type ":")) { \
827 warn_msg.erase(0, sizeof("e" #warning_type ":") - 1); \
828 return eWarn##warning_type; \
855 #define WARNING_TYPE_TO_STRING(warning_type) \
856 case eWarn##warning_type: \
857 return #warning_type;
862 switch (warning_type) {
882 return "eWarnUnknown";
897 const string& affinity)
899 m_Impl->AllocNotificationThread();
915 if (job_exptime !=
NULL)
921 const string& mode_str)
923 if (pause_mode !=
NULL)
936 cmd +=
" need_progress_msg=1";
937 auto response =
m_Impl->ExecOnJobServer(job,
cmd);
955 job.
input = parser(
"input");
956 job.
output = parser(
"output");
991 if (job_exptime !=
NULL)
1018 known_server = server_props_it->second;
1039 string cmd(
"QINF2 " + queue);
1053 if (field->name[0] ==
'm') {
1054 if (field->name ==
"max_input_size") {
1055 field_bits |= (1 << eMaxInputSize);
1058 }
else if (field->name ==
"max_output_size") {
1059 field_bits |= (1 << eMaxOutputSize);
1064 if (field_bits == (1 << eNumberOfSizeParams) - 1)
1073 return m_Impl->GetServerParams();
1079 string cmd(
"QINF2 ");
1081 if (!queue_name.empty()) {
1082 limits::Check<limits::SQueueName>(queue_name);
1085 }
else if (!
m_Queue.empty()) {
1096 queue_params[field->name] = field->value;
1103 return m_Impl->GetQueueParams(queue_name, queue_params);
1108 string cmd(
"GETP2");
1115 queue_params[field->name] = field->value;
1121 return m_Impl->GetQueueParams(queue_params);
1128 auto response = m_Impl->ExecOnJobServer(job,
cmd);
1135 if (client_node.empty()) {
1137 "'" << limits::SClientNode::Name() <<
"' cannot be empty");
1140 limits::Check<limits::SClientNode>(client_node);
1142 m_Impl->m_ClientNode = client_node;
1144 m_Impl->UpdateAuthString();
1150 if (client_session.empty()) {
1152 "'" << limits::SClientSession::Name() <<
"' cannot be empty");
1155 limits::Check<limits::SClientSession>(client_session);
1157 m_Impl->m_ClientSession = client_session;
1159 m_Impl->UpdateAuthString();
1171 m_Impl->m_ClientType = client_type;
1173 m_Impl->UpdateAuthString();
1184 const string& param_value)
1186 if (!param_value.empty()) {
1187 string auth_param(
' ' + param_name);
1188 auth_param +=
"=\"";
1200 const bool claim_new_affinities =
registry.
Get(sections,
"claim_new_affinities",
false);
1201 const bool process_any_job =
registry.
Get(sections,
"process_any_job",
false);
1205 if (affinity_ladder.empty()) {
1207 if (claim_new_affinities) {
1210 }
else if (process_any_job) {
1217 if (affinity_list.empty())
return;
1223 limits::Check<limits::SAffinity>(affinity);
1230 if (claim_new_affinities) {
1232 "'affinity_ladder' cannot be used with 'claim_new_affinities'");
1234 if (!affinity_list.empty()) {
1236 "'affinity_ladder' cannot be used with 'affinity_list'");
1239 if (!process_any_job) {
1243 list<CTempString> affinities;
1247 if (affinities.empty())
return;
1249 string affinity_step;
1251 for (
auto& affinity : affinities) {
1252 limits::Check<limits::SAffinity>(affinity);
1254 if (!affinity_step.empty()) affinity_step +=
',';
1255 affinity_step += affinity;
1282 int patch_level = -1)
1283 : m_DriverVersionInfo
1288 m_DriverName(driver_name)
1290 _ASSERT(!m_DriverName.empty());
1299 if (params && (driver.empty() || driver == m_DriverName) &&
1310 info_list.push_back(
TDriverInfo(m_DriverName, m_DriverVersionInfo));
1331 string& client_node(m_Impl->m_ClientNode);
1333 client_node += data;
1339 m_Impl->UpdateAuthString();
1344 m_Impl->UseOldStyleAuth();
1359 limits::Check<limits::SClientNode>(client_node);
1360 m_Impl->m_ClientNode = client_node;
1361 m_Impl->UpdateAuthString();
1366 limits::Check<limits::SClientSession>(client_session);
1367 m_Impl->m_ClientSession = client_session;
1368 m_Impl->UpdateAuthString();
1373 const string& client_name)
1380 const string& client_name,
const string& queue_name)
Pool of recycled CCompoundID objects.
static CNcbiApplication * Instance(void)
Singleton method.
IClassFactory< SNetScheduleAPIImpl > TParent
CVersionInfo m_DriverVersionInfo
virtual TInterface * CreateInstance(const string &driver=kEmptyStr, CVersionInfo version=NCBI_INTERFACE_VERSION(IFace), const TPluginManagerParamTree *params=0) const
Create instance of TDriver.
TParent::TDriverList TDriverList
SNetScheduleAPIImpl IFace
void GetDriverVersions(TDriverList &info_list) const
Versions of the interface exported by the factory.
TParent::SDriverInfo TDriverInfo
CNetScheduleAPICF(const string &driver_name=kNetScheduleAPIDriverName, int patch_level=-1)
Construction.
SNetScheduleAPIImpl TDriver
Client API for NCBI NetSchedule server.
CNetScheduleConfigLoader(CSynRegistry ®istry, SRegSynonyms §ions, bool ns_conf=true)
bool Transform(const string &prefix, string &name) const
bool operator()(SNetScheduleAPIImpl *impl)
enum CNetScheduleConfigLoader::@969 m_Mode
const SRegSynonyms & m_Sections
CSynRegistry & m_Registry
NetSchedule internal exception.
Smart pointer to a part of the NetSchedule API that does job retrieval and processing on the worker n...
Smart pointer to a part of the NetSchedule API that allows to retrieve completed jobs.
unsigned short GetPort() const
CNetScheduleNotificationHandler()
bool WaitForNotification(const CDeadline &deadline, string *server_host=NULL)
SNetScheduleNotificationReceiver m_Receiver
bool ReceiveNotification(string *server_host=NULL)
CRef< SNetScheduleSharedData > m_SharedData
void OnConnected(CNetServerConnection &connection) override
void OnErrorImpl(const string &err_msg, CNetServer &server) override
void OnWarningImpl(const string &warn_msg, CNetServer &server) override
CNetScheduleServerListener(bool non_wn, SNetScheduleSharedData *shared_data)
TPropCreator GetPropCreator() const override
void SetAuthString(const string &auth)
INetServerConnectionListener * Clone() override
Smart pointer to the job submission part of the NetSchedule API.
string Exec(const string &cmd, bool multiline_output=false, const STimeout *timeout=NULL)
Execute remote command 'cmd', wait for the reply, check that it starts with 'OK:',...
bool GetNextAttribute(string &attr_name, string &attr_value)
Return the next attribute.
CNetServer::SExecResult FindServerAndExec(const string &cmd, bool multiline_output=false)
bool IsLoadBalanced() const
CNetServiceIterator Iterate(EIterationMode mode=eSortByLoad)
void Add(const IRegistry ®istry)
TR< TType >::T Get(const SRegSynonyms §ions, SRegSynonyms names, TType default_value)
bool Has(const SRegSynonyms §ions, SRegSynonyms names)
CTempString implements a light-weight string on top of a storage buffer whose lifetime management is ...
definition of a Culling tree
const_iterator end() const
const_iterator find(const key_type &key) const
iterator_bool insert(const value_type &val)
const_iterator begin() const
parent_type::iterator iterator
static CNcbiApplicationGuard InstanceGuard(void)
Singleton method.
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
TValue Add(int delta) THROWS_NONE
Atomically add value (=delta), and return new counter value.
const string & GetHost(void) const
Get host name.
string GetStringUID(TUID uid=0) const
Return string representation of UID.
CDiagContext & GetDiagContext(void)
Get diag context instance.
static TPID GetPID(void)
Get cached PID (read real PID if not cached yet).
void SetDiagUserAndHost(TDiagUserAndHost flags=fDiag_AddUser|fDiag_AddHost)
Set username and hostname properties for the diag context.
#define ERR_POST(message)
Error posting with file, line number information but without error codes.
TErrCode GetErrCode(void) const
Get error code.
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
void Warning(CExceptionArgs_Base &args)
#define NCBI_THROW_FMT(exception_class, err_code, message)
The same as NCBI_THROW but with message processed as output to ostream.
virtual const char * what(void) const noexcept
Standard report (includes full backlog).
@ eInvalid
To be used ONLY as a return value; please, NEVER throw an exception with this code.
EJobStatus
Job status codes.
CNetScheduleSubmitter GetSubmitter()
Create an instance of CNetScheduleSubmitter.
string output
Job result data.
void GetQueueParams(const string &queue_name, TQueueParams &queue_params)
static const char * GetErrCodeDescription(CException::TErrCode err_code)
EJobStatus GetJobDetails(CNetScheduleJob &job, time_t *job_exptime=NULL, ENetScheduleQueuePauseMode *pause_mode=NULL)
Get job details.
void SetClientSession(const string &client_session)
static ENetScheduleWarningType ExtractWarningType(string &warn_msg)
CNetScheduleJobReader GetJobReader(const string &group=kEmptyStr, const string &affinity=kEmptyStr)
Create an instance of CNetScheduleJobReader.
CNetScheduleAPI::TJobMask mask
int ret_code
Job return code.
static string StatusToString(EJobStatus status)
Printable status type.
const string & GetProgramVersion() const
Get program version string.
CNetRef< SNetScheduleAPIImpl > m_Impl
const string & GetQueueName() const
Return Queue name.
static const char * WarningTypeToString(ENetScheduleWarningType warning_type)
void GetProgressMsg(CNetScheduleJob &job)
Update the progress_message field of the job structure.
EAppRegistry
Defines how this object must be initialized.
void SetClientType(EClientType client_type)
const SServerParams & GetServerParams()
void SetProgramVersion(const string &pv)
Set program version (like: MyProgram v.
CNetScheduleExecutor GetExecutor()
Create an instance of CNetScheduleExecutor.
static EJobStatus StringToStatus(const CTempString &status_str)
Parse status string into enumerator value.
CNetScheduleAdmin GetAdmin()
static CException::TErrCode GetCode(const string &name)
string job_id
Output job key.
void SetClientNode(const string &client_node)
@ eDeleted
The job has been wiped out of the database.
@ eDone
Job is ready (computed successfully)
@ eConfirmed
Final state - read confirmed.
@ eReading
Job has its output been reading.
@ eCanceled
Explicitly canceled.
@ eRunning
Running on a worker node.
@ eJobNotFound
No such job.
@ ePending
Waiting for execution.
@ eReadFailed
Final state - read failed.
@ eFailed
Failed to run (execution timeout)
@ eExplicitAffinitiesOnly
TObjectType & GetObject(void)
Get object.
bool Empty(void) const THROWS_NONE
Check if CRef is empty – not pointing to any object, which means having a null value.
ncbi::TDriverList TDriverList
static void NCBI_EntryPointImpl(TDriverInfoList &info_list, EEntryPointRequest method)
Entry point implementation.
#define NCBI_INTERFACE_VERSION(iface)
Macro to construct CVersionInfo class using interface name (relies on CInterfaceVersion class)
ncbi::SDriverInfo SDriverInfo
virtual const string & Get(const string §ion, const string &name, TFlags flags=0) const
Get the parameter value.
#define END_NCBI_SCOPE
End previously defined NCBI scope.
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
EIO_Status Wait(const STimeout *timeout=kInfiniteTimeout)
EIO_Status Bind(unsigned short port)
EIO_Status Recv(void *buf, size_t buflen, size_t *msglen=0, string *sender_host=0, unsigned short *sender_port=0, size_t maxmsglen=0)
ESwitch SetDataLogging(ESwitch log=eOn)
EIO_Status SetTimeout(EIO_Event event, const STimeout *timeout)
Set timeout for I/O in the specified direction.
EIO_Status Send(const void *data, size_t datalen, const string &host=string(), unsigned short port=0)
unsigned short GetLocalPort(ENH_ByteOrder byte_order, bool trueport=false) const
Get socket local port number.
static string PrintableString(const CTempString str, TPrintableMode mode=fNewLine_Quote|fNonAscii_Passthru)
Get a printable version of the specified string.
static int CompareNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2)
Case-insensitive compare of a substring with another string.
static int StringToInt(const CTempString str, TStringToNumFlags flags=0, int base=10)
Convert string to int.
static list< string > & Split(const CTempString str, const CTempString delim, list< string > &arr, TSplitFlags flags=0, vector< SIZE_TYPE > *token_pos=NULL)
Split a string using specified delimiters.
static string ParseEscapes(const CTempString str, EEscSeqRange mode=eEscSeqRange_Standard, char user_char='?')
Parse C-style escape sequences in the specified string.
static string UIntToString(unsigned int value, TNumToStringFlags flags=0, int base=10)
Convert UInt to string.
static bool StartsWith(const CTempString str, const CTempString start, ECase use_case=eCase)
Check if a string starts with a specified prefix value.
static Uint8 StringToUInt8(const CTempString str, TStringToNumFlags flags=0, int base=10)
Convert string to Uint8.
static bool SplitInTwo(const CTempString str, const CTempString delim, string &str1, string &str2, TSplitFlags flags=0)
Split a string into two pieces using the specified delimiters.
static enable_if< is_arithmetic< TNumeric >::value||is_convertible< TNumeric, Int8 >::value, string >::type NumericToString(TNumeric value, TNumToStringFlags flags=0, int base=10)
Convert numeric value to string.
static int CompareCase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2)
Case-sensitive compare of a substring with another string.
@ fConvErr_NoThrow
Do not throw an exception on error.
@ fSplit_MergeDelimiters
Merge adjacent delimiters.
bool Run(TRunMode flags=fRunDefault)
Run the thread.
static void SetCurrentThreadName(const CTempString &)
Set name for the current thread.
bool TryWait(unsigned int timeout_sec=0, unsigned int timeout_nsec=0)
Timed wait.
void Post(unsigned int count=1)
Increment the semaphore by "count".
void Join(void **exit_data=0)
Wait for the thread termination.
CNanoTimeout GetRemainingTime(void) const
Get time left to the expiration.
CTime GetFastLocalTime(void)
Quick and dirty getter of local time.
void Get(unsigned int *sec, unsigned int *microsec) const
Get timeout in seconds and microseconds.
TArgs::const_iterator const_iterator
const TArgs & GetArgs(void) const
Get the const list of arguments.
iterator FindFirst(const string &name)
Find the first argument with the given name.
unsigned int usec
microseconds (modulo 1,000,000)
const char * IO_StatusStr(EIO_Status status)
Get the text form of an enum status value.
@ eIO_Timeout
timeout expired before any I/O succeeded
@ eIO_Success
everything is fine, no error occurred
@ eNonCompatible
major, minor does not match
#define NCBI_XCONNECT_EXPORT
void ThrowIllegalChar(const string &name, const string &value, char c)
Magic spell ;-) needed for some weird compilers... very empiric.
static void s_SetJobExpTime(time_t *job_exptime, const string &time_str)
#define WARNING_TYPE_TO_STRING(warning_type)
#define EXTRACT_WARNING_TYPE(warning_type)
CTempString s_GetSection(bool ns_conf)
CUrlArgs s_CreateCUrlArgs(const string &output)
int g_ParseNSOutput(const string &attr_string, const char *const *attr_names, string *attr_values, size_t attr_count)
static void s_SetPauseMode(ENetScheduleQueuePauseMode *pause_mode, const string &mode_str)
void NCBI_EntryPoint_xnetscheduleapi(CPluginManager< SNetScheduleAPIImpl >::TDriverInfoList &info_list, CPluginManager< SNetScheduleAPIImpl >::EEntryPointRequest method)
#define COMPATIBLE_NETSCHEDULE_VERSION
const char *const kNetScheduleAPIDriverName
ENetScheduleQueuePauseMode
Defines whether the job queue is paused, and if so, defines the pause mode set by the administrator.
const unsigned int kNetScheduleMaxDBDataSize
void g_AppendClientIPSessionIDHitID(string &cmd)
static const TDS_WORD limits[]
static const char * prefix[]
static pcre_uint8 * buffer
Helper classes and templates to implement plugins.
static SQLCHAR output[256]
void ReSetClientSession(const string &)
void AddToClientNode(const string &data)
void ReSetClientNode(const string &)
CCompoundIDPool GetCompoundIDPool()
static TInstance CreateWnCompat(const string &, const string &)
static TInstance CreateNoCfgLoad(const string &, const string &, const string &)
CNetScheduleAPI GetServer(CNetServer::TInstance server)
Extract one of the servers comprising this service as a separate NetSchedule API object.
function< INetServerProperties *()> TPropCreator
void OnWarning(const string &warn_msg, CNetServer &server)
SCompoundIDObjectPool< SCompoundIDImpl, ECompoundIDClass > m_CompoundIDPool
const CNetScheduleAPI::SServerParams & operator()(CNetService &service, const string &queue)
constexpr static long kAskMaxCount
CNetScheduleAPI::SServerParams m_ServerParams
CNetScheduleExecutor::EJobAffinityPreference m_AffinityPreference
CRef< SNetScheduleSharedData > m_SharedData
CNetScheduleGetJob::TAffinityLadder m_AffinityLadder
CFastMutex m_NotificationThreadMutex
void StartNotificationThread()
void AllocNotificationThread()
bool GetServerByNode(const string &ns_node, CNetServer *server)
CNetScheduleAPI::EClientType m_ClientType
CNetScheduleServerListener * GetListener()
CAtomicCounter_WithAutoInit m_NotificationThreadStartStopCounter
void SetAuthParam(const string ¶m_name, const string ¶m_value)
bool m_UseEmbeddedStorage
void Init(CSynRegistry ®istry, SRegSynonyms §ions)
string ExecOnJobServer(const TJob &job, const string &cmd, ESwitch roe=eDefault)
void InitAffinities(CSynRegistry ®istry, const SRegSynonyms §ions)
SNetScheduleAPIImpl(CSynRegistryBuilder registry_builder, const string §ion, const string &service_name=kEmptyStr, const string &client_name=kEmptyStr, const string &queue_name=kEmptyStr, bool wn=false, bool try_config=true)
CNetScheduleAPI::EJobStatus GetJobStatus(string cmd, const CNetScheduleJob &job, time_t *job_exptime, ENetScheduleQueuePauseMode *pause_mode)
list< string > m_AffinityList
CRef< SNetScheduleNotificationThread > m_NotificationThread
void GetQueueParams(const string &queue_name, TQueueParams &queue_params)
bool operator()(string *server_host)
SNetScheduleNotificationReceiver()
SServerNotifications m_GetNotifications
unsigned short GetPort() const
SNetScheduleAPIImpl * m_API
virtual void * Main()
Derived (user-created) class must provide a real thread function.
void CmdAppendPortAndTimeout(string *cmd, unsigned remaining_seconds)
SNetScheduleNotificationReceiver m_Receiver
ENotificationType CheckNotification(string *ns_node)
SServerNotifications m_ReadNotifications
SNetScheduleNotificationThread(SNetScheduleAPIImpl *ns_api)
const string & operator()(const string ¶m) const
SNetScheduleOutputParser(const string &output)
CFastMutex m_ServerByNodeMutex
TServerByNode m_ServerByNode
void WriteLine(const string &line)
CRef< SNetServerInPool > m_ServerInPool
CRef< TProperties > Get()
CNetServer::SExecResult ConnectAndExec(const string &cmd, bool multiline_output, bool retry_on_exception=false)
void ResetServerConnections()
CRef< SNetServerInPool > ReturnServer(SNetServerInPool *server_impl)
CNetServerPool m_ServerPool
static SNetServiceImpl * Create(const string &api_name, const string &service_name, const string &client_name, INetServerConnectionListener *listener, CSynRegistry ®istry, SRegSynonyms §ions, const string &ns_client_name=kEmptyStr)
const string & GetClientName() const
void Insert(CTempString s)
void x_ClearInterruptFlag()
TReadyServers m_ReadyServers
bool GetNextNotification(string *ns_node)
void RegisterServer(const string &ns_node)
CSemaphore m_NotificationSemaphore
int g(Seg_Gsm *spe, Seq_Mtf *psm, Thd_Gsm *tdg)