Merged context masking

This paper discusses one concrete issue related to merged contexts: masking of deleted items. Merged context is discussed in issue 34057. It is expected that reader read comments in the issue and is familiar with MultiFilesystems and its implementation of masking of files.

Two solutions are presented here:
  • multiFS like solution
  • external storage

1. MultiFS like solution

MultiFS uses for masking special files with names which ends with _hidden and with attributes with special value VoidValue. The merged context can use the same approch. For the clients of merged context the merging is transparent. Situation changes if client access directly the writable layer - it contains bunch of internal stuff which is used to implement masking.

Below is list of all possible usage scenarios of merged context and their impact on writable layer and how the masking will be implemented. Following contexts are used in the examples: R, W and M. M is merged context of [W, R]. W is writtable layer of  merged context. R is readonly layer of merged context. All context are SPI contexts, ie. BasicContext descendants.

It is also expected that clients can later access directly the writable layer and they need to distinguish internal masking staff from real context content.

A.) Delete binding

  M.bindObject("B", null);
results in
  if (notExistBinding(W,"B")) {
    W.bindObject("B", whateverValue);
  }
  W.setAttribute("B", "DELETED_BINDING", whateverValue);

Comments:
  • the deleted binding is always masked without regard to its existence on the R. It makes the rules for masking simpler and guarantees that once the B was deleted it stays deleted.
  • M ignores and does not report bindings which has "DELETED_BINDING" attribute set to non-null value
  • M ignores and does not report binding attribute with name "DELETED_BINDING"
  • W can use boolean MergedContextUtils.isBindingDeleted(W, "B") to identify and/or ignore deleted bindings
  • W can use boolean MergedContextUtils.isInternalAttribute(W, "B", "DELETED_BINDING") to ignore internal attributes

B.) Modify binding

  M.bindObject("B", someValue);
results in
  if (notExistBinding(W,"B")) {
     copyAttributes = true;
  }
  W.bindObject("B", someValue);
  W.setAttribute("DELETED_BINDING", null);
  if (copyAttributes) {
     // copy all attrs of R.B to W.B here
  }

Comments:
  • because binding attributes are not merged they have to be copied from layer R when object is being created on layer W.

C.) Set binding attribute

  M.setAttribute("B", "A", someValue);
results in
  if (notExistBinding(W,"B")) {
    W.bindObject("B", R.lookupObject("B"));
     // copy all attrs of R.B to W.B here
  }
  W.setAttribute("B", "A", someValue);

Comments:
  • binding attributes are not merged
  • because binding attributes are not merged they have to be copied from layer R when object is being created on layer W.

D.) Delete binding attribute

  M.setAttribute("B", "A", null);
results in
  if (notExistBinding(W,"B")) {
    W.bindObject("B", R.lookupObject("B"));
    // copy all attrs of R.B to W.B here
  }
  W.setAttribute("B", "A", null);

E.) Set context attribute

  M.setAttribute(null, "A", someValue);
results in
  W.setAttribute(null, "A", someValue);

Comments:
  • context attributes are merged. That's opposite to binding attributes.

F.) Delete context attribute

  M.setAttribute(null, "A", null);
results in
  W.setAttribute(null, "A", "DELETED_ATTRIBUTE");

Comments:
  • M ignores and does not report context attributes with value "DELETED_ATTRIBUTE"
  • W can use boolean MergedContextUtils.isAttributeDeleted(W, null, "A") to identify and/or ignore deleted attributes

G.) Destroy subcontext

  M.destroySubcontext("S");
results in
  W.setAttribute(null, "DELETED_SUBCONTEXT_"+"S", whateverValue);

Comments:
  • subcontext is not physically deleted on writable layer. It is just masked out.
  • M ignores and does not report context attributes with name starting with "DELETED_SUBCONTEXT_"
  • M ignores and does not report subcontexts which are according to existence of "DELETED_SUBCONTEXT_<subcontext_name>" attribute deleted
  • W can use boolean MergedContextUtils.isSubcontextDeleted(W, "S") to identify and/or ignore deleted subcontexts
  • W can use boolean MergedContextUtils.isInternalAttribute(W, null, "DELETED_SUBCONTEXT_<subcontext_name>") to ignore internal attributes

H.) Create subcontext

  M.createSubcontext("S");
results in
  W.createSubcontext("S");
  W.setAttribute(null, "DELETED_SUBCONTEXT_"+"S", null);

Summary of all used masks

Following masks are used:
  • "DELETED_BINDING" - name of binding attribute. Binding having this attribute was deleted.
  • "DELETED_ATTRIBUTE" - value of binding attribute. Attribute with this value was deleted.
  • "DELETED_SUBCONTEXT_<subcontext_name>" - name of context attribute. Context with this attribute contains deleted subcontext with name <subcontext_name>.
Following methods would be needed in API for clients to identify and/or ignore masking implementation. It is better to have explicit API rather then leting clients compare the Strings directly:
  • isBindingDeleted(BasicContext ctx, String bindingName)
  • isAttributeDeleted(BasicContext ctx, String bindingNameOrNullForContext, String attrName)
  • isSubcontextDeleted(BasicContext ctx, String subcontextName);
  • isInternalAttribute(BasicContext ctx, String bindingNameOrNullForContext, String attrName)

2. External storage solution

This is modification of previous solution with only difference that masks are not stored in W layer, but in separate storage. The storage could be for example Properties file and it would be up to clients of merged context whether and how they persist the properties file. For example default context registry (aka SFS) could store the properties file somewhere in the userdir.

A.) Delete binding

  M.bindObject("B", null);
results in
  properties.setProperty(M.getAbsoluteContextName()+":DELETED_BINDING:"+"B", "yes");

B.) Modify binding

  M.bindObject("B", someValue);
results in
  if (notExistBinding(W,"B")) {
     copyAttributes = true;
  }
  W.bindObject("B", someValue);
  if (copyAttributes) {
     // copy all attrs of R.B to W.B here
  }
  properties.setProperty(M.getAbsoluteContextName()+":DELETED_BINDING:"+"B", null);

C.) Set binding attribute

  M.setAttribute("B", "A", someValue);
results in
  if (notExistBinding(W,"B")) {
    W.bindObject("B", R.lookupObject("B"));
    // copy all attrs of R.B to W.B here
  }
  W.setAttribute("B", "A", someValue);

D.) Delete binding attribute

  M.setAttribute("B", "A", null);
results in
  if (notExistBinding(W,"B")) {
    W.bindObject("B", R.lookupObject("B"));
    // copy all attrs of R.B to W.B here
  }
  W.setAttribute("B", "A", null);

E.) Set context attribute

  M.setAttribute(null, "A", someValue);
results in
  W.setAttribute(null, "A", someValue);
  properties.setProperty(M.getAbsoluteContextName()+":DELETED_CONTEXT_ATTRIBUTE:"+"A", null);

F.) Delete context attribute

  M.setAttribute(null, "A", null);
results in
  properties.setProperty(M.getAbsoluteContextName()+":DELETED_CONTEXT_ATTRIBUTE:"+"A", "yes");

G.) Destroy subcontext

  M.destroySubcontext("S");
results in
  properties.setProperty(M.getAbsoluteContextName()+":DELETED_SUBCONTEXT:"+"S", "yes");

H.) Create subcontext

  M.createSubcontext("S");
results in
  W.createSubcontext("S");
  properties.setProperty(M.getAbsoluteContextName()+":DELETED_SUBCONTEXT:"+"S", null);


Project Features

About this Project

openide was started in November 2009, is owned by Antonin Nebuzelsky, and has 92 members.
By use of this website, you agree to the NetBeans Policies and Terms of Use (revision 20160708.bf2ac18). © 2014, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo
 
 
Close
loading
Please Confirm
Close