Skip to content

IncDesIncDes Requests

laforge49 edited this page Oct 6, 2011 · 7 revisions

There may be times when we just need to get or set the value of the root block of a data store. E.G. It makes it easy to copy the entire data store. GetRootRequest and SetRootRequest perform these operations. These same operations also apply to an IncDesIncDes--which Block subclasses.

##RootRequestsTest

The first test simply creates an IncDesInt and assigns it to the contents of the root block ("/$").

{
  val systemServices = SystemServices(new ServicesRootComponentFactory)
  val dbName = "SmallNoLog.db"
  val file = new java.io.File(dbName)
  file.delete
  val properties = new Properties
  properties.put("dbPathname", dbName)
  val db = Subsystem(
    systemServices,
    new SmallNoLogComponentFactory,
    properties = properties,
    actorId = ActorId("db"))
  val results = new Results
  val chain = new Chain(results)
  chain.op(systemServices, Register(db))
  chain.op(db, SetRequest(db, "/$", IncDesInt(null)), "timestamp")
  Future(systemServices, chain)
  println(results)
  systemServices.close
}

Output.

{timestamp=1348541751760896}

The second test does the following:

  1. A get on the root block ("/").
  2. A get on the contents of the root block ("/$").
  3. Sets the contents of the root block to null.
  4. Another get on the contents of the root block.

Here's the code for the second test.

{
  val systemServices = SystemServices(new ServicesRootComponentFactory)
  val dbName = "SmallNoLog.db"
  val properties = new Properties
  properties.put("dbPathname", dbName)
  val db = Subsystem(
    systemServices,
    new SmallNoLogComponentFactory,
    properties = properties,
    actorId = ActorId("db"))
  val chain = new Chain
  chain.op(systemServices, Register(db))
  chain.op(db, GetRequest(db, "/"), "root")
  chain.op(db, GetRequest(db, "/$"), "IncDesInt")
  chain.op(db, SetRequest(db, "/$", null), "timestamp")
  chain.op(db, GetRequest(db, "/$"), "null")
  Future(systemServices, chain)
  println(chain.results)
  systemServices.close
}

Output.

{IncDesInt=org.agilewiki.incDes.IncDesInt@34bf1d3b, 
 null=null, 
 root=org.agilewiki.incDes.blocks.Block@6f18278a,
 timestamp=1348541751792640}

RootRequestsTest

##SmallNoLogComponentFactory

SmallNoLogComponentFactory defines the dependencies of the data store. SmallTransactionsComponentFactory, in turn, registers various request factories, including SetRequestFactory and GetRequestFactory, and adds a dependency on NoDbInitializationComponentFactory.

class SmallNoLogDataStoreComponentFactory
  extends ComponentFactory {
  addDependency(classOf[SmallDataStoreComponentFactory])
  addDependency(classOf[NullTransactionLogComponentFactory])
  addDependency(classOf[SmallTransactionsComponentFactory])
}

SmallNoLogComponentFactory

##SetRequest

Here are the invocations of SetRequest:

chain.op(db, SetRequest(db, "/$", IncDesInt(null)), "timestamp")
chain.op(db, SetRequest(db, "/$", null), "timestamp")

SetRequest does not support a pathname of "/".

There are three things to note in the implementation of SetRequest:

  1. In the apply method of the SetRequest companion object, the configure method is called on the factory and the request is given the system services of the data store. This is required because the request is an IncDesStringIncDesMap.
  2. In the process method of the class of SetRequestComponent, it is a copy of the value of the request which is assigned to the root block. This is because an IncDes object can only have a single container.
  3. The IncDes value is copied, allowing it to be used again to create other requests.

Implementation.

object SetRequest {
  def apply(db: Actor, pathname: String, value: IncDes) = {
    var pn = pathname
    if (pn.startsWith("/")) pn = pn.substring(1)
    val pnid = IncDesString(null)
    val pnidid = IncDesIncDes(null)
    val vidid = IncDesIncDes(null)
    val jef = new SetRequestFactory
    jef.configure(db)
    val je = jef.newActor(null).asInstanceOf[IncDes]
    je.setSystemServices(db.systemServices)
    val chain = new Chain
    chain.op(je, Put[String, IncDesIncDes, IncDes](null, "pathname", pnidid))
    chain.op(pnidid, Set(null, pnid))
    chain.op(pnid, Set(null, pn))
    chain.op(je, Put[String, IncDesIncDes, IncDes](null, "value", vidid))
    chain.op(value, Copy(null), "copy")
    chain.op(vidid, Unit => Set(null, chain("copy").asInstanceOf[IncDes]))
    chain.op(db, TransactionRequest(je))
    chain
  }
}

class SetRootRequestFactory 
  extends IncDesStringIncDesMapFactory(DBT_SET) {
  override protected def instantiate = {
    val req = new IncDesIncDes
    addComponent(new UpdateRequestComponent(req))
    addComponent(new SetRequestComponent(req))
    req
  }
}

class SetRootRequestComponent(actor: Actor)
  extends Component(actor) {
  bindSafe(classOf[Process], new ChainFactory(process))

  private def process(msg: AnyRef, chain: Chain) {
    val transactionContext = msg.asInstanceOf[Process].transactionContext
    var key = ""
    chain.op(actor, GetValue("pathname"), "pathnameId")
    chain.op(Unit => chain("pathnameId"), Value(), "pathname")
    chain.op(actor, GetValue("value"), "value")
    chain.op(Unit => chain("value"), Copy(null), "copy")
    chain.op(systemServices, DbRoot(), "dbRoot")
    chain.op(Unit => chain("dbRoot"),
      Unit => Resolve(chain("pathname").asInstanceOf[String]), "tuple")
    chain.op(Unit => {
      val (incDes, k) = chain("tuple").asInstanceOf[(IncDes, String)]
      key = k
      incDes
    }, Unit => Assign(transactionContext, key, chain("copy").asInstanceOf[IncDes]))
  }
}

SetRequest

##GetRequest

Here are the invocations of GetRequest:

chain.op(db, GetRequest(db, "/"), "root")
chain.op(db, GetRequest(db, "/$"), "IncDesInt")
chain.op(db, GetRequest(db, "/$"), "null")

One thing to note in the implementation. In the apply method of the GetRootRequestComponent, a copy of the root block value is returned rather than the root block value itself, as the value should not be accessed outside of a transactional context.

object GetRootRequest {
  def apply(db: Actor, pathname: String) = {
    var pn = pathname
    if (pn.startsWith("/")) pn = pn.substring(1)
    if (!pn.endsWith("/") && pn.length > 0) pn = pn + "/"
    val je = (new GetRequestFactory).newActor(null).asInstanceOf[IncDes]
    val chain = new Chain
    chain.op(je, Set(null, pn))
    chain.op(db, TransactionRequest(je))
    chain
  }
}

class GetRequestFactory extends IncDesStringFactory(DBT_GET) {
  override protected def instantiate = {
    val req = super.instantiate
    addComponent(new QueryRequestComponent(req))
    addComponent(new GetRequestComponent(req))
    req
  }
}

class GetRootRequestComponent(actor: Actor)
  extends Component(actor) {
  bindSafe(classOf[Process], new ChainFactory(process))

  private def process(msg: AnyRef, chain: Chain) {
    chain.op(actor, Value(), "pathname")
    chain.op(systemServices, DbRoot(), "dbRoot")
    chain.op(Unit => chain("dbRoot"),
      Unit => Resolve(chain("pathname").asInstanceOf[String]), "tuple")
    chain.op(Unit => {
      val (value, key) = chain("tuple").asInstanceOf[(IncDes, String)]
      value
    }, Copy(null))
  }
}

GetRequest


tutorial

Clone this wiki locally