public static int unpackString(byte[] arr, int offs, out string str, Encoding encoding) { int len = Bytes.unpack4(arr, offs); offs += 4; str = null; if (len >= 0) { char[] chars = new char[len]; for (int i = 0; i < len; i++) { chars[i] = (char)Bytes.unpack2(arr, offs); offs += 2; } str = new string(chars); } else if (len < -1) { if (encoding != null) { str = encoding.GetString(arr, offs, -2 - len); } else { str = Encoding.Default.GetString(arr, offs, -2 - len); } offs -= 2 + len; } return(offs); }
protected ReplicationSlaveStorageImpl(String pageTimestampFilePath) { if (pageTimestampFilePath != null) { pageTimestampFile = new OSFile(pageTimestampFilePath, fileParameters); long fileLength = pageTimestampFile.Length; if (fileLength == 0) { pageTimestamps = new int[INIT_PAGE_TIMESTAMPS_LENGTH]; } else { pageTimestamps = new int[(int)(fileLength / 4)]; byte[] page = new byte[Page.pageSize]; int i = 0; for (long pos = 0; pos < fileLength; pos += Page.pageSize) { int rc = pageTimestampFile.Read(pos, page); for (int offs = 0; offs < rc; offs += 4) { pageTimestamps[i++] = Bytes.unpack4(page, offs); } } if (i != pageTimestamps.Length) { throw new StorageError(StorageError.ErrorCode.FILE_ACCESS_ERROR); } } dirtyPageTimestampMap = new int[(((pageTimestamps.Length * 4 + Page.pageSize - 1) >> Page.pageSizeLog) + 31) >> 5]; } }
internal void exportMultiFieldIndex(int oid, byte[] data) { Btree btree = new Btree(data, ObjectHeader.Sizeof); storage.assignOid(btree, oid); writer.Write(" <Perst.Impl.BtreeMultiFieldIndex id=\"" + oid + "\" unique=\"" + (btree.unique ? '1' : '0') + "\" class="); int offs = exportString(data, Btree.Sizeof); int nFields = Bytes.unpack4(data, offs); offs += 4; for (int i = 0; i < nFields; i++) { writer.Write(" field" + i + "="); offs = exportString(data, offs); } writer.Write(">\n"); int nTypes = Bytes.unpack4(data, offs); offs += 4; compoundKeyTypes = new ClassDescriptor.FieldType[nTypes]; for (int i = 0; i < nTypes; i++) { compoundKeyTypes[i] = (ClassDescriptor.FieldType)Bytes.unpack4(data, offs); offs += 4; } btree.export(this); compoundKeyTypes = null; writer.Write(" </Perst.Impl.BtreeMultiFieldIndex>\n"); }
public static decimal unpackDecimal(byte[] arr, int offs) { int[] bits = new int[4]; bits[0] = Bytes.unpack4(arr, offs); bits[1] = Bytes.unpack4(arr, offs + 4); bits[2] = Bytes.unpack4(arr, offs + 8); bits[3] = Bytes.unpack4(arr, offs + 12); return(new decimal(bits)); }
public static int skipString(byte[] arr, int offs) { int len = Bytes.unpack4(arr, offs); offs += 4; if (len >= 0) { offs += len * 2; } else if (len < -1) { offs -= len + 2; } return(offs); }
void exportCompoundKey(byte[] body, int offs, int size, ClassDescriptor.FieldType type) { Debug.Assert(type == ClassDescriptor.FieldType.tpArrayOfByte); int end = offs + size; for (int i = 0; i < compoundKeyTypes.Length; i++) { type = compoundKeyTypes[i]; if (type == ClassDescriptor.FieldType.tpArrayOfByte || type == ClassDescriptor.FieldType.tpString) { size = Bytes.unpack4(body, offs); offs += 4; } writer.Write(" key" + i + "=\""); offs = exportKey(body, offs, size, type); writer.Write("\""); } Debug.Assert(offs == end); }
internal int exportBinary(byte[] body, int offs) { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { if (len == -2 - (int)ClassDescriptor.FieldType.tpObject) { exportRef(Bytes.unpack4(body, offs)); offs += 4; } else if (len < -1) { writer.Write("\"#"); writer.Write(hexDigit[-2 - len]); len = ClassDescriptor.Sizeof[-2 - len]; while (--len >= 0) { byte b = body[offs++]; writer.Write(hexDigit[(b >> 4) & 0xF]); writer.Write(hexDigit[b & 0xF]); } writer.Write('\"'); } else { writer.Write("null"); } } else { writer.Write('\"'); while (--len >= 0) { byte b = body[offs++]; writer.Write(hexDigit[(b >> 4) & 0xF]); writer.Write(hexDigit[b & 0xF]); } writer.Write('\"'); } return(offs); }
internal int exportString(byte[] body, int offs) { int len = Bytes.unpack4(body, offs); offs += 4; if (len >= 0) { writer.Write("\""); while (--len >= 0) { exportChar((char)Bytes.unpack2(body, offs)); offs += 2; } writer.Write("\""); } else if (len < -1) { writer.Write("\""); string s; if (storage.encoding != null) { s = storage.encoding.GetString(body, offs, -len - 2); } else { s = Encoding.Default.GetString(body, offs, -len - 2); } offs -= len + 2; for (int i = 0, n = s.Length; i < n; i++) { exportChar(s[i]); } } else { writer.Write("null"); } return(offs); }
public override int compareByteArrays(byte[] key, byte[] item, int offs, int lengtn) { int o1 = 0; int o2 = offs; byte[] a1 = key; byte[] a2 = item; for (int i = 0; i < types.Length && o1 < key.Length; i++) { int diff = 0; switch (types[i]) { case ClassDescriptor.FieldType.tpBoolean: case ClassDescriptor.FieldType.tpByte: diff = a1[o1++] - a2[o2++]; break; case ClassDescriptor.FieldType.tpSByte: diff = (sbyte)a1[o1++] - (sbyte)a2[o2++]; break; case ClassDescriptor.FieldType.tpShort: diff = Bytes.unpack2(a1, o1) - Bytes.unpack2(a2, o2); o1 += 2; o2 += 2; break; case ClassDescriptor.FieldType.tpUShort: diff = (ushort)Bytes.unpack2(a1, o1) - (ushort)Bytes.unpack2(a2, o2); o1 += 2; o2 += 2; break; case ClassDescriptor.FieldType.tpChar: diff = (char)Bytes.unpack2(a1, o1) - (char)Bytes.unpack2(a2, o2); o1 += 2; o2 += 2; break; case ClassDescriptor.FieldType.tpInt: { int i1 = Bytes.unpack4(a1, o1); int i2 = Bytes.unpack4(a2, o2); diff = i1 < i2 ? -1 : i1 == i2 ? 0 : 1; o1 += 4; o2 += 4; break; } case ClassDescriptor.FieldType.tpUInt: case ClassDescriptor.FieldType.tpEnum: case ClassDescriptor.FieldType.tpObject: case ClassDescriptor.FieldType.tpOid: { uint u1 = (uint)Bytes.unpack4(a1, o1); uint u2 = (uint)Bytes.unpack4(a2, o2); diff = u1 < u2 ? -1 : u1 == u2 ? 0 : 1; o1 += 4; o2 += 4; break; } case ClassDescriptor.FieldType.tpLong: { long l1 = Bytes.unpack8(a1, o1); long l2 = Bytes.unpack8(a2, o2); diff = l1 < l2 ? -1 : l1 == l2 ? 0 : 1; o1 += 8; o2 += 8; break; } case ClassDescriptor.FieldType.tpULong: case ClassDescriptor.FieldType.tpDate: { ulong l1 = (ulong)Bytes.unpack8(a1, o1); ulong l2 = (ulong)Bytes.unpack8(a2, o2); diff = l1 < l2 ? -1 : l1 == l2 ? 0 : 1; o1 += 8; o2 += 8; break; } case ClassDescriptor.FieldType.tpFloat: { float f1 = Bytes.unpackF4(a1, o1); float f2 = Bytes.unpackF4(a2, o2); diff = f1 < f2 ? -1 : f1 == f2 ? 0 : 1; o1 += 4; o2 += 4; break; } case ClassDescriptor.FieldType.tpDouble: { double d1 = Bytes.unpackF8(a1, o1); double d2 = Bytes.unpackF8(a2, o2); diff = d1 < d2 ? -1 : d1 == d2 ? 0 : 1; o1 += 8; o2 += 8; break; } case ClassDescriptor.FieldType.tpDecimal: { decimal d1 = Bytes.unpackDecimal(a1, o1); decimal d2 = Bytes.unpackDecimal(a2, o2); diff = d1.CompareTo(d2); o1 += 16; o2 += 16; break; } case ClassDescriptor.FieldType.tpGuid: { Guid g1 = Bytes.unpackGuid(a1, o1); Guid g2 = Bytes.unpackGuid(a2, o2); diff = g1.CompareTo(g2); o1 += 16; o2 += 16; break; } case ClassDescriptor.FieldType.tpString: { int len1 = Bytes.unpack4(a1, o1); int len2 = Bytes.unpack4(a2, o2); o1 += 4; o2 += 4; int len = len1 < len2 ? len1 : len2; while (--len >= 0) { diff = (char)Bytes.unpack2(a1, o1) - (char)Bytes.unpack2(a2, o2); if (diff != 0) { return(diff); } o1 += 2; o2 += 2; } diff = len1 - len2; break; } case ClassDescriptor.FieldType.tpArrayOfByte: { int len1 = Bytes.unpack4(a1, o1); int len2 = Bytes.unpack4(a2, o2); o1 += 4; o2 += 4; int len = len1 < len2 ? len1 : len2; while (--len >= 0) { diff = a1[o1++] - a2[o2++]; if (diff != 0) { return(diff); } } diff = len1 - len2; break; } default: Debug.Assert(false, "Invalid type"); break; } if (diff != 0) { return(diff); } } return(0); }
protected override object unpackByteArrayKey(Page pg, int pos) { int offs = BtreePage.firstKeyOffs + BtreePage.getKeyStrOffs(pg, pos); byte[] data = pg.data; Object[] values = new Object[types.Length]; for (int i = 0; i < types.Length; i++) { Object v = null; switch (types[i]) { case ClassDescriptor.FieldType.tpBoolean: v = data[offs++] != 0; break; case ClassDescriptor.FieldType.tpSByte: v = (sbyte)data[offs++]; break; case ClassDescriptor.FieldType.tpByte: v = data[offs++]; break; case ClassDescriptor.FieldType.tpShort: v = Bytes.unpack2(data, offs); offs += 2; break; case ClassDescriptor.FieldType.tpUShort: v = (ushort)Bytes.unpack2(data, offs); offs += 2; break; case ClassDescriptor.FieldType.tpChar: v = (char)Bytes.unpack2(data, offs); offs += 2; break; case ClassDescriptor.FieldType.tpInt: v = Bytes.unpack4(data, offs); offs += 4; break; case ClassDescriptor.FieldType.tpUInt: v = (uint)Bytes.unpack4(data, offs); offs += 4; break; case ClassDescriptor.FieldType.tpOid: case ClassDescriptor.FieldType.tpObject: { int oid = Bytes.unpack4(data, offs); v = oid == 0 ? null : ((StorageImpl)Storage).lookupObject(oid, null); offs += 4; break; } case ClassDescriptor.FieldType.tpLong: v = Bytes.unpack8(data, offs); offs += 8; break; case ClassDescriptor.FieldType.tpDate: { v = new DateTime(Bytes.unpack8(data, offs)); offs += 8; break; } case ClassDescriptor.FieldType.tpULong: v = (ulong)Bytes.unpack8(data, offs); offs += 8; break; case ClassDescriptor.FieldType.tpFloat: v = Bytes.unpackF4(data, offs); offs += 4; break; case ClassDescriptor.FieldType.tpDouble: v = Bytes.unpackF8(data, offs); offs += 8; break; case ClassDescriptor.FieldType.tpDecimal: v = Bytes.unpackDecimal(data, offs); offs += 16; break; case ClassDescriptor.FieldType.tpGuid: v = Bytes.unpackGuid(data, offs); offs += 16; break; case ClassDescriptor.FieldType.tpString: { int len = Bytes.unpack4(data, offs); offs += 4; char[] sval = new char[len]; for (int j = 0; j < len; j++) { sval[j] = (char)Bytes.unpack2(pg.data, offs); offs += 2; } v = new String(sval); break; } case ClassDescriptor.FieldType.tpArrayOfByte: { int len = Bytes.unpack4(data, offs); offs += 4; byte[] val = new byte[len]; Array.Copy(pg.data, offs, val, 0, len); offs += len; v = val; break; } default: Debug.Assert(false, "Invalid type"); break; } values[i] = v; } return(values); }
internal static int getItem(Page pg, int index) { return(Bytes.unpack4(pg.data, firstKeyOffs + index * 4)); }
internal static int getSize(byte[] arr, int offs) { return(Bytes.unpack4(arr, offs)); }
internal void extract(Page pg, int offs, ClassDescriptor.FieldType type) { byte[] data = pg.data; switch (type) { case ClassDescriptor.FieldType.tpBoolean: key = new Key(data[offs] != 0); break; case ClassDescriptor.FieldType.tpSByte: key = new Key((sbyte)data[offs]); break; case ClassDescriptor.FieldType.tpByte: key = new Key(data[offs]); break; case ClassDescriptor.FieldType.tpShort: key = new Key(Bytes.unpack2(data, offs)); break; case ClassDescriptor.FieldType.tpUShort: key = new Key((ushort)Bytes.unpack2(data, offs)); break; case ClassDescriptor.FieldType.tpChar: key = new Key((char)Bytes.unpack2(data, offs)); break; case ClassDescriptor.FieldType.tpInt: key = new Key(Bytes.unpack4(data, offs)); break; case ClassDescriptor.FieldType.tpEnum: case ClassDescriptor.FieldType.tpUInt: case ClassDescriptor.FieldType.tpObject: case ClassDescriptor.FieldType.tpOid: key = new Key((uint)Bytes.unpack4(data, offs)); break; case ClassDescriptor.FieldType.tpLong: key = new Key(Bytes.unpack8(data, offs)); break; case ClassDescriptor.FieldType.tpDate: case ClassDescriptor.FieldType.tpULong: key = new Key((ulong)Bytes.unpack8(data, offs)); break; case ClassDescriptor.FieldType.tpFloat: key = new Key(Bytes.unpackF4(data, offs)); break; case ClassDescriptor.FieldType.tpDouble: key = new Key(Bytes.unpackF8(data, offs)); break; case ClassDescriptor.FieldType.tpGuid: key = new Key(Bytes.unpackGuid(data, offs)); break; case ClassDescriptor.FieldType.tpDecimal: key = new Key(Bytes.unpackDecimal(data, offs)); break; default: Debug.Assert(false, "Invalid type"); break; } }
public void run() { try { byte[] buf = new byte[Page.pageSize + PAGE_DATA_OFFSET + (pageTimestamps != null ? 4 : 0)]; while (listening) { int offs = 0; do { int rc = -1; try { if (socket != null) { ArrayList recvSocks = new ArrayList(1); recvSocks.Add(socket); Socket.Select(recvSocks, null, null, replicationReceiveTimeout * 2000); if (recvSocks.Count == 1) { rc = socket.Receive(buf, offs, buf.Length - offs, SocketFlags.None); } else { Console.WriteLine("Receive timeout expired"); } } } catch (SocketException x) { Console.WriteLine("Failed to receive data from master: " + x); rc = -1; } lock (done) { if (!listening) { return; } } if (rc < 0) { HandleError(); hangup(); return; } else { offs += rc; } } while (offs < buf.Length); long pos = Bytes.unpack8(buf, 0); bool transactionCommit = false; if (pos == 0) { if (replicationAck) { try { socket.Send(buf, 0, 1, SocketFlags.None); } catch (SocketException x) { Console.WriteLine("Failed to send request to master: " + x); HandleError(); hangup(); return; } } if (buf[PAGE_DATA_OFFSET + DB_HDR_CURR_INDEX_OFFSET] != prevIndex) { prevIndex = buf[PAGE_DATA_OFFSET + DB_HDR_CURR_INDEX_OFFSET]; lck.ExclusiveLock(); transactionCommit = true; } } else if (pos == REPL_SYNC) { lock (sync) { outOfSync = false; Monitor.Pulse(sync); } continue; } else if (pos == REPL_PING) { continue; } else if (pos == REPL_CLOSE) { hangup(); return; } if (pageTimestamps != null) { int pageNo = (int)(pos >> Page.pageSizeLog); if (pageNo >= pageTimestamps.Length) { int newLength = pageNo >= pageTimestamps.Length * 2 ? pageNo + 1 : pageTimestamps.Length * 2; int[] newPageTimestamps = new int[newLength]; Array.Copy(pageTimestamps, 0, newPageTimestamps, 0, pageTimestamps.Length); pageTimestamps = newPageTimestamps; int[] newDirtyPageTimestampMap = new int[(((newLength * 4 + Page.pageSize - 1) >> Page.pageSizeLog) + 31) >> 5]; Array.Copy(dirtyPageTimestampMap, 0, newDirtyPageTimestampMap, 0, dirtyPageTimestampMap.Length); dirtyPageTimestampMap = newDirtyPageTimestampMap; } int timestamp = Bytes.unpack4(buf, Page.pageSize + PAGE_DATA_OFFSET); pageTimestamps[pageNo] = timestamp; dirtyPageTimestampMap[pageNo >> (Page.pageSizeLog - 2 + 5)] |= 1 << ((pageNo >> (Page.pageSizeLog - 2)) & 31); } Page pg = pool.putPage(pos); Array.Copy(buf, PAGE_DATA_OFFSET, pg.data, 0, Page.pageSize); pool.unfix(pg); if (pos == 0) { if (!initialized && buf[PAGE_DATA_OFFSET + DB_HDR_INITIALIZED_OFFSET] != 0) { lock (init) { initialized = true; Monitor.Pulse(init); } } if (transactionCommit) { lck.Unlock(); lock (commit) { Monitor.PulseAll(commit); } if (listener != null) { listener.OnMasterDatabaseUpdate(); } pool.flush(); if (pageTimestamps != null) { byte[] page = new byte[Page.pageSize]; for (int i = 0; i < dirtyPageTimestampMap.Length; i++) { if (dirtyPageTimestampMap[i] != 0) { for (int j = 0; j < 32; j++) { if ((dirtyPageTimestampMap[i] & (1 << j)) != 0) { int pageNo = (i << 5) + j; int beg = pageNo << (Page.pageSizeLog - 2); int end = beg + Page.pageSize / 4; if (end > pageTimestamps.Length) { end = pageTimestamps.Length; } offs = 0; while (beg < end) { Bytes.pack4(page, offs, pageTimestamps[beg]); beg += 1; offs += 4; } pageTimestampFile.Write(pageNo << Page.pageSizeLog, page); } } } dirtyPageTimestampMap[i] = 0; } pageTimestampFile.Sync(); } } } } } finally { listening = false; lock (init) { Monitor.Pulse(init); } lock (sync) { Monitor.Pulse(sync); } } }
int exportKey(byte[] body, int offs, int size, ClassDescriptor.FieldType type) { switch (type) { case ClassDescriptor.FieldType.tpBoolean: writer.Write(body[offs++] != 0?"1":"0"); break; case ClassDescriptor.FieldType.tpByte: writer.Write(System.Convert.ToString((byte)body[offs++])); break; case ClassDescriptor.FieldType.tpSByte: writer.Write(System.Convert.ToString((sbyte)body[offs++])); break; case ClassDescriptor.FieldType.tpChar: writer.Write(System.Convert.ToString((ushort)Bytes.unpack2(body, offs))); offs += 2; break; case ClassDescriptor.FieldType.tpShort: writer.Write(System.Convert.ToString((ushort)Bytes.unpack2(body, offs))); offs += 2; break; case ClassDescriptor.FieldType.tpUShort: writer.Write(System.Convert.ToString((ushort)Bytes.unpack2(body, offs))); offs += 2; break; case ClassDescriptor.FieldType.tpInt: writer.Write(System.Convert.ToString(Bytes.unpack4(body, offs))); offs += 4; break; case ClassDescriptor.FieldType.tpUInt: case ClassDescriptor.FieldType.tpObject: case ClassDescriptor.FieldType.tpEnum: writer.Write(System.Convert.ToString((uint)Bytes.unpack4(body, offs))); offs += 4; break; case ClassDescriptor.FieldType.tpLong: writer.Write(System.Convert.ToString(Bytes.unpack8(body, offs))); offs += 8; break; case ClassDescriptor.FieldType.tpULong: writer.Write(System.Convert.ToString((ulong)Bytes.unpack8(body, offs))); offs += 8; break; case ClassDescriptor.FieldType.tpFloat: writer.Write(System.Convert.ToString(Bytes.unpackF4(body, offs))); offs += 4; break; case ClassDescriptor.FieldType.tpDouble: writer.Write(System.Convert.ToString(Bytes.unpackF8(body, offs))); offs += 8; break; case ClassDescriptor.FieldType.tpGuid: writer.Write(Bytes.unpackGuid(body, offs).ToString()); offs += 16; break; case ClassDescriptor.FieldType.tpDecimal: writer.Write(Bytes.unpackDecimal(body, offs).ToString()); offs += 16; break; case ClassDescriptor.FieldType.tpString: for (int i = 0; i < size; i++) { exportChar((char)Bytes.unpack2(body, offs)); offs += 2; } break; case ClassDescriptor.FieldType.tpArrayOfByte: for (int i = 0; i < size; i++) { byte b = body[offs++]; writer.Write(hexDigit[(b >> 4) & 0xF]); writer.Write(hexDigit[b & 0xF]); } break; case ClassDescriptor.FieldType.tpDate: writer.Write(Bytes.unpackDate(body, offs).ToString()); offs += 8; break; default: Debug.Assert(false, "Invalid type"); break; } return(offs); }
private ReplicationMasterFile(ReplicationMasterStorageImpl storage, IFile file, string localhost, int port, string[] hosts, bool ack, String pageTimestampFilePath) { this.storage = storage; this.file = file; this.ack = ack; this.localhost = localhost; this.port = port; mutex = new object(); replicas = new Replica[hosts.Length]; rcBuf = new byte[1]; nHosts = 0; if (pageTimestampFilePath != null) { FileParameters fileParameters = storage != null ? storage.fileParameters : new FileParameters(false, false, false, 1024 * 1024); pageTimestampFile = new OSFile(pageTimestampFilePath, fileParameters); long fileLength = pageTimestampFile.Length; if (fileLength == 0) { pageTimestamps = new int[InitPageTimestampsLength]; } else { pageTimestamps = new int[(int)(fileLength / 4)]; byte[] page = new byte[Page.pageSize]; int i = 0; for (long pos = 0; pos < fileLength; pos += Page.pageSize) { int rc = pageTimestampFile.Read(pos, page); for (int offs = 0; offs < rc; offs += 4, i++) { pageTimestamps[i] = Bytes.unpack4(page, offs); if (pageTimestamps[i] > timestamp) { timestamp = pageTimestamps[i]; } } } if (i != pageTimestamps.Length) { throw new StorageError(StorageError.ErrorCode.FILE_ACCESS_ERROR); } } dirtyPageTimestampMap = new int[(((pageTimestamps.Length * 4 + Page.pageSize - 1) >> Page.pageSizeLog) + 31) >> 5]; txBuf = new byte[12 + Page.pageSize]; } else { txBuf = new byte[8 + Page.pageSize]; } for (int i = 0; i < hosts.Length; i++) { replicas[i] = new Replica(); replicas[i].host = hosts[i]; Connect(i); } if (port >= 0) { storage.SetProperty("perst.alternative.btree", true); // prevent direct modification of pages listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); listenSocket.Bind(new IPEndPoint(localhost != null && localhost != "localhost" ? IPAddress.Parse(localhost) : IPAddress.Any, port)); listenSocket.Listen(ListenQueueSize); listening = true; listenThread = new Thread(new ThreadStart(run)); listenThread.Start(); } watchdogThread = new Thread(new ThreadStart(watchdog)); watchdogThread.Start(); }
void synchronizeNewSlaveNode(int i) { long size = storage.DatabaseSize; int[] syncNodeTimestamps = null; byte[] txBuf; if (pageTimestamps != null) { txBuf = new byte[12 + Page.pageSize]; byte[] psBuf = new byte[4]; if (!Receive(i, psBuf)) { Console.WriteLine("Failed to receive page timestamps length from slave node " + replicas[i].host); return; } int psSize = Bytes.unpack4(psBuf, 0); psBuf = new byte[psSize * 4]; if (!Receive(i, psBuf)) { Console.WriteLine("Failed to receive page timestamps from slave node " + replicas[i].host); return; } syncNodeTimestamps = new int[psSize]; for (int j = 0; j < psSize; j++) { syncNodeTimestamps[j] = Bytes.unpack4(psBuf, j * 4); } } else { txBuf = new byte[8 + Page.pageSize]; } for (long pos = 0; pos < size; pos += Page.pageSize) { int pageNo = (int)(pos >> Page.pageSizeLog); if (syncNodeTimestamps != null) { if (pageNo < syncNodeTimestamps.Length && pageNo < pageTimestamps.Length && syncNodeTimestamps[pageNo] == pageTimestamps[pageNo]) { continue; } } lock (storage) { lock (storage.objectCache) { Page pg = storage.pool.getPage(pos); Bytes.pack8(txBuf, 0, pos); Array.Copy(pg.data, 0, txBuf, 8, Page.pageSize); storage.pool.unfix(pg); if (syncNodeTimestamps != null) { Bytes.pack4(txBuf, Page.pageSize + 8, pageNo < pageTimestamps.Length ? pageTimestamps[pageNo] : 0); } } } if (!Send(i, txBuf)) { return; } if (ack && pos == 0 && !Receive(i, rcBuf)) { Console.WriteLine("Failed to receive ACK from node " + replicas[i].host); return; } } Bytes.pack8(txBuf, 0, ReplicationSlaveStorageImpl.REPL_SYNC); Send(i, txBuf); }
internal int exportObject(ClassDescriptor desc, byte[] body, int offs, int indent) { ClassDescriptor.FieldDescriptor[] all = desc.allFields; for (int i = 0, n = all.Length; i < n; i++) { ClassDescriptor.FieldDescriptor fd = all[i]; FieldInfo f = fd.field; indentation(indent); String fieldName = exportIdentifier(fd.fieldName); writer.Write("<" + fieldName + ">"); switch (fd.type) { case ClassDescriptor.FieldType.tpBoolean: writer.Write(body[offs++] != 0?"1":"0"); break; case ClassDescriptor.FieldType.tpByte: writer.Write(System.Convert.ToString((byte)body[offs++])); break; case ClassDescriptor.FieldType.tpSByte: writer.Write(System.Convert.ToString((sbyte)body[offs++])); break; case ClassDescriptor.FieldType.tpChar: writer.Write(System.Convert.ToString((ushort)Bytes.unpack2(body, offs))); offs += 2; break; case ClassDescriptor.FieldType.tpShort: writer.Write(System.Convert.ToString((ushort)Bytes.unpack2(body, offs))); offs += 2; break; case ClassDescriptor.FieldType.tpUShort: writer.Write(System.Convert.ToString((ushort)Bytes.unpack2(body, offs))); offs += 2; break; case ClassDescriptor.FieldType.tpInt: writer.Write(System.Convert.ToString(Bytes.unpack4(body, offs))); offs += 4; break; case ClassDescriptor.FieldType.tpEnum: writer.Write(Enum.ToObject(f.FieldType, Bytes.unpack4(body, offs))); offs += 4; break; case ClassDescriptor.FieldType.tpUInt: writer.Write(System.Convert.ToString((uint)Bytes.unpack4(body, offs))); offs += 4; break; case ClassDescriptor.FieldType.tpLong: writer.Write(System.Convert.ToString(Bytes.unpack8(body, offs))); offs += 8; break; case ClassDescriptor.FieldType.tpULong: writer.Write(System.Convert.ToString((ulong)Bytes.unpack8(body, offs))); offs += 8; break; case ClassDescriptor.FieldType.tpFloat: writer.Write(System.Convert.ToString(Bytes.unpackF4(body, offs))); offs += 4; break; case ClassDescriptor.FieldType.tpDouble: writer.Write(System.Convert.ToString(Bytes.unpackF8(body, offs))); offs += 8; break; case ClassDescriptor.FieldType.tpGuid: writer.Write("\"" + Bytes.unpackGuid(body, offs) + "\""); offs += 16; break; case ClassDescriptor.FieldType.tpDecimal: writer.Write("\"" + Bytes.unpackDecimal(body, offs) + "\""); offs += 16; break; case ClassDescriptor.FieldType.tpString: offs = exportString(body, offs); break; case ClassDescriptor.FieldType.tpDate: { long msec = Bytes.unpack8(body, offs); offs += 8; if (msec >= 0) { writer.Write("\"" + new System.DateTime(msec) + "\""); } else { writer.Write("null"); } break; } case ClassDescriptor.FieldType.tpObject: exportRef(Bytes.unpack4(body, offs)); offs += 4; break; case ClassDescriptor.FieldType.tpValue: writer.Write('\n'); offs = exportObject(fd.valueDesc, body, offs, indent + 1); indentation(indent); break; #if SUPPORT_RAW_TYPE case ClassDescriptor.FieldType.tpRaw: #endif case ClassDescriptor.FieldType.tpArrayOfByte: case ClassDescriptor.FieldType.tpArrayOfSByte: offs = exportBinary(body, offs); break; case ClassDescriptor.FieldType.tpArrayOfBoolean: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + (body[offs++] != 0?"1":"0") + "</element>\n"); } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfChar: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + (Bytes.unpack2(body, offs) & 0xFFFF) + "</element>\n"); offs += 2; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfShort: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + Bytes.unpack2(body, offs) + "</element>\n"); offs += 2; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfUShort: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + (ushort)Bytes.unpack2(body, offs) + "</element>\n"); offs += 2; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfInt: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + Bytes.unpack4(body, offs) + "</element>\n"); offs += 4; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfEnum: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { Type elemType = f.FieldType.GetElementType(); writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + Enum.ToObject(elemType, Bytes.unpack4(body, offs)) + "</element>\n"); offs += 4; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfUInt: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + (uint)Bytes.unpack4(body, offs) + "</element>\n"); offs += 4; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfLong: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + Bytes.unpack8(body, offs) + "</element>\n"); offs += 8; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfULong: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + (ulong)Bytes.unpack8(body, offs) + "</element>\n"); offs += 8; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfFloat: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + Bytes.unpackF4(body, offs) + "</element>\n"); offs += 4; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfDouble: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + Bytes.unpackF8(body, offs) + "</element>\n"); offs += 8; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfDate: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>\"" + Bytes.unpackDate(body, offs) + "\"</element>\n"); offs += 8; } } break; } case ClassDescriptor.FieldType.tpArrayOfGuid: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { writer.Write("<element>\"" + Bytes.unpackGuid(body, offs) + "\"</element>\n"); offs += 16; } } break; } case ClassDescriptor.FieldType.tpArrayOfDecimal: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { writer.Write("<element>\"" + Bytes.unpackDecimal(body, offs) + "\"</element>\n"); offs += 16; } } break; } case ClassDescriptor.FieldType.tpArrayOfString: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>"); offs = exportString(body, offs); writer.Write("</element>\n"); } indentation(indent); } break; } case ClassDescriptor.FieldType.tpLink: case ClassDescriptor.FieldType.tpArrayOfObject: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); int oid = Bytes.unpack4(body, offs); if (oid != 0 && (exportedBitmap[oid >> 5] & (1 << (oid & 31))) == 0) { markedBitmap[oid >> 5] |= 1 << (oid & 31); } writer.Write("<element><ref id=\"" + oid + "\"/></element>\n"); offs += 4; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfValue: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>\n"); offs = exportObject(fd.valueDesc, body, offs, indent + 2); indentation(indent + 1); writer.Write("</element>\n"); } indentation(indent); } break; } #if SUPPORT_RAW_TYPE case ClassDescriptor.FieldType.tpArrayOfRaw: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>"); offs = exportBinary(body, offs); writer.Write("</element>\n"); } indentation(indent); } break; } #endif } writer.Write("</" + fieldName + ">\n"); } return(offs); }