void Connect() { try { socket = GetSocket(); if (socket == null) { HandleError(); return; } if (pageTimestamps != null && socket != null) { int size = pageTimestamps.Length; byte[] psBuf = new byte[4 + size * 4]; Bytes.pack4(psBuf, 0, size); for (int i = 0; i < size; i++) { Bytes.pack4(psBuf, (i + 1) * 4, pageTimestamps[i]); } socket.Send(psBuf, 0, psBuf.Length, SocketFlags.None); } return; } catch (SocketException x) { Console.WriteLine("Connection failure: " + x); } HandleError(); socket = null; }
public int packString(int offs, string s) { if (s == null) { extend(offs + 4); Bytes.pack4(arr, offs, -1); offs += 4; } else { int len = s.Length; if (encoding == null) { extend(offs + 4 + len * 2); Bytes.pack4(arr, offs, len); offs += 4; for (int i = 0; i < len; i++) { Bytes.pack2(arr, offs, (short)s[i]); offs += 2; } } else { byte[] bytes = encoding.GetBytes(s); extend(offs + 4 + bytes.Length); Bytes.pack4(arr, offs, -2 - bytes.Length); Array.Copy(bytes, 0, arr, offs + 4, bytes.Length); offs += 4 + bytes.Length; } } return(offs); }
internal void pack(Page pg, int i) { byte[] dst = pg.data; switch (key.type) { case ClassDescriptor.FieldType.tpBoolean: case ClassDescriptor.FieldType.tpSByte: case ClassDescriptor.FieldType.tpByte: dst[BtreePage.firstKeyOffs + i] = (byte)key.ival; break; case ClassDescriptor.FieldType.tpShort: case ClassDescriptor.FieldType.tpUShort: case ClassDescriptor.FieldType.tpChar: Bytes.pack2(dst, BtreePage.firstKeyOffs + i * 2, (short)key.ival); break; case ClassDescriptor.FieldType.tpInt: case ClassDescriptor.FieldType.tpUInt: case ClassDescriptor.FieldType.tpEnum: case ClassDescriptor.FieldType.tpObject: case ClassDescriptor.FieldType.tpOid: Bytes.pack4(dst, BtreePage.firstKeyOffs + i * 4, key.ival); break; case ClassDescriptor.FieldType.tpLong: case ClassDescriptor.FieldType.tpULong: case ClassDescriptor.FieldType.tpDate: Bytes.pack8(dst, BtreePage.firstKeyOffs + i * 8, key.lval); break; case ClassDescriptor.FieldType.tpFloat: Bytes.packF4(dst, BtreePage.firstKeyOffs + i * 4, (float)key.dval); break; case ClassDescriptor.FieldType.tpDouble: Bytes.packF8(dst, BtreePage.firstKeyOffs + i * 8, key.dval); break; case ClassDescriptor.FieldType.tpDecimal: Bytes.packDecimal(dst, BtreePage.firstKeyOffs + i * 16, key.dec); break; case ClassDescriptor.FieldType.tpGuid: Bytes.packGuid(dst, BtreePage.firstKeyOffs + i * 16, key.guid); break; default: Debug.Assert(false, "Invalid type"); break; } Bytes.pack4(dst, BtreePage.firstKeyOffs + (BtreePage.maxItems - i - 1) * 4, oid); }
public virtual void Write(long pos, byte[] buf) { lock (mutex) { 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; } pageTimestamps[pageNo] = ++timestamp; dirtyPageTimestampMap[pageNo >> (Page.pageSizeLog - 2 + 5)] |= 1 << ((pageNo >> (Page.pageSizeLog - 2)) & 31); } Bytes.pack8(txBuf, 0, pos); Array.Copy(buf, 0, txBuf, 8, buf.Length); if (pageTimestamps != null) { Bytes.pack4(txBuf, Page.pageSize + 8, timestamp); } for (int i = 0; i < replicas.Length; i++) { if (Send(i, txBuf)) { if (ack && pos == 0 && !Receive(i, rcBuf)) { Console.WriteLine("Failed to receive ACK from node " + replicas[i].host); } } } } file.Write(pos, buf); }
public void Sync() { if (pageTimestamps != null) { lock (mutex) { 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; } int offs = 0; while (beg < end) { Bytes.pack4(page, offs, pageTimestamps[beg]); beg += 1; offs += 4; } long pos = pageNo << Page.pageSizeLog; pageTimestampFile.Write(pos, page); } } dirtyPageTimestampMap[i] = 0; } } } pageTimestampFile.Sync(); } file.Sync(); }
public int packI4(int offs, int val) { extend(offs + 4); Bytes.pack4(arr, offs, val); return(offs + 4); }
private int packKeyPart(ByteBuffer buf, int dst, ClassDescriptor.FieldType type, object val) { switch (type) { case ClassDescriptor.FieldType.tpBoolean: dst = buf.packBool(dst, (bool)val); break; case ClassDescriptor.FieldType.tpByte: dst = buf.packI1(dst, (byte)val); break; case ClassDescriptor.FieldType.tpSByte: dst = buf.packI1(dst, (sbyte)val); break; case ClassDescriptor.FieldType.tpShort: dst = buf.packI2(dst, (short)val); break; case ClassDescriptor.FieldType.tpUShort: dst = buf.packI2(dst, (ushort)val); break; case ClassDescriptor.FieldType.tpChar: dst = buf.packI2(dst, (char)val); break; case ClassDescriptor.FieldType.tpInt: case ClassDescriptor.FieldType.tpOid: dst = buf.packI4(dst, (int)val); break; case ClassDescriptor.FieldType.tpEnum: dst = buf.packI4(dst, Convert.ToInt32(val)); break; case ClassDescriptor.FieldType.tpUInt: dst = buf.packI4(dst, (int)(uint)val); break; case ClassDescriptor.FieldType.tpObject: if (val != null) { Storage.MakePersistent(val); dst = buf.packI4(dst, Storage.GetOid(val)); } else { dst = buf.packI4(dst, 0); } break; case ClassDescriptor.FieldType.tpLong: dst = buf.packI8(dst, (long)val); break; case ClassDescriptor.FieldType.tpULong: dst = buf.packI8(dst, (long)(ulong)val); break; case ClassDescriptor.FieldType.tpDate: dst = buf.packDate(dst, (DateTime)val); break; case ClassDescriptor.FieldType.tpFloat: dst = buf.packF4(dst, (float)val); break; case ClassDescriptor.FieldType.tpDouble: dst = buf.packF8(dst, (double)val); break; case ClassDescriptor.FieldType.tpDecimal: dst = buf.packDecimal(dst, (decimal)val); break; case ClassDescriptor.FieldType.tpGuid: dst = buf.packGuid(dst, (Guid)val); break; case ClassDescriptor.FieldType.tpString: dst = buf.packString(dst, (string)val); break; case ClassDescriptor.FieldType.tpArrayOfByte: buf.extend(dst + 4); if (val != null) { byte[] arr = (byte[])val; int len = arr.Length; Bytes.pack4(buf.arr, dst, len); dst += 4; buf.extend(dst + len); Array.Copy(arr, 0, buf.arr, dst, len); dst += len; } else { Bytes.pack4(buf.arr, dst, 0); dst += 4; } break; default: Debug.Assert(false, "Invalid type"); break; } return(dst); }
internal static void setItem(Page pg, int index, int mask) { Bytes.pack4(pg.data, firstKeyOffs + index * 4, mask); }
internal static void setType(byte[] arr, int offs, int type) { Bytes.pack4(arr, offs + 4, type); }
internal static void setSize(byte[] arr, int offs, int size) { Bytes.pack4(arr, offs, size); }
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); } } }
public override void Write(long pos, byte[] buf) { file.Write(pos, buf); lock (mutex) { 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; } pageTimestamps[pageNo] = ++timestamp; dirtyPageTimestampMap[pageNo >> (Page.pageSizeLog - 2 + 5)] |= 1 << ((pageNo >> (Page.pageSizeLog - 2)) & 31); } } for (int i = 0; i < replicas.Length; i++) { if (replicas[i].socket != null) { byte[] data = new byte[txBuf.Length]; Bytes.pack8(data, 0, pos); Array.Copy(buf, 0, data, 8, buf.Length); if (pageTimestamps != null) { Bytes.pack4(data, Page.pageSize + 8, timestamp); } Parcel p = new Parcel(); p.data = data; p.pos = pos; p.host = i; lock (async) { buffered += data.Length; while (buffered > asyncBufSize && buffered != data.Length) { Monitor.Wait(async); } } lock (go) { if (head == null) { head = tail = p; } else { tail = tail.next = p; } Monitor.Pulse(go); } } } }
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); }