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;
 }
コード例 #2
0
 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);
 }
コード例 #3
0
        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();
 }
コード例 #6
0
 public int packI4(int offs, int val)
 {
     extend(offs + 4);
     Bytes.pack4(arr, offs, val);
     return(offs + 4);
 }
コード例 #7
0
        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);
        }
コード例 #8
0
 internal static void setItem(Page pg, int index, int mask)
 {
     Bytes.pack4(pg.data, firstKeyOffs + index * 4, mask);
 }
コード例 #9
0
 internal static void  setType(byte[] arr, int offs, int type)
 {
     Bytes.pack4(arr, offs + 4, type);
 }
コード例 #10
0
 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);
        }