I have seen that attribute concept exists in Hazelcast. I want to define attributes for each member while it is starting and detect which member left the cluster using these attributes.
I could not find how to set it programmatically or by configuration.I tried to get the attributes by the getAttributes() method and add a new attribute but it throws an exception since it is an unmodifiable collection.
How can I set attributes of a cluster member?
You can set up attributes in the member configuration and then read them from the client. For example, you can start a Hazelcast cluster in which one member has some attributes assigned and the other does not.
// Member with attributes
Config config = new Config();
config.getMemberAttributeConfig().setAttribute("key-1", "value-1");
Hazelcast.newHazelcastInstance(config);
// Member without attributes
Hazelcast.newHazelcastInstance();
Then, in the client, you can read the attributes.
HazelcastInstance client = HazelcastClient.newHazelcastClient();
for (Member member : client.getCluster().getMembers()) {
System.out.println("Member attributes: " + member.getAttributes());
}
It should print the attributes.
Member attributes: {key-1=value-1}
Member attributes: {}
Related
I'm working on the LDAP overlay of MitreID Connect project and everthing is working greatly:
Authentication
Retrieving attributes from LDAP Directory
The problem I have now, is how to retrieve operational attributes in LDAP directory.
I'm not good with Spring development, but I found some documentation which treat this sub, but I'm not able to make it work.
Here's what I found:
Retrieving operational attributes
Ldap Server maintains many operational attributes internally. Example entryUUID is an operational attribute assigns the Universally Unique Identifier (UUID) to the entry. The createTimestamp, modifyTimestamp are also operational attributes assigned to the entry on create or update. These operational attributes does not belong to an object class and hence they were not returned as part of your search or lookup. You need to explicitly request them by their name in your search or build the custom AttributeMapper implementation with matching attribute names.
Now let’s try to retrieve the entryUUID, first you need to build the search controls like this,
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
controls.setReturningObjFlag(false);
controls.setReturningAttributes(new String[]{"entryUUID"});
Once you have search control then it’s simply calling search method just like retrieving any other attributes.
ldapTemplate.search("baseName", "(objectclass=person)", controls, new AttributesMapper() {
public Object mapFromAttributes(Attributes attrs) throws NamingException {
Attribute attrUuid = attrs.get("entryUUID");
return attrUuid;
}});
Here is another way to do the same using ContextMapper,
ldapTemplate.search("baseName","(objectclass=person)", 1, new String[]{"entryUUID"},
new ContextMapper(){
public Object mapFromContext(Object ctx) {
DirContextAdapter context = (DirContextAdapter)ctx;
return context.getStringAttributes("entryUUID");
}
});
Let’s add the filter based off of operational attributes like below,
OrFilter orFilter = new OrFilter();
orFilter.or(new GreaterThanOrEqualsFilter("createTimestamp", "YYYYMMDDHHMMSSZ"));
orFilter.or(new LessThanOrEqualsFilter("modifyTimestamp", "YYYYMMDDHHMMSSZ"));
Now call the above search with the filter
ldapTemplate.search("baseName", orFilter.encode(), controls, new AttributesMapper() {
public Object mapFromAttributes(Attributes attrs) throws NamingException {
Attribute attrUuid = attrs.get("entryUUID");
return attrUuid;
}});
Let's say I have two types of Hazelcast nodes running on cluster:
"Leader" nodes – these are able to load and populate Hazelcast map M. Leaders will also update values in M from time to time (based on external resource).
"Follower" nodes – these will need to read from M
My intent is for Follower nodes to trigger loading missing elements into M (loading thus needs to be done on Leader side) .
Roughly, the steps made to get an element from map could look like this:
IMap m = hazelcastInstance.getMap("M");
if (!m.containsKey(k)) {
if (iAmLeader()) {
Object fresh = loadByKey(k); // loading from external resource
return m.put(k, fresh);
} else {
makeSomeLeaderPopulateValueForKey(k);
}
}
return m.get(k);
What approach could you suggest?
Notes
I want Followers to act as nodes, not just clients, because there are going to be far more Follower instances than Leaders and I would like them to participate in load distribution.
I could just build another level of service, that would run only on Leader nodes and provide interface to populate map with requested keys. But that would mean adding extra layer of communication and configuration, and I was hoping that the kind of requirements stated above could be solved within single Hazelcast cluster.
I think I may have found an answer in the form of MapLoader (EDIT since originally posting, I have confirmed this is indeed the way to do this).
final Config config = new Config();
config.getMapConfig("MY_MAP_NAME").setMapStoreConfig(
new MapStoreConfig().setImplementation(new MapLoader<KeyType, ValueType>(){
#Override
public ValueType load(final KeyType key) {
//when a client asks for data for corresponding key of type
//KeyType that isn't already loaded
//this function will be invoked and give you a chance
//to load it and return it
ValueType rv = ...;
return rv;
}
#Override
public Map<KeyType, ValueType> loadAll(
final Collection<KeyType> keys) {
//Similar to MapLoader#load(KeyType), except this is
//a batched version of it for performance gains.
//this gets called on first access to the cache,
//where MapLoader#loadAllKeys() is called to get
//the keys parameter for this funcion
Map<KeyType, ValueType> rv = new HashMap<>();
keys.foreach((key)->{
rv.put(key, /*figure out what key means*/);
});
return rv;
}
#Override
public Set<KeyType> loadAllKeys() {
//Prepopulate all the keys. My understanding is that
//this is an initialization step, to give you a chance
//to load data on startup so an initial set of datas
//will be available to anyone using the cache. Any keys
//returned here are sent to MapLoader#loadAll(Collection)
Set<KeyType> rv = new HashSet<>();
//figure out what keys need to be in the return value
//to load a key into cache at first access to this map,
//named "MY_MAP_NAME" in this example
return rv;
}
}));
config.getGroupConfig().setName("MY_INSTANCE_NAME").setPassword("my_password");
final HazelcastInstance hazelcast = Hazelcast
.getOrCreateHazelcastInstance(config);
I have a base class "Entity" and a derived class "Site" or "Group". Both are marked as serializable. I am sending them to the service bus and retrieving as follows. None of the inherited properties are set after reading, however; it's as if they are ignored during deserialization. Any way I can get these to work or do I need to write my own XML deserializer?
var queueEntity = new QueueEntity(e); // e is Entity, Site
var brokered = new BrokeredMessage(queueEntity);
QueueContext.QueueClient.Send(brokered);
Worker role
var message = receivedMessage.GetBody<QueueEntity>();
var e = message.Entity; // this only has derived class property values set
Thanks!
You could serialize it using existing serializers and pass into BrokeredMesdage as a Stream. On the receiving side do the other way around, serializing from a Stream into your object.
I am trying to retrieve all DCs from domain and would also like to know if they are readable or writable.
To know if DC is readable or not, I need to read attribute primaryGroupID value for DC. Trying same in code below.
Code snippet -
var currDomain = Domain.GetCurrentDomain();
foreach (DomainController dc in currDomain.DomainControllers)
{
var dcName = dc.Name;
var de = dc.GetDirectoryEntry(); // DirectoryEntry represent DC
// Loads the values of the specified properties into the property cache.
de.RefreshCache(new[] {"primaryGroupID"});
if (de.Properties.Contains("primaryGroupID"))
{
int primaryGroupID;
var strPrimaryGroupID = Convert.ToString(de.Properties["primaryGroupID"][0]);
if (int.TryParse(strPrimaryGroupID, out primaryGroupID))
{
// RID for the "Read-only Domain Controllers" built-in group in Active Directory
// Writable Domain Controllers have primaryGroupID set to 516 (the "Domain Controllers" group).
dcName = string.Format(primaryGroupID == 521 ? "{0} (Read only)" : "{0} (Writable)", dc.Name);
}
}
}
However still property don't show up. I had confirmed from AD that the respective attribute exists for DC.
The default properties that show up are shown in screenshot below -
Do you have any clue why the property primaryGroupID is missing?
dc.GetDirectoryEntry() returns a server object, not the computer object of the DC. And primaryGroupID doesn't exist on server objects. But it does contain a reference to the computer object. Try this:
var dcDe = dc.GetDirectoryEntry(); // DirectoryEntry represent DC
var de = new DirectoryEntry("LDAP://" + dcDe.Properties["serverReference"].Value);
if (de.Properties.Contains("primaryGroupID"))
...
I have a couple of tables in my schema with PK and FK relationships. I have created the DAL using the SubSonic generator. If I create a new parent and its children, how should I save both? Separately or in one shot?
e.g.
Parent.Save();
ChildCollection.SaveAll();
I tried the above, but it does not work because ChildCollection does not have its parent's ID. Is it that I have to assign parent IDs for each child myself or is there an option to save it all in one shot?
Assumption: That your Primary Keys are auto generated by your Data Base. If so, what you will need to do first is Save() the parent and then populate the ParentID property in each of the objects in your ChildrenCollection. Once you have done that, you will be able to Save() your ChildrenCollection.
Parent.Save();
ChildCollection.ForEach(x => x.ParentID = Parent.ParentID);
ChildCollection.SaveAll();
You can use partial classes with custom overload of save function to provide the desired functionality.
public partial class Class1
{
public void Save(bool childern)
{
Save();
if (childern)
{
//based on primary/foreign key SubSonic provides
//methods to fetch child collections related to
//this (primary key) table.
ChildernCollection col = Childerns();
col.SaveAll();
}
}
}