Physical storage model of node and relation in 1 neo4j
1.1 NEO4J Storage Model
The node records contain only a pointer to their the "a" and "their" (in relationship is what the _ Relationship chain). From this, we can follow the (doubly) linked-list of relationships until we find the one we ' re interested in, the likes R Elationship from Node 1 to node, 2 in the. Once we ' ve found the relationship record of interest, we can simply read it properties if there are any via the same sing ly-linked list structure as node properties, or we can examine the node records that it relates via its start node and end Node IDs. These IDs, multiplied by the node record size, of course give the immediate offset of both nodes in the node store file.
The above English excerpt from <graph databases> (author: Ianrobinson) describes the NEO4J storage model. The property of node and relationship is saved with a key-value bidirectional list, node relatsionship is saved with a two-way list, and it is easy to find the from-to node of the relationship through the relationship. Node nodes hold the 1th attribute and the 1th relationship ID.
Through the storage model above, starting from a node-a, it is convenient to traverse the graph with the node-a as the starting point. Here is an example to help understand the storage model above, and the specific format of the storage file is described in detail in chapter 2nd.
1.2 Example 1
In this example, A~e represents the node's number, R1~R7 represents the relationship number, and P1~P10 represents the property's number.
The storage sample diagram for node is as follows, with each node saving the 1th and 1th relationship:
The storage diagram for the relationship is as follows:
From the schematic, it can be seen from the node-b start, through the relationship of the next pointer, you can traverse the node-b of all the relationships, and then you can reach the 1th layer of their relationship nodes, through the traversal of the 1th layer nodes relationship, can reach the 2nd layer nodes,...
2 neo4j Graph DB Storage File Introduction
When we download the NEO4J-COMMUNITY-2.1.0-M01 and install it, and then run it with the embeddedneo4j example of the neo4j embedded-example, we can see that in target/ The following NEO4J graph DB storage files are generated under NEO4J-HELLO-DB.
-rw-r–r–11 04-11 13:28 Active_tx_log
Drwxr-xr-x 4096 04-11 13:28 Index
-rw-r–r–23740 04-11 13:28 Messages.log
-rw-r–r–78 04-11 13:28 Neostore
-rw-r–r–9 04-11 13:28 neostore.id
-rw-r–r–22 04-11 13:28 neostore.labeltokenstore.db
-rw-r–r–9 04-11 13:28 neostore.labeltokenstore.db.id
-rw-r–r–64 04-11 13:28 Neostore.labeltokenstore.db.names
-rw-r–r–9 04-11 13:28 neostore.labeltokenstore.db.names.id
-rw-r–r–61 04-11 13:28 neostore.nodestore.db
-rw-r–r–9 04-11 13:28 neostore.nodestore.db.id
-rw-r–r–93 04-11 13:28 Neostore.nodestore.db.labels
-rw-r–r–9 04-11 13:28 neostore.nodestore.db.labels.id
-rw-r–r–307 04-11 13:28 neostore.propertystore.db
-rw-r–r–153 04-11 13:28 Neostore.propertystore.db.arrays
-rw-r–r–9 04-11 13:28 neostore.propertystore.db.arrays.id
-rw-r–r–9 04-11 13:28 neostore.propertystore.db.id
-rw-r–r–61 04-11 13:28 Neostore.propertystore.db.index
-rw-r–r–9 04-11 13:28 neostore.propertystore.db.index.id
-rw-r–r–216 04-11 13:28 Neostore.propertystore.db.index.keys
-rw-r–r–9 04-11 13:28 neostore.propertystore.db.index.keys.id
-rw-r–r–410 04-11 13:28 neostore.propertystore.db.strings
-rw-r–r–9 04-11 13:28 neostore.propertystore.db.strings.id
-rw-r–r–69 04-11 13:28 neostore.relationshipgroupstore.db
-rw-r–r–9 04-11 13:28 neostore.relationshipgroupstore.db.id
-rw-r–r–92 04-11 13:28 neostore.relationshipstore.db
-rw-r–r–9 04-11 13:28 neostore.relationshipstore.db.id
-rw-r–r–38 04-11 13:28 neostore.relationshiptypestore.db
-rw-r–r–9 04-11 13:28 neostore.relationshiptypestore.db.id
-rw-r–r–140 04-11 13:28 Neostore.relationshiptypestore.db.names
-rw-r–r–9 04-11 13:28 neostore.relationshiptypestore.db.names.id
-rw-r–r–82 04-11 13:28 neostore.schemastore.db
-rw-r–r–9 04-11 13:28 neostore.schemastore.db.id
-rw-r–r–4 04-11 13:28 nioneo_logical.log.active
-rw-r–r–2249 04-11 13:28 Nioneo_logical.log.v0
Drwxr-xr-x 4096 04-11 13:28 schema
-rw-r–r–0 04-11 13:28 Store_lock
-rw-r–r–800 04-11 13:28 Tm_tx_log.1
2.1 Storage node's files
1 storage node data and its sequence ID
NEOSTORE.NODESTORE.DB: Storage node Array, the subscript of the array is the ID of the node
Neostore.nodestore.db.id: Store the largest ID and the ID of free
2 Storage node label and its sequence ID
Neostore.nodestore.db.labels: Stores node label array data, and the subscript of the array is the ID of the node label
Neostore.nodestore.db.labels.id
2.2 Storage of relationship files
1 store relational data and their sequence IDs
Neostore.relationshipstore.db Storage relational Record array data
Neostore.relationshipstore.db.id
2 Store relational group data and their sequence IDs
NEOSTORE.RELATIONSHIPGROUPSTORE.DB Storage Relational Group array data
Neostore.relationshipgroupstore.db.id
3 Store relationship types and their sequence IDs
Neostore.relationshiptypestore.db store relational Type array data
Neostore.relationshiptypestore.db.id
4 Store the name of the relationship type and its sequence ID
Neostore.relationshiptypestore.db.names Storage relational type token array data
Neostore.relationshiptypestore.db.names.id
2.3 Files that store label
1 store label token data and its sequence ID
Neostore.labeltokenstore.db store lable token array data
Neostore.labeltokenstore.db.id
2 Store label token name data and its sequence ID
Neostore.labeltokenstore.db.names store names data for label token
Neostore.labeltokenstore.db.names.id
2.4 Files that store the property
1 Store property data and its sequence ID
Neostore.propertystore.db Store Property Data
Neostore.propertystore.db.id
2 storing the array type data in the property data and its sequence ID
The value value of the Neostore.propertystore.db.arrays storage property (Key-value structure) is the data for the array.
Neostore.propertystore.db.arrays.id
3 The property data is a long string type of storage file and its sequence ID
The value value of the Neostore.propertystore.db.strings storage property (Key-value structure) is the data for the string.
Neostore.propertystore.db.strings.id
4 Index data file of attribute data and its sequence ID
Neostore.propertystore.db.index the index data for the key that stores the property (Key-value structure).
Neostore.propertystore.db.index.id
5 The key value data store file of the property data and its sequence ID
Neostore.propertystore.db.index.keys the string value of the key that stores the property (Key-value structure).
Neostore.propertystore.db.index.keys.id
2.5 Other documents
1 Storing version information
Neostore
Neostore.id
2 Storing schema data
Neostore.schemastore.db
Neostore.schemastore.db.id
3 Logical log of activity
Nioneo_logical.log.active
4 log file name of the currently active record
Active_tx_log
3 NEO4J Storage Structure
In neo4j, there are 4 types of nodes, attributes, relationships, and other files that are based on arrays as core storage structures, and each data item of a node, attribute, relationship, etc., is assigned a unique ID, which is the subscript of the array when stored. This enables fast positioning by using its ID as the subscript at the time of access. So in the diagram traversal and other operations, you can achieve free-index.
3.1 Neo4j's Store section class diagram
3.1.1 Commonabstractstore.java
Commonabstractstore is the base class for all store classes, the following code fragment is the Commonabstractstore member variable, the more important is the floating several, especially idgenerator, each store instance has its own ID Assignment Manager; Storechannel is responsible for the reading and writing of the store files and Windowspool is the cache associated with the store record to improve performance.
The code is as follows |
Copy Code |
<div>public Abstract class Commonabstractstore implements Idsequence
{
public static abstract class Configuration
{
public static final Setting store_dir = InternalAbstractGraphDatabase.Configuration.store_dir;
public static final Setting neo_store = InternalAbstractGraphDatabase.Configuration.neo_store;
public static final Setting read_only = graphdatabasesettings.read_only;
public static final Setting backup_slave = Graphdatabasesettings.backup_slave;
public static final Setting use_memory_mapped_buffers = graphdatabasesettings.use_memory_mapped_buffers;
}
public static final String all_stores_version = "V0." A.2 ";
public static final String unknown_version = "Uknown";
protected Config configuration;
Private final idgeneratorfactory idgeneratorfactory;
Private final windowpoolfactory windowpoolfactory;
protected Filesystemabstraction filesystemabstraction;
Protected final File Storagefilename;
Protected final Idtype Idtype;
protected Stringlogger Stringlogger;
Private Idgenerator idgenerator = null;
Private Storechannel FileChannel = null;
Private Windowpool Windowpool;
Private Boolean storeok = true;
Private Throwable Causeofstorenotok;
Private Filelock Filelock;
Private Boolean readOnly = false;
Private Boolean backupslave = false;
Private Long Highestupdaterecordid =-1;
|
1.2 neo4j DB files and their corresponding storage format types
Filename |
File storage format |
Neostore.labeltokenstore.db |
Labeltokenstore (Tokenstore) |
Neostore.labeltokenstore.db.id |
ID type |
Neostore.labeltokenstore.db.names |
Stringpropertystore (abstractdynamicstore, name_store_block_size = 30) |
Neostore.labeltokenstore.db.names.id |
ID type |
Neostore.nodestore.db |
Nodestore |
Neostore.nodestore.db.id |
ID type |
Neostore.nodestore.db.labels |
Arraypropertystore (abstractdynamicstorelabel_block_size=60) |
Neostore.nodestore.db.labels.id |
ID type |
Neostore.propertystore.db |
PropertyStore |
Neostore.propertystore.db.arrays |
Arraypropertystore (abstractdynamicstorearray_block_size=120) |
Neostore.propertystore.db.arrays.id |
ID type |
Neostore.propertystore.db.id |
ID type |
Neostore.propertystore.db.index |
Propertyindexstore |
Neostore.propertystore.db.index.id |
ID type |
Neostore.propertystore.db.index.keys |
Stringpropertystore (abstractdynamicstore, name_store_block_size = 30) |
Neostore.propertystore.db.index.keys.id |
ID type |
Neostore.propertystore.db.strings |
Stringpropertystore (abstractdynamicstorestring_block_size=120) |
Neostore.propertystore.db.strings.id |
ID type |
Neostore.relationshipgroupstore.db |
Relationshipgroupstore |
Neostore.relationshipgroupstore.db.id |
ID type |
Neostore.relationshipstore.db |
Relationshipstore |
Neostore.relationshipstore.db.id |
ID type |
Neostore.relationshiptypestore.db |
Relationshiptypetokenstore (Tokenstore) |
Neostore.relationshiptypestore.db.id |
ID type |
Neostore.relationshiptypestore.db.names |
Stringpropertystore (abstractdynamicstore, name_store_block_size = 30) |
Neostore.relationshiptypestore.db.names.id |
ID type |
Neostore.schemastore.db |
Schemastore (Abstractdynamicstore, block_size = 56) |
Neostore.schemastore.db.id |
ID type |
3.3 General Store Type
3.3.1 ID Type
Below is neo4j db, each store has its own ID file (suffix. id file), and they all have the same format.
[test00] $ls-lh target/neo4j-test00.db/|grep. Id
-rw-r–r–9 04-11 13:28 neostore.id
-rw-r–r–9 04-11 13:28 neostore.labeltokenstore.db.id
-rw-r–r–9 04-11 13:28 neostore.labeltokenstore.db.names.id
-rw-r–r–9 04-11 13:28 neostore.nodestore.db.id
-rw-r–r–9 04-11 13:28 neostore.nodestore.db.labels.id
-rw-r–r–9 04-11 13:28 neostore.propertystore.db.arrays.id
-rw-r–r–9 04-11 13:28 neostore.propertystore.db.id
-rw-r–r–9 04-11 13:28 neostore.propertystore.db.index.id
-rw-r–r–9 04-11 13:28 neostore.propertystore.db.index.keys.id
-rw-r–r–9 04-11 13:28 neostore.propertystore.db.strings.id
-rw-r–r–9 04-11 13:28 neostore.relationshipgroupstore.db.id
-rw-r–r–9 04-11 13:28 neostore.relationshipstore.db.id
-rw-r–r–9 04-11 13:28 neostore.relationshiptypestore.db.id
-rw-r–r–9 04-11 13:28 neostore.relationshiptypestore.db.names.id
-rw-r–r–9 04-11 13:28 neostore.schemastore.db.id
Storage format for 3.3.1.1 ID type files
The file format with the suffix ". Id" in neo4j is composed of the file header (9 Bytes) and the long array 2 parts, as shown in the previous illustration:
Sticky (1 byte): If sticky the id generator wasn ' t closed properly so it has to berebuilt (go through the node, Relationsh IP, property, rel type etc files.
Nextfreeid (Long): holds the largest ID, which corresponds to the array size of the storage array of the corresponding type.
Reuseid (Long): Used to hold the freed and reusable ID values. By reusing IDs, you can reduce the empty array of resources and increase disk utilization.
3.3.1.2 Idgeneratorimpl.java
The ID allocation neo4j for each resource type is implemented through IDGENERATORIMPL, which is responsible for ID management allocation and recovery reuse. For each resource type, a node, relationship, attribute, and so on, a idgenerator instance can be generated to handle its ID management allocation and recovery reuse.
3.3.1.2.1 read ID file for initialization
In the following trial Idgeneratorimpl.java, the process of reading the ID file for initialization, Idgeneratorimpl reads the GRABSIZE reusable ID (Reuseid) from the ID file to Idsreadfromfile ( linkedlist<long>), the reusable ID in Idsreadfromfile is prioritized when an application ID is required.
Initialize the ID generator and performs a simple validation
Private synchronized void Initgenerator ()
{
Try
{
FileChannel = Fs.open (FileName, "RW");
Bytebuffer buffer = bytebuffer.allocate (header_size);
Readheader (buffer);
Markassticky (buffer);
Filechannel.position (header_size);
Maxreadposition = Filechannel.size ();
Defraggedidcount = (int) (maxreadposition-header_size)/8;
Readidbatch ();
}
catch (IOException E)
{
throw New Underlyingstorageexception (
"Unable to init ID generator" + fileName, E);
}
}
private void Readheader (Bytebuffer buffer) throws IOException
{
Readposition = filechannel.read (buffer);
if (readposition!= header_size)
{
Filechannel.close ();
throw New Invalididgeneratorexception (
"Unable to read header, Bytes read:" + readposition);
}
Buffer.flip ();
byte Storagestatus = Buffer.get ();
if (storagestatus!= clean_generator)
{
Filechannel.close ();
throw new Invalididgeneratorexception ("Sticky generator[" +
FileName + "] Delete this ID file and build a new one");
}
This.highId.set (Buffer.getlong ());
}
private void Readidbatch ()
{
if (!canreadmoreidbatches ())
Return
Try
{
int howmuchtoread = (int) math.min (grabsize*8, maxreadposition-readposition);
Bytebuffer Readbuffer = bytebuffer.allocate (Howmuchtoread);
Filechannel.position (readposition);
int bytesread = Filechannel.read (Readbuffer);
Assert Filechannel.position () <= maxreadposition;
Readposition + = Bytesread;
Readbuffer.flip ();
ASSERT (bytesread% 8) = = 0;
int idsread = BYTESREAD/8;
Defraggedidcount-= Idsread;
for (int i = 0; i < idsread; i++)
{
Long id = Readbuffer.getlong ();
if (ID!= integer_minus_one)
{
Idsreadfromfile.add (ID);
}
}
}
catch (IOException E)
{
throw New Underlyingstorageexception (
"Failed reading defragged ID batch", e);
}
}
3.3.1.2.2 Release ID (freeid)
After the user releases an ID, it is placed in Releasedidlist (linkedlist<long>) and is written to the end of the ID file when the number of IDs recycled in Releasedidlist exceeds grabsize. So, for a idgeneratorimpl, there is a maximum of 2 * grabsize ID caches (releasedidlist and Idsreadfromfile).
/**
* Frees the <CODE>id</CODE> making it a defragged ID that'll be
* Returned by next ID before no new ID (that hasn ' t been used yet) is
* Returned.
* <p>
* This method would throw a <CODE>IOException</CODE> if ID is negative or
* If ID is greater than the highest returned ID. However as stated in the
* Class documentation above the ID isn ' t validated to = if it really is
* Free.
*/
@Override
Public synchronized void Freeid (long id)
{
if (id = = Integer_minus_one)
{
Return
}
if (FileChannel = null)
{
throw new IllegalStateException ("generator closed" + fileName);
}
if (ID < 0 | | | ID >= highid.get ())
{
throw new IllegalArgumentException ("illegal id[" + ID + "]");
}
Releasedidlist.add (ID);
defraggedidcount++;
if (Releasedidlist.size () >= grabsize)
{
Writeidbatch (Bytebuffer.allocate (grabsize*8));
}
}
3.3.1.2.3 Request ID (NextID)
When a user requests an ID, IDGENERATORIMPL has 2 allocation policies when assigned: "Normal allocation policy" and "aggressive allocation policy" (aggressivereuse), which can be selected based on configuration.
n "Normal allocation policy":
(a) first distributed from the Idsreadfromfile; If Idsreadfromfile is empty, read the freed and reusable IDs to idsreadfromfile from the corresponding ID file.
b If there are no freed and reusable IDs in the Idsreadfromfile and ID files, assign a completely new ID, that is, id = highid.get () and add HighID to 1;
N "Radical Distribution Strategy" (Aggressivereuse):
A) is first allocated from the releasedidlist (the ID List just reclaimed).
b) The distribution of light is releasedidlist from the idsreadfromfile; If Idsreadfromfile is empty, read the freed and reusable IDs to idsreadfromfile from the corresponding ID file.
c If there are no freed and reusable IDs in the Idsreadfromfile and ID files, assign a completely new ID, that is, id = highid.get () and add HighID to 1;
/**
* Returns the next "free" ID. If a defragged ID exist it'll be returned
* Else the next free ID this hasn ' t been used yet is returned. If No ID
* Exist the capacity is exceeded (all values <= Max are taken) and a
* {@link Underlyingstorageexception} 'll be thrown.
*/
@Override
Public synchronized long NextID ()
{
Assertstillopen ();
Long Nextdefragid = Nextidfromdefraglist ();
if (Nextdefragid!=-1) return nextdefragid;
Long id = highid.get ();
if (id = = Integer_minus_one)
{
Skip the Integer-1 (0xFFFFFFFF) because it represents
Special values, f.ex. The end of a relationships/property chain.
id = highid.incrementandget ();
}
Assertidwithincapacity (ID);
Highid.incrementandget ();
return ID;
}
3.3.2 Dynamicstore Type
Storage format for 3.3.2.1 Abstractdynamicstore
In neo4j, the preservation strategy for variable length values of strings is saved by a set of fixed blocks, which are linked by one-way chain links. Class Abstractdynamicstore implements this feature, and the following is a description of its annotations.
/**
* An abstract representation of a dynamic store. The difference between a
* Normal Abstractstore and a abstractdynamicstore is
* The size of a record/entry can be dynamic.
* Instead of a fixed record is the class uses blocks to store a record. If A
* Record size is greater than the "block size" the record would use one or more
* Blocks to store its data.
* A dynamic store don ' t have a idgenerator because the position of a
* Record can ' t is calculated just by knowing the ID. Instead one should use a
* Abstractstore and store the "start Block" of the record located in the
* Dynamic Store. Note:this class makes use of a ID generator internally for
* Managing free and non free blocks.
* Note, the ' a dynamic store is reserved and contains information
* About the store.
*/
The Abstractdynamicstore class corresponds to the storage file format as shown in the image above, the entire file is a fixed-length array with a block_size=block_header_size (8Bytes) +block_content_size and a string "Stringpropertystore V0. A.2 "or" Arraypropertystore v0. A.2 "or" Schemastore v0. A.2 "(file type describes the all_stores_version composition of Type_descriptor and neo4j). When accessed, it can be accessed by using an ID as the subscript for the array. Among them, the first 4 bytes in the 1th record of the file are used to save the block_size. The 2nd record of the file begins to save the actual block data, which is composed of 8 bytes of Block_header and a fixed-length block_content (configurable). The Block_header structure is as follows:
InUse (1 byte): 1th Byte, divided into 3 parts
[X__,] 0:start record, 1:linked record
[X,] InUse
[, XXXX] high next block bits
The 1th to 4th bit indicates Next_block's 4-bit height.
The 5th bit indicates whether the block is in use;
The 8th bit indicates whether the block is a one-way linked list of the 1th block;0 represents the 1th block, 1 represents the subsequent block.
Nr_of_bytes (3Bytes): The length of the data saved in this block.
Next_block (4Bytes): Next_block is 4 bytes low, plus InUse's 1th to 4th bit, the actual length of the Next_block is a total of bit. A pointer to a one-way linked list stored as an array, pointing to the ID of the next block that holds the same data.
3.3.2.2 Abstractdynamicstore.java
Here's a look at the Getrecord () and readandverifyblocksize () member functions in Abstractdynamicstore.java to help you understand the Dynamicstore storage format.
Getrecord (Long blockid, Persistencewindow window, recordload load)
{
Dynamicrecord record = new Dynamicrecord (blockid);
Buffer buffer = Window.getoffsettedbuffer (blockid);
/*
* 4b
* [X,] [,] [,] [,] 0:start record, 1:linked record
* [X,] [,] [,] [,] InUse
* [, xxxx][,] [,] [,] high-next block bits
* [,][xxxx,xxxx][xxxx,xxxx][xxxx,xxxx] nr of bytes in the ' data field in the ' record
*
*/
Long Firstinteger = Buffer.getunsignedint ();
Boolean Isstartrecord = (Firstinteger & 0x80000000) = = 0;
Long Maskedinteger = Firstinteger & ~0x80000000;
int highnibbleinmaskedinteger = (int) ((Maskedinteger) >> 28);
Boolean InUse = Highnibbleinmaskedinteger = = Record.IN_USE.intValue ();
if (!inuse && load!= recordload.force)
{
throw new Invalidrecordexception ("Dynamicrecord not in use, blockid[" + Blockid + "]");
}
int datasize = Getblocksize ()-block_header_size;
int nrofbytes = (int) (Firstinteger & 0xFFFFFF);
/*
* Pointer to next blocks 4b (low bits of the pointer)
*/
Long Nextblock = Buffer.getunsignedint ();
Long Nextmodifier = (Firstinteger & 0xf000000l) << 8;
Long Longnextblock = Longfromintandmod (Nextblock, nextmodifier);
Boolean readdata = Load!= recordload.check;
if (Longnextblock!= Record.NO_NEXT_BLOCK.intValue ()
&& nrofbytes < DataSize | | Nrofbytes > DataSize)
{
ReadData = false;
if (load!= recordload.force)
{
throw new Invalidrecordexception ("Next block set[" + nextblock
+ "] Current block illegal size[" + nrofbytes + "/" + DataSize + "]";
}
}
Record.setinuse (INUSE);
Record.setstartrecord (Isstartrecord);
Record.setlength (nrofbytes);
Record.setnextblock (Longnextblock);
/*
* Data ' nrofbytes ' bytes
*/
if (readdata)
{
byte bytearrayelement[] = new Byte[nrofbytes];
Buffer.get (bytearrayelement);
Record.setdata (bytearrayelement);
}
return record;
}
Readandverifyblocksize ()
protected void Readandverifyblocksize () throws IOException
{
Bytebuffer buffer = bytebuffer.allocate (4);
Getfilechannel (). Position (0);
Getfilechannel (). read (buffer);
Buffer.flip ();
BlockSize = Buffer.getint ();
if (blockSize <= 0)
{
throw new Invalidrecordexception ("Illegal block size:" +
BlockSize + "in" + Getstoragefilename ());
}
}
3.3.2.3 class Dynamicarraystore, Dynamicstringstore
Class Schemastore,dynamicarraystore (Arraypropertystore), Dynamicstringstore (Stringpropertystore) are inherited from class Abstractdynamicstore, so the storage format of the corresponding files with class Dynamicarraystore, Dynamicstringstore, and Schemastore, Follow the Abstractdynamicstore storage format, except for the block size (block_size).
DB file Storage type Block_size
Neostore.labeltokenstore.db.names Stringpropertystore name_store_block_size=30
Neostore.propertystore.db.index.keys Stringpropertystore name_store_block_size=30
Neostore.relationshiptypestore.db.names Stringpropertystore name_store_block_size=30
Neostore.propertystore.db.strings Stringpropertystore string_block_size=120
Neostore.nodestore.db.labels Arraypropertystore label_block_size=60
Neostore.propertystore.db.arrays Arraypropertystore array_block_size=120
Neostore.schemastore.db Schemastore block_size=56
Block_size is set by a configuration file or by default, the following code fragment shows how the Neostore.propertystore.db.strings file was created and how the Block_size size was passed in.
1) Graphdatabasesettings.java
<div>public static final Setting string_block_size = Setting ("String_block_size", INTEGER, "", min (1));
public static final Setting array_block_size = Setting ("Array_block_size", INTEGER, "", min (1));
public static final Setting label_block_size = Setting ("Label_block_size", INTEGER, "a", min (1));</div>
<pre>
2) The configuration class of Storefactory.java
public static abstract class Configuration
{
public static final Setting string_block_size = graphdatabasesettings.string_block_size;
public static final Setting array_block_size = graphdatabasesettings.array_block_size;
public static final Setting label_block_size = graphdatabasesettings.label_block_size;
public static final Setting dense_node_threshold = Graphdatabasesettings.dense_node_threshold;
}
3) The Createpropertystore function of Storefactory.java
public void Createpropertystore (File fileName)
{
Createemptystore (FileName, Buildtypedescriptorandversion (Propertystore.type_descriptor));
int stringstoreblocksize = Config.get (configuration.string_block_size);
int arraystoreblocksize = Config.get (configuration.array_block_size)
Createdynamicstringstore (New File (Filename.getpath () + Strings_part), stringstoreblocksize, Idtype.string_block);
Createpropertykeytokenstore (New File (Filename.getpath () + Index_part));
Createdynamicarraystore (New File (Filename.getpath () + Arrays_part), arraystoreblocksize);
}
4) The Createdynamicstringstore function of Storefactory.java
private void Createdynamicstringstore (File fileName, int blockSize, Idtype idtype)
{
Createemptydynamicstore (FileName, BlockSize, Dynamicstringstore.version, Idtype);
}
5) The Createemptydynamicstore function of Storefactory.java
/**
* Creates a new empty store. A Factory method returning an implementation
* Should make use of the to initialize an empty store. Block size
* Must be greater than zero. Not that the the ' the ', ' would be marked as
* Reserved (contains info about the block size). There'll be a overhead
* For each block of <code>abstractdynamicstore.block_header_size</code>bytes.
*/
public void Createemptydynamicstore (File fileName, int baseblocksize,
String Typeandversiondescriptor, Idtype idtype)
{
int blockSize = baseblocksize;
Sanity Checks
...
BlockSize + = Abstractdynamicstore.block_header_size;
Write the header
Try
{
FileChannel channel = Filesystemabstraction.create (FileName);
int endheadersize = BlockSize
+ Utf8.encode (typeandversiondescriptor). length;
Bytebuffer buffer = bytebuffer.allocate (endheadersize);
Buffer.putint (blockSize);
Buffer.position (Endheadersize-typeandversiondescriptor.length ());
Buffer.put (Utf8.encode (Typeandversiondescriptor)). Flip ();
Channel.write (buffer);
Channel.force (FALSE);
Channel.close ();
}
catch (IOException E)
{
throw new Underlyingstorageexception ("Unable to create store"
+ FileName, E);
}
Idgeneratorfactory.create (Filesystemabstraction, New File (Filename.getpath () + ". Id"), 0);
TODO highestidinuse = 0 works now, but not when slave can create store files.
Idgenerator idgenerator = Idgeneratorfactory.open (Filesystemabstraction,
New File (Filename.getpath () + ". Id"), idtype.getgrabsize (), Idtype, 0);
Idgenerator.nextid (); Reserve A for BlockSize
Idgenerator.close ();
}