jackrabbit-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "David Rauschenbach" <david.rauschenb...@synchronica.com>
Subject Re: SPI caching, was: [jira] Resolved: (JCR-1361) Lock testassumesthat changes in one session are immediately visible in differentsession
Date Tue, 12 Feb 2008 12:54:53 GMT
 
I should have elaborated on the Repository factory problem.

Let's say someone implements the
org.apache.jackrabbit.commons.repository.RepositoryFactory interface.
They might have some constructor arguments, or some bean setters, for
setting properties like target host and protocol in a corba or web
service, or whatever.

Instantiating such a factory via Spring might look like this:

  <bean id="repoFactory" class="MyFactory">
    <property name="uri" value="iiop://server1/svc"/>
    <property name="debug" value="true"/>
  </bean>

  <bean id="repo"
    factory-bean="repoFactory"
    factory-method="getRepository"
  </bean>

So, the proprietary setter methods of the factory (setDebug(boolean) and
setUri(String)) have to pass over the SPI, in order to instantiate the
target Repository that is to be used by SPI2JCR.

And all that has to be able to happen when or before getDescriptors gets
called, which JCR2SPI calls before login.

In other words:

  1. You call getDescriptors on the repository, not the session. SPI
needs to reflect that.

  2. Repository factories and configuration are not addressed by JSR170, but SPI has to allow
it to occur anyway.

David



On Tue, 2008-02-12 at 12:51 +0100, David Rauschenbach wrote:
> Some other SPI deficiencies off the top of my head, while we're on the
> subject:
> 
>   1. Default workspace name. They should not be specified in JCR2SPI.
> When you log into Exchange or an IMAP server, or a SQL Server, you get a
> default namespace (or database) based on what the server thinks is the
> right default name for you. The name should not be known at the client
> (that's why it's a default!). Once you're logged in, you can ask for
> other namespace names, which also fits in nicely with JCR
> (Workspace.getAccessibleWorkspaceNames). But specifying a default
> namespace name in JCR2SPI is wrong, because a null should be passed when
> the server should choose.
> 
>   2. Repository descriptors over SPI. This is a deficiency. I have a web
> service that remotes SPI, and I can't ask the target web service for the
> repository descriptors. It doesn't help that JCR2SPI asks for the
> descriptors before a login. That makes it almost mandatory to mock up
> fake values in the SPI, before a dynamic proxy can initialize itself, if
> initialization is dependent on logging in, as is the case in 2 out of
> the 5 SPIs I have in front of me, or in cases where the target web
> service is deployed under the umbrella of container-managed security.
> 
>   3. Out-of-band data. Since JCR doesn't address configuration, or a
> RepositoryFactory pattern (even though Jackrabbit provides one), it is
> up to each implementation to get configuration done. SPI could use a
> place to pass this data. SimpleCredential attributes are not enough.
> IIOP for CORBA is a good example, where you can stuff profiles with your
> extra data, like timezone of the client, alternate server names,
> whatever. For SPI, the out-of-band data could be a place where the
> implementation-specific BatchReadConfig for a specific getItemInfos
> operation could be placed. I'm not sure this is a good idea for SPI, but
> I'm thinking about it.
> 
> David
> 
> 
> 
> On Mon, 2008-02-11 at 18:49 +0100, Julian Reschke wrote:
> > Julian Reschke wrote:
> > > At the end of the day, what we should do is *measure* the performance of 
> > > JCR2SPI compared to native implementations. I'll try to submit a few 
> > > tests soon.
> > > ...
> > 
> > OK, I've got tests (not polished) and numbers.
> > 
> > Scenario:
> > 
> > A collection /a/b with 500 members, each 1024 in size, content type 
> > application/octet-stream.
> > 
> > Test code that obtains all members, checking content type, size, and 
> > total number.
> > 
> > My store can do that in ~80ms.
> > 
> > Why doing it through SPI (with limited batch read support), it will take 
> > ~1500ms.
> > 
> > Wrapping that with JCR2SPI, it takes around ~2700ms.
> > 
> > So it seems we need drastically remove the overhead introduced by the 
> > SPI API.
> > 
> > Test code below:
> > 
> > 
> >    private String createTestCollJcr(String p_parentpath, int p_members, 
> > int p_size) throws Exception {
> >      Repository l_repository = getRepository();
> >      Session l_session = null;
> > 
> >      try {
> >        l_session = l_repository.login(getCredentials());
> > 
> >        Node l_folder = null;
> >        try {
> >          l_folder = (Node)l_session.getItem(p_parentpath + "/bigcoll");
> >        }
> >        catch (RepositoryException ex) {
> >          // nothing to do
> >        }
> > 
> >        // delete when needed
> >        if (l_folder != null) {
> >          l_folder.remove();
> >          l_session.save();
> >        }
> > 
> >        Node l_parent = (Node)l_session.getItem(p_parentpath);
> >        l_folder = l_parent.addNode("bigcoll", "nt:folder");
> >        assertNotNull(l_folder);
> > 
> >        long l_cnt = 0;
> > 
> >        while (l_cnt < p_members) {
> >          InputStream l_is = new BufferedInputStream(new 
> > ContentGenerator(p_size), p_size);
> >          Node l_new = l_folder.addNode("tst" + l_cnt, "nt:file");
> >          Node l_cnew = l_new.addNode("jcr:content", "nt:resource");
> >          l_cnew.setProperty("jcr:data", l_is);
> >          l_cnew.setProperty("jcr:mimeType", "application/octet-stream");
> >          l_session.save();
> >          l_cnt += 1;
> >        }
> >      }
> >      finally {
> >        if (l_session != null) {
> >          l_session.logout();
> >        }
> >      }
> > 
> >      return p_parentpath + "/bigcoll";
> >    }
> > 
> > 
> >    private static int BIGCOLLMEMBERS = 500;
> >    private static int BIGCOLLMEMBERSIZE = 1024;
> >    private static String BIGCOLLMIMETYPE = "application/octet-stream";
> > 
> >    public void testGetMembersSpi() throws Exception {
> > 
> >      String l_path = createTestColl(this.m_path, BIGCOLLMEMBERS, 
> > BIGCOLLMEMBERSIZE);
> > 
> >      RepositoryService l_rs = getRepositoryService();
> >      SessionInfo l_si = null;
> > 
> >      try {
> >        l_si = l_rs.obtain(getCredentials(), null);
> > 
> >        long l_start = System.currentTimeMillis();
> >        long l_cnt = 0;
> > 
> >        while (System.currentTimeMillis() - l_start < MS || l_cnt < 5) {
> >          NodeId l_nid = TestPerf.computeNodeId(l_rs, l_si, l_path);
> >          int l_members = 0;
> >          for (Iterator<ChildInfo> l_it = 
> > (Iterator<ChildInfo>)l_rs.getChildInfos(l_si, l_nid); l_it.hasNext(); ) {
> >            ChildInfo l_c = l_it.next();
> >            assertNotNull(l_c);
> >            NodeId l_cnid = 
> > l_rs.getIdFactory().createNodeId(l_c.getUniqueID());
> >            NodeInfo l_node = null;
> >            NodeInfo l_contentnode = null;
> >            PropertyInfo l_mimetype = null;
> >            PropertyInfo l_data = null;
> >            Iterator l_iteminfos = l_rs.getItemInfos(l_si, l_cnid);
> >            l_node = (NodeInfo)l_iteminfos.next();
> >            assertNotNull(l_node);
> > 
> >            while (l_iteminfos.hasNext()) {
> >              ItemInfo l_i = (ItemInfo)l_iteminfos.next();
> >              if (l_i.getParentId().equals(l_node.getId()) && 
> > NameConstants.JCR_CONTENT.equals(l_i.getName())) {
> >                l_contentnode = (NodeInfo)l_i;
> >              }
> >              if (l_contentnode != null && 
> > l_i.getParentId().equals(l_contentnode.getId()) && 
> > NameConstants.JCR_MIMETYPE.equals(l_i.getName())) {
> >                l_mimetype = (PropertyInfo)l_i;
> >              }
> >              if (l_contentnode != null && 
> > l_i.getParentId().equals(l_contentnode.getId()) && 
> > NameConstants.JCR_DATA.equals(l_i.getName())) {
> >                l_data = (PropertyInfo)l_i;
> >              }
> >            }
> > 
> >            if (l_contentnode == null) {
> >              // explicitly fetch the content node, it wasn't returned 
> > with the parent
> >              NodeId l_contentnodeid = 
> > l_rs.getIdFactory().createNodeId(l_c.getUniqueID(), 
> > l_rs.getPathFactory().create(NameConstants.JCR_CONTENT));
> >              Iterator l_iteminfos2 = l_rs.getItemInfos(l_si, 
> > l_contentnodeid);
> >              l_contentnode = (NodeInfo)l_iteminfos2.next();
> >              while (l_iteminfos2.hasNext()) {
> >                ItemInfo l_i = (ItemInfo)l_iteminfos2.next();
> >                if (l_i.getParentId().equals(l_contentnode.getId()) && 
> > NameConstants.JCR_MIMETYPE.equals(l_i.getName())) {
> >                  l_mimetype = (PropertyInfo)l_i;
> >                }
> >                if (l_i.getParentId().equals(l_contentnode.getId()) && 
> > NameConstants.JCR_DATA.equals(l_i.getName())) {
> >                  l_data = (PropertyInfo)l_i;
> >                }
> >              }
> >            }
> > 
> >            assertNotNull(l_contentnode);
> > 
> >            if (l_mimetype == null) {
> >              // explicitly fetch the mime type property, it wasn't 
> > returned with the parent
> >              PropertyId l_mimetypeid = 
> > l_rs.getIdFactory().createPropertyId(l_contentnode.getId(), 
> > NameConstants.JCR_MIMETYPE);
> >              l_mimetype = l_rs.getPropertyInfo(l_si, l_mimetypeid);
> >            }
> > 
> >            assertNotNull(l_mimetype);
> >            assertEquals(BIGCOLLMIMETYPE, 
> > l_mimetype.getValues()[0].getString());
> > 
> >            if (l_data == null) {
> >              // explicitly fetch the mime type property, it wasn't 
> > returned with the parent
> >              PropertyId l_dataid = 
> > l_rs.getIdFactory().createPropertyId(l_contentnode.getId(), 
> > NameConstants.JCR_DATA);
> >              l_data = l_rs.getPropertyInfo(l_si, l_dataid);
> >            }
> > 
> >            assertNotNull(l_data);
> >            assertEquals(BIGCOLLMEMBERSIZE, 
> > l_data.getValues()[0].getLength());
> > 
> >            l_members += 1;
> >          }
> >          assertEquals(BIGCOLLMEMBERS, l_members);
> >          l_cnt += 1;
> >        }
> > 
> >        long l_elapsed = System.currentTimeMillis() - l_start;
> > 
> >        LOG.info(String.format("GetMembers - SPI: %.4fms per call (%d 
> > iterations)", (double)l_elapsed / l_cnt, l_cnt));
> > 
> >      }
> >      finally {
> >        if (l_si != null) {
> >          l_rs.dispose(l_si);
> >        }
> >      }
> >    }
> > 
> >    public void testGetMembersJcr() throws Exception {
> > 
> >      String l_path = createTestCollJcr(this.m_path, BIGCOLLMEMBERS, 
> > BIGCOLLMEMBERSIZE);
> > 
> >      Repository l_repository = getRepository();
> >      Session l_session = null;
> > 
> >      try {
> >        l_session = l_repository.login(getCredentials(), null);
> > 
> >        long l_start = System.currentTimeMillis();
> >        long l_cnt = 0;
> > 
> >        while (System.currentTimeMillis() - l_start < MS || l_cnt < 5) {
> >          Node l_dir = (Node)l_session.getItem(l_path);
> >          assertNotNull(l_dir);
> >          int l_members = 0;
> >          for (NodeIterator l_it = l_dir.getNodes(); l_it.hasNext(); ) {
> >            Node l_c = l_it.nextNode();
> >            Node l_e = l_c.getNode("jcr:content");
> >            String l_type = l_e.getProperty("jcr:mimeType").getString();
> >            long l_length = l_e.getProperty("jcr:data").getLength();
> >            assertTrue(l_c.isNode());
> >            assertEquals(BIGCOLLMIMETYPE, l_type);
> >            assertEquals(BIGCOLLMEMBERSIZE, l_length);
> >            l_members += 1;
> >          }
> >          assertEquals(BIGCOLLMEMBERS, l_members);
> >          l_session.refresh(false);
> >          l_cnt += 1;
> >        }
> > 
> >        long l_elapsed = System.currentTimeMillis() - l_start;
> > 
> >        LOG.info(String.format("GetMembers - JCR: %.4fms per call (%d 
> > iterations)", (double)l_elapsed / l_cnt, l_cnt));
> > 
> >      }
> >      finally {
> >        if (l_session != null) {
> >          l_session.logout();
> >        }
> >      }
> >    }
> > 
> >    private class ContentGenerator extends InputStream {
> > 
> >      private long m_length;
> >      private long m_position;
> > 
> >      public ContentGenerator(long p_length) {
> >        this.m_length = p_length;
> >        this.m_position = 0;
> >      }
> > 
> >      public int read() {
> > 
> >        if (this.m_position++ < this.m_length) {
> >          return 0;
> >        }
> >        else {
> >          return -1;
> >        }
> >      }
> >    }
> > 
> 
>  
> Visit Synchronica at GSMA Mobile World Congress, Barcelona, 11-14 Feb, Hall 2, Booth
#2J25
>  
> 

 
Visit Synchronica at GSMA Mobile World Congress, Barcelona, 11-14 Feb, Hall 2, Booth #2J25
 
 

Mime
View raw message