RetCode BOSS_CALL ServiceRegistry::AddService(IServiceInfo *service) { try { std::lock_guard<std::recursive_mutex> Lock(Mtx); if (!service) return Status::InvalidArgument; IServiceInfoPtr Info(service); ServiceId SrvId = 0; RetCode Res = Info->GetServiceId(&SrvId); if (Res != Status::Ok) return Res; RefObjPtr<IEnum> ClassIdsEnum; Res = Info->GetClassIds(ClassIdsEnum.GetPPtr()); if (Res != Status::Ok) return Res; typedef std::vector<ClassId> ClassIdPool; ClassIdPool ClassIds; if (ClassIdsEnum->Reset() != Status::Ok) return Status::Fail; for (RefObjPtr<IBase> i ; ClassIdsEnum->Next(i.GetPPtr()) == Status::Ok ; i.Release()) { RefObjQIPtr<IEntityId> Id(i); if (!Id.Get()) return Status::Fail; ClassId ClsId = 0; Res = Id->GetId(&ClsId); if (Res != Status::Ok) return Res; if (Services.find(ClsId) != std::end(Services)) return Status::Fail; ClassIds.push_back(ClsId); } auto Pred = [&] (decltype(*ServicePool::const_iterator()) &info) { ServiceId Id = 0; return info.second->GetServiceId(&Id) == Status::Ok && Id == SrvId; }; auto Iter = std::find_if(std::begin(Services), std::end(Services), Pred); if (Iter != std::end(Services)) return Status::AlreadyExists; for (auto const &i : ClassIds) Services[i] = Info; } catch (...) { return Status::Fail; } return Status::Ok; }
RetCode BOSS_CALL ServiceRegistry::Load(IIStream *stream) { if (!stream) return Status::InvalidArgument; std::lock_guard<std::recursive_mutex> Lock(Mtx); try { auto Registry = PropertyBagType::Create(RegistryTag); RetCode Code = Registry->Load(stream); if (Code != Status::Ok) return Code; RefObjPtr<IBase> ServiceEnumProp; if ((Code = Registry->GetProperty(ServicesTag, ServiceEnumProp.GetPPtr())) != Status::Ok) return Code; RefObjQIPtr<IEnum> ServiceEnum(ServiceEnumProp); if (!ServiceEnum.Get()) return Status::Fail; ServicePool NewServices; for (RefObjPtr<IBase> i ; ServiceEnum->Next(i.GetPPtr()) == Status::Ok ; i.Release()) { RefObjQIPtr<IPropertyBag> ServiceItem(i); if (!ServiceItem.Get()) return Status::Fail; RefObjPtr<IBase> EntId; if ((Code = ServiceItem->GetProperty(ServiceIdTag, EntId.GetPPtr())) != Status::Ok) return Code; RefObjQIPtr<IEntityId> EntSrvId(EntId); if (!EntSrvId.Get()) return Status::Fail; ServiceId SrvId = 0; if ((Code = EntSrvId->GetId(&SrvId)) != Status::Ok) return Code; RefObjPtr<IBase> ClassIdsEnumProp; if ((Code = ServiceItem->GetProperty(ClassIdsTag, ClassIdsEnumProp.GetPPtr())) != Status::Ok) return Code; RefObjQIPtr<IEnum> ClassIdsEnum(ClassIdsEnumProp); if (!ClassIdsEnum.Get()) return Status::Fail; RefObjPtr<IBase> ModulePathProp; RefObjPtr<IServiceInfo> ServiceInfo; if (ServiceItem->GetProperty(ModulePathTag, ModulePathProp.GetPPtr()) == Status::Ok) { RefObjQIPtr<IString> ModulePath(ModulePathProp); if (!ModulePath.Get()) return Status::Fail; auto LocalSrvInfo = Base<LocalServiceInfo>::Create(); LocalSrvInfo->SetServiceId(SrvId); LocalSrvInfo->AddCoClassIds(ClassIdsEnum); LocalSrvInfo->SetModulePath(ModulePath); ServiceInfo = LocalSrvInfo; } else { RefObjPtr<IBase> RemotePropertiesProp; if (ServiceItem->GetProperty(RemotePropertiesTag, RemotePropertiesProp.GetPPtr()) == Status::Ok) { RefObjQIPtr<IPropertyBag> RemoteProperties(RemotePropertiesProp); if (!RemoteProperties.Get()) return Status::Fail; auto RemoteSrvInfo = Base<RemoteServiceInfo>::Create(); RemoteSrvInfo->SetServiceId(SrvId); RemoteSrvInfo->AddCoClassIds(ClassIdsEnum); RemoteSrvInfo->SetProps(RemoteProperties); ServiceInfo = RemoteSrvInfo; } else return Status::Fail; } if ((Code = ClassIdsEnum->Reset()) != Status::Ok) return Code; for (RefObjPtr<IBase> j ; ClassIdsEnum->Next(j.GetPPtr()) == Status::Ok ; j.Release()) { RefObjQIPtr<IEntityId> ClsId(j); if (!ClsId.Get()) return Status::Fail; ClassId Id = 0; if ((Code = ClsId->GetId(&Id)) != Status::Ok) return Code; NewServices[Id] = ServiceInfo; } } std::swap(Services, NewServices); return Status::Ok; } catch (...) { return Status::Fail; } return Status::Ok; }