All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.scudata.vdb.HeaderBlock Maven / Gradle / Ivy

Go to download

SPL(Structured Process Language) A programming language specially for structured data computing.

There is a newer version: 20240823
Show newest version
package com.scudata.vdb;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import com.scudata.dm.ObjectReader;
import com.scudata.dm.ObjectWriter;
import com.scudata.util.HashUtil;

/**
 * ?׿?
 * @author RunQian
 *
 */
class HeaderBlock {	
	private int []otherBlocks; // ????һ????ռ?õ??????????飬????Ϊnull
	private byte sign; // ????λ
	private long commitTime; // ?ύʱ??
	
	private ArrayList fileZones; // ?ļ???λ?б?
	private ArrayList subDirs;
	
	public HeaderBlock() {
	}
	
	public void read(byte []bytes, Section section) throws IOException {
		ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
		ObjectReader reader = new ObjectReader(bis);
		
		int count = reader.readInt32();
		if (count > 0) {
			otherBlocks = new int[count];
			for (int i = 0; i < count; ++i) {
				otherBlocks[i] = reader.readInt32();
			}
		}
		
		sign = reader.readByte();
		commitTime = reader.readLong64();

		count = reader.readInt();
		if (count > 0) {
			fileZones = new ArrayList(count);
			for (int i = 0; i < count; ++i) {
				Zone zone = new Zone();
				zone.read(reader);
				fileZones.add(zone);
			}
		}
		
		count = reader.readInt();
		if (count > 0) {
			subDirs = new ArrayList(count);
			for (int i = 0; i < count; ++i) {
				Dir dir = new Dir(section);
				dir.read(reader);
				subDirs.add(dir);
			}
		}
		
		reader.close();
	}
	
	private byte[] toBytes() throws IOException {
		ByteArrayOutputStream bos = new ByteArrayOutputStream(Library.BLOCKSIZE);
		ObjectWriter writer = new ObjectWriter(bos);
		writer.writeByte(sign);
		writer.writeLong64(commitTime);
		
		ArrayList fileZones = this.fileZones;
		int count = fileZones == null ? 0 : fileZones.size();
		if (count > 0) {
			Zone lastZone = fileZones.get(count - 1);
			writer.writeInt(1);
			lastZone.write(writer);
		} else {
			writer.writeInt(0);
		}
		
		
		ArrayList subDirs = this.subDirs;
		count = subDirs == null ? 0 : subDirs.size();
		writer.writeInt(count);
		
		if (count > 0) {
			for (Dir dir : subDirs) {
				dir.write(writer);
			}
		}
		
		writer.close();
		return bos.toByteArray();
	}
	
	// ת???ֽ????飬?????ύ???ļ?
	public void commit(Library library, int header, int outerSeq, long innerSeq) throws IOException {
		ByteArrayOutputStream bos = new ByteArrayOutputStream(Library.BLOCKSIZE);
		ObjectWriter writer = new ObjectWriter(bos);
		
		commitTime = System.currentTimeMillis();
		writer.writeByte(sign);
		writer.writeLong64(commitTime);
		
		ArrayList fileZones = this.fileZones;
		int count = fileZones == null ? 0 : fileZones.size();
		writer.writeInt(count);
		
		if (count > 0) {
			Zone lastZone = fileZones.get(count - 1);
			if (!lastZone.isCommitted()) {
				synchronized(this) {
					lastZone.setTxSeq(outerSeq, innerSeq);
				}
			}
			
			for (Zone zone : fileZones) {
				zone.write(writer);
			}
		}
		
		ArrayList subDirs = this.subDirs;
		count = subDirs == null ? 0 : subDirs.size();
		writer.writeInt(count);
		
		if (count > 0) {
			for (Dir dir : subDirs) {
				dir.write(writer, library, outerSeq, innerSeq);
			}
		}
		
		writer.close();
		byte []bytes = bos.toByteArray();
		otherBlocks = library.writeHeaderBlock(header, otherBlocks, bytes);
	}
	
	// ȡ??Ŀ¼
	public synchronized Dir getSubDir(Object path) {
		if (subDirs == null) return null;
		
		for (Dir dir : subDirs) {
			if (dir.isEqualValue(path)) return dir;
		}
		
		return null;
	}
	
	// ȡ???е???Ŀ¼
	public synchronized Dir[] getSubDirs() {
		if (subDirs == null || subDirs.size() == 0) {
			return null;
		}
		
		Dir []dirs = new Dir[subDirs.size()];
		subDirs.toArray(dirs);
		return dirs;
	}
	
	public ArrayList getSubList(Library library) {
		if (subDirs == null || subDirs.size() == 0) {
			return null;
		}
		
		int size = subDirs.size();
		ArrayList list = new ArrayList(size);
		for (Dir dir : subDirs) {
			DirZone zone = dir.getLastZone();
			if (zone.valid()) {
				list.add(zone.getSection(library, dir));
			}
		}
		
		return list;
	}

	public synchronized Dir createSubDir(Object path, String name, Section section) {
		if (subDirs == null) {
			subDirs = new ArrayList();
		} else {
			// ???ܴ????????·????????ɾ????????????
			for (Dir dir : subDirs) {
				if (dir.isEqualValue(path)) {
					dir.addZone(Dir.S_NORMAL);
					return dir;
				}
			}
		}
		
		Dir dir = new Dir(path, name, section);
		subDirs.add(dir);
		return dir;
	}
	
	public synchronized void createFileZone(Library library, int block) {
		if (fileZones == null) {
			fileZones = new ArrayList();
		} else {
			// ????Ѿ???һ????û?ύ????λ?򸲸?
			int size = fileZones.size();
			if (size > 0) {
				Zone zone = fileZones.get(size - 1);
				if (!zone.isCommitted()) {
					library.recycleData(zone.getBlock());
					zone.setBlock(block);
					return;
				}
			}
		}
		
		fileZones.add(new Zone(block));
	}
	
	// ȡ??Ӧ???ļ???λ
	public synchronized Zone getFileZone(VDB vdb, boolean isLockVDB) {
		ArrayList fileZones = this.fileZones;
		if (fileZones == null) return null;
		
		for (int i = fileZones.size() - 1; i >= 0; --i) {
			Zone zone = fileZones.get(i);
			if (zone.match(vdb, isLockVDB)) {
				return zone;
			}
		}
		
		return null;
	}

	public synchronized void roolBack(Library library) {
		if (fileZones != null && fileZones.size() > 0) {
			int last = fileZones.size() - 1;
			Zone zone = fileZones.get(last);
			
			if (!zone.isCommitted()) {
				int block = zone.getBlock();
				library.recycleData(block);
				if (last == 0) {
					fileZones = null;
				} else {
					fileZones.remove(last);
				}
			}
		}
		
		ArrayList subDirs = this.subDirs;
		if (subDirs != null) {
			for (int i = subDirs.size() - 1; i >= 0; --i) {
				Dir dir = subDirs.get(i);
				if (dir.roolBack() == 0) {
					subDirs.remove(i);
				}
			}
			
			if (subDirs.size() == 0) subDirs = null;
		}
	}
	
	// ɾ?????????txSeq??Ķ??????λ
	synchronized public void deleteOutdatedZone(Library library, int outerSeq, long txSeq) {
		// ???ٱ???һ?????ύ????λ??
		ArrayList fileZones = this.fileZones;
		if (fileZones != null && fileZones.size() > 1) {
			int last = fileZones.size() - 1;
			if (fileZones.get(last).isCommitted()) {
				last--;
			} else {
				last -= 2;
			}
			
			for (; last >= 0; --last) {
				Zone zone = fileZones.get(last);
				if (zone.canDelete(outerSeq, txSeq)) {
					for (; last >= 0; --last) {
						fileZones.remove(last);
					}
					
					break;
				}
			}
		}
		
		ArrayList subDirs = this.subDirs;
		if (subDirs != null) {
			for (Dir dir : subDirs) {
				dir.deleteOutdatedZone(library, outerSeq, txSeq);
			}
		}
	}
	
	// ???????ݿ???׼????????ɾ??????λ??ȡ??ռ?õ???????
	public void scanUsedBlocks(Library library, BlockManager manager) throws IOException {
		if (otherBlocks != null) {
			manager.setBlocksUsed(otherBlocks);
		}
		
		ArrayList fileZones = this.fileZones;
		if (fileZones != null) {
			if (manager.getStopSign()) {
				return;
			}
			
			int size = fileZones.size();
			Zone zone;
			
			if (size > 1) {
				zone = fileZones.get(size - 1);
				fileZones.clear();
				fileZones.add(zone);
			} else {
				zone = fileZones.get(0);
			}

			int block = zone.getBlock();
			manager.setBlockUsed(block);
			
			int []otherBlocks = library.readOtherBlocks(block);
			if (otherBlocks != null) {
				manager.setBlocksUsed(otherBlocks);
			}
		}
		
		ArrayList subDirs = this.subDirs;
		if (subDirs != null) {
			for (int i = subDirs.size() - 1; i >= 0; --i) {
				if (manager.getStopSign()) {
					return;
				}
				
				Dir dir = subDirs.get(i);
				dir.scanUsedBlocks(library, manager);
				//if (!dir.scanUsedBlocks(library, manager)) {
					//subDirs.remove(i);
				//}
			}
		}
	}
	
	public synchronized boolean isFile() {
		return fileZones != null;
	}
	
	public synchronized boolean isDir() {
		return subDirs != null;
	}
	
	// ???ؽڵ??Ƿ??ǿսڵ㣬û?е??ݺ???Ŀ¼
	public synchronized boolean isNullSection() {
		if (fileZones != null && fileZones.size() > 0) {
			return false;
		}
		
		if (subDirs == null) {
			return true;
		}
		
		for (Dir dir : subDirs) {
			DirZone lastZone = dir.getLastZone();
			if (lastZone != null && lastZone.valid()) {
				return false;
			}
		}
		
		return true;
	}
	
	public void removeSubDir(Dir dir) {
		subDirs.remove(dir);
	}
	
	public void deleteSubDir(Dir dir) {
		dir.addZone(Dir.S_DELETE);
	}
	
	public void moveSubDir(Dir dir, ISection section) {
		// û????????????ܻ?????ʵ??˽ڣ????????յ?ʱ???ж??Ƿ?move????move?IJ?????
		//dir.getLastZone().releaseSection();
		dir.addZone(Dir.S_MOVE);
	}
	
	public void deleteAllSubDirs() {
		if (subDirs != null) {
			for (Dir dir : subDirs) {
				dir.addZone(Dir.S_DELETE);
			}
		}
	}
	
	public long getCommitTime() {
		return commitTime;
	}
	
	public boolean isKeySection() {
		return (sign & ISection.SIGN_KEY_SECTION) != 0;
	}

	// ȡ????ij??·????hashֵ??ӦDir
	public Dir getSubKeyDir(Object path) {
		int len = subDirs.size();
		int hash = HashUtil.hashCode(path, len);
		return subDirs.get(hash);
	}
		
	public void setKeySection(VDB vdb, Section section, int len) {
		sign |= ISection.SIGN_KEY_SECTION;
		ArrayList subDirs = new ArrayList(len);
		this.subDirs = subDirs;
		
		for (int i = 0; i < len; ++i) {
			Dir dir = new Dir(i, null, section);
			subDirs.add(dir);
		}
	}
	
	public void releaseSubSection() {
		if (subDirs != null) {
			for (Dir dir : subDirs) {
				dir.releaseSubSection();
			}
		}
	}
	
	public Zone getFileZone() {
		if (fileZones != null && fileZones.size() > 0) {
			return fileZones.get(fileZones.size() - 1);
		}
		
		return null;
	}
		
	public void reset(Library srcLib, Library destLib, int destHeader) throws IOException {
		HeaderBlock dest = new HeaderBlock();
		dest.sign = sign;
		dest.commitTime = commitTime;
		
		int outerSeq = destLib.getOuterTxSeq();
		long innerSeq = destLib.getNextInnerTxSeq();
		
		Zone zone = getFileZone();
		if (zone != null) {
			Object data = zone.getData(srcLib);
			int block = destLib.writeDataBlock(destHeader, data);
			Zone destZone = new Zone(block);
			destZone.setTxSeq(outerSeq, innerSeq);
			dest.fileZones = new ArrayList(1);
			dest.fileZones.add(destZone);
		}
		
		ArrayList srcSubDirs = subDirs;
		ArrayList destSubDirs = null;
		if (srcSubDirs != null) {
			int subCount = srcSubDirs.size();
			destSubDirs = new ArrayList(subCount);
			for (Dir srcDir : srcSubDirs) {
				DirZone srcDirZone = srcDir.getLastZone();
				if (srcDirZone != null && srcDirZone.valid()) {
					Dir destDir = new Dir(srcDir.getValue(), srcDir.getName(), null);
					destSubDirs.add(destDir);
					DirZone destDirZone = destDir.getLastZone();
					destDirZone.setBlock(destLib.applyHeaderBlock());
					destDirZone.setTxSeq(outerSeq, innerSeq);
				}
			}
		}
		
		int subDirCount = destSubDirs != null ? destSubDirs.size() : 0;
		if (subDirCount > 0) {
			dest.subDirs = destSubDirs;
		}
		
		byte []bytes = dest.toBytes();
		destLib.writeHeaderBlock(destHeader, null, bytes);
		
		if (subDirCount > 0) {
			int q = 0;
			for (Dir srcDir : srcSubDirs) {
				DirZone srcDirZone = srcDir.getLastZone();
				if (srcDirZone != null && srcDirZone.valid()) {
					ISection srcSection = srcDirZone.getSection(srcLib, srcDir);
					Dir destDir = destSubDirs.get(q++);
					int destSubHeader = destDir.getLastZone().getBlock();
					srcSection.reset(srcLib, destLib, destSubHeader);
					srcDirZone.releaseSection();
				}
			}
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy